redscript-mc 2.2.1 → 2.3.0

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.
Files changed (43) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +18 -2
  3. package/dist/src/__tests__/tuner/engine.test.d.ts +4 -0
  4. package/dist/src/__tests__/tuner/engine.test.js +232 -0
  5. package/dist/src/tuner/adapters/ln-polynomial.d.ts +23 -0
  6. package/dist/src/tuner/adapters/ln-polynomial.js +142 -0
  7. package/dist/src/tuner/adapters/sqrt-newton.d.ts +28 -0
  8. package/dist/src/tuner/adapters/sqrt-newton.js +125 -0
  9. package/dist/src/tuner/cli.d.ts +5 -0
  10. package/dist/src/tuner/cli.js +168 -0
  11. package/dist/src/tuner/engine.d.ts +17 -0
  12. package/dist/src/tuner/engine.js +215 -0
  13. package/dist/src/tuner/metrics.d.ts +15 -0
  14. package/dist/src/tuner/metrics.js +51 -0
  15. package/dist/src/tuner/simulator.d.ts +35 -0
  16. package/dist/src/tuner/simulator.js +78 -0
  17. package/dist/src/tuner/types.d.ts +32 -0
  18. package/dist/src/tuner/types.js +6 -0
  19. package/docs/STDLIB_ROADMAP.md +142 -0
  20. package/editors/vscode/package-lock.json +3 -3
  21. package/editors/vscode/package.json +1 -1
  22. package/package.json +1 -1
  23. package/src/__tests__/tuner/engine.test.ts +260 -0
  24. package/src/stdlib/bigint.mcrs +155 -192
  25. package/src/stdlib/bits.mcrs +158 -0
  26. package/src/stdlib/color.mcrs +160 -0
  27. package/src/stdlib/geometry.mcrs +124 -0
  28. package/src/stdlib/list.mcrs +125 -0
  29. package/src/stdlib/math.mcrs +90 -0
  30. package/src/stdlib/math_hp.mcrs +65 -0
  31. package/src/stdlib/random.mcrs +67 -0
  32. package/src/stdlib/signal.mcrs +112 -0
  33. package/src/stdlib/vec.mcrs +27 -0
  34. package/src/tuner/adapters/ln-polynomial.ts +147 -0
  35. package/src/tuner/adapters/sqrt-newton.ts +135 -0
  36. package/src/tuner/cli.ts +158 -0
  37. package/src/tuner/engine.ts +272 -0
  38. package/src/tuner/metrics.ts +66 -0
  39. package/src/tuner/simulator.ts +69 -0
  40. package/src/tuner/types.ts +44 -0
  41. package/docs/ARCHITECTURE.zh.md +0 -1088
  42. package/docs/COMPILATION_STATS.md +0 -142
  43. package/docs/IMPLEMENTATION_GUIDE.md +0 -512
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ /**
3
+ * CLI entry point for `redscript tune`.
4
+ * Usage: redscript tune --adapter <name> [--budget N] [--out path]
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const engine_1 = require("./engine");
43
+ const ln_polynomial_1 = require("./adapters/ln-polynomial");
44
+ const sqrt_newton_1 = require("./adapters/sqrt-newton");
45
+ const ADAPTERS = {
46
+ 'ln-polynomial': ln_polynomial_1.lnPolynomialAdapter,
47
+ 'sqrt-newton': sqrt_newton_1.sqrtNewtonAdapter,
48
+ };
49
+ function printUsage() {
50
+ console.log(`Usage: redscript tune --adapter <name> [--budget N] [--out path]
51
+
52
+ Available adapters:
53
+ ${Object.entries(ADAPTERS)
54
+ .map(([name, a]) => ` ${name.padEnd(20)} ${a.description}`)
55
+ .join('\n')}
56
+
57
+ Options:
58
+ --adapter <name> Adapter to use (required)
59
+ --budget <N> Max optimizer iterations (default: 10000)
60
+ --out <path> Output .mcrs file path (optional)
61
+ `);
62
+ }
63
+ function parseArgs(args) {
64
+ const result = { budget: 10000, strategy: 'nm' };
65
+ for (let i = 0; i < args.length; i++) {
66
+ if (args[i] === '--adapter' && args[i + 1]) {
67
+ result.adapter = args[++i];
68
+ }
69
+ else if (args[i] === '--budget' && args[i + 1]) {
70
+ result.budget = parseInt(args[++i], 10);
71
+ }
72
+ else if (args[i] === '--out' && args[i + 1]) {
73
+ result.out = args[++i];
74
+ }
75
+ else if (args[i] === '--strategy' && args[i + 1]) {
76
+ const s = args[++i];
77
+ if (s === 'nm' || s === 'sa')
78
+ result.strategy = s;
79
+ }
80
+ }
81
+ return result;
82
+ }
83
+ function renderProgressBar(fraction, width = 30) {
84
+ const filled = Math.round(fraction * width);
85
+ const bar = '█'.repeat(filled) + '░'.repeat(width - filled);
86
+ return `[${bar}]`;
87
+ }
88
+ async function main() {
89
+ // Skip 'node', 'ts-node', 'cli.ts' etc from argv
90
+ const rawArgs = process.argv.slice(2);
91
+ // Support `redscript tune` prefix (first arg might be 'tune')
92
+ const args = rawArgs[0] === 'tune' ? rawArgs.slice(1) : rawArgs;
93
+ if (args.includes('--help') || args.includes('-h') || args.length === 0) {
94
+ printUsage();
95
+ process.exit(0);
96
+ }
97
+ const { adapter: adapterName, budget, out, strategy } = parseArgs(args);
98
+ if (!adapterName) {
99
+ console.error('Error: --adapter is required');
100
+ printUsage();
101
+ process.exit(1);
102
+ }
103
+ const adapter = ADAPTERS[adapterName];
104
+ if (!adapter) {
105
+ console.error(`Error: unknown adapter "${adapterName}"`);
106
+ console.error(`Available: ${Object.keys(ADAPTERS).join(', ')}`);
107
+ process.exit(1);
108
+ }
109
+ console.log(`\nredscript tune — ${adapter.name}`);
110
+ console.log(`Description: ${adapter.description}`);
111
+ console.log(`Strategy: ${strategy === 'sa' ? 'Simulated Annealing' : 'Nelder-Mead'}`);
112
+ console.log(`Budget: ${budget} iterations`);
113
+ console.log(`Parameters: ${adapter.params.map(p => p.name).join(', ')}\n`);
114
+ let lastProgress = 0;
115
+ const startTime = Date.now();
116
+ const searchFn = strategy === 'sa' ? engine_1.searchSA : engine_1.search;
117
+ const result = searchFn(adapter, budget, (iteration, bestError) => {
118
+ const fraction = iteration / budget;
119
+ const bar = renderProgressBar(fraction);
120
+ const errorStr = isFinite(bestError) ? bestError.toFixed(6) : 'Inf';
121
+ process.stdout.write(`\r ${bar} ${(fraction * 100).toFixed(1)}% iter=${iteration} best_max_error=${errorStr} `);
122
+ lastProgress = iteration;
123
+ });
124
+ const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
125
+ process.stdout.write('\n');
126
+ console.log(`\n${'─'.repeat(60)}`);
127
+ console.log(`Optimization complete in ${elapsed}s`);
128
+ console.log(`Budget used: ${result.budgetUsed}/${budget} iterations`);
129
+ console.log(`\nResults:`);
130
+ console.log(` max_error : ${result.maxError.toFixed(8)}`);
131
+ console.log(` mae : ${result.mae.toFixed(8)}`);
132
+ console.log(` rmse : ${result.rmse.toFixed(8)}`);
133
+ console.log(`\nBest parameters:`);
134
+ for (const [k, v] of Object.entries(result.params)) {
135
+ console.log(` ${k.padEnd(12)} = ${v}`);
136
+ }
137
+ // Estimate command count (rough: ~4 cmds per param + 10 overhead)
138
+ const estimatedCmds = adapter.params.length * 4 + 15;
139
+ const meta = {
140
+ maxError: result.maxError,
141
+ mae: result.mae,
142
+ rmse: result.rmse,
143
+ estimatedCmds,
144
+ tuneDate: new Date().toISOString().split('T')[0],
145
+ budgetUsed: result.budgetUsed,
146
+ };
147
+ const code = adapter.generateCode(result.params, meta);
148
+ if (out) {
149
+ const outPath = path.resolve(out);
150
+ const dir = path.dirname(outPath);
151
+ if (!fs.existsSync(dir)) {
152
+ fs.mkdirSync(dir, { recursive: true });
153
+ }
154
+ fs.writeFileSync(outPath, code, 'utf8');
155
+ console.log(`\nWrote: ${outPath}`);
156
+ }
157
+ else {
158
+ console.log(`\n${'─'.repeat(60)}`);
159
+ console.log('Generated code:');
160
+ console.log('─'.repeat(60));
161
+ console.log(code);
162
+ }
163
+ }
164
+ main().catch(err => {
165
+ console.error(err);
166
+ process.exit(1);
167
+ });
168
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Nelder-Mead simplex optimization engine for hyperparameter tuning.
3
+ * Suitable for continuous parameter spaces without gradient information.
4
+ * Supports mixed-integer parameters.
5
+ */
6
+ import { TunerAdapter, SearchResult } from './types';
7
+ export type ProgressCallback = (iteration: number, bestError: number) => void;
8
+ /**
9
+ * Run Nelder-Mead optimization.
10
+ */
11
+ export declare function search(adapter: TunerAdapter, budget?: number, onProgress?: ProgressCallback): SearchResult;
12
+ /**
13
+ * Simulated Annealing search strategy.
14
+ * More robust than Nelder-Mead for integer parameters and multimodal objectives.
15
+ * Uses 3 independent restarts, taking the global best.
16
+ */
17
+ export declare function searchSA(adapter: TunerAdapter, budget: number, onProgress?: ProgressCallback): SearchResult;
@@ -0,0 +1,215 @@
1
+ "use strict";
2
+ /**
3
+ * Nelder-Mead simplex optimization engine for hyperparameter tuning.
4
+ * Suitable for continuous parameter spaces without gradient information.
5
+ * Supports mixed-integer parameters.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.search = search;
9
+ exports.searchSA = searchSA;
10
+ const metrics_1 = require("./metrics");
11
+ /**
12
+ * Apply integer constraints to parameters.
13
+ */
14
+ function applyIntegerConstraints(coords, specs) {
15
+ return coords.map((v, i) => {
16
+ const spec = specs[i];
17
+ // Clamp to range
18
+ const clamped = Math.max(spec.range[0], Math.min(spec.range[1], v));
19
+ return spec.integer ? Math.round(clamped) : clamped;
20
+ });
21
+ }
22
+ /**
23
+ * Convert coordinate array to params record.
24
+ */
25
+ function coordsToParams(coords, specs) {
26
+ const params = {};
27
+ for (let i = 0; i < specs.length; i++) {
28
+ params[specs[i].name] = coords[i];
29
+ }
30
+ return params;
31
+ }
32
+ /**
33
+ * Evaluate a point using the adapter.
34
+ */
35
+ function scorePoint(coords, specs, adapter) {
36
+ const constrained = applyIntegerConstraints(coords, specs);
37
+ const params = coordsToParams(constrained, specs);
38
+ const metrics = (0, metrics_1.evaluate)(adapter, params);
39
+ return metrics.maxError;
40
+ }
41
+ /**
42
+ * Run Nelder-Mead optimization.
43
+ */
44
+ function search(adapter, budget = 10000, onProgress) {
45
+ const specs = adapter.params;
46
+ const n = specs.length;
47
+ if (n === 0) {
48
+ // No params to optimize
49
+ const params = coordsToParams([], specs);
50
+ const metrics = (0, metrics_1.evaluate)(adapter, params);
51
+ return {
52
+ params,
53
+ maxError: metrics.maxError,
54
+ mae: metrics.mae,
55
+ rmse: metrics.rmse,
56
+ budgetUsed: 0,
57
+ };
58
+ }
59
+ // Nelder-Mead parameters
60
+ const alpha = 1.0; // reflection
61
+ const gamma = 2.0; // expansion
62
+ const rho = 0.5; // contraction
63
+ const sigma = 0.5; // shrink
64
+ // Initialize simplex with n+1 points
65
+ const simplex = [];
66
+ // Start point: midpoint of each parameter range
67
+ const startCoords = specs.map(s => (s.range[0] + s.range[1]) / 2);
68
+ simplex.push({
69
+ coords: startCoords,
70
+ score: scorePoint(startCoords, specs, adapter),
71
+ });
72
+ // Generate remaining n points by perturbing each dimension
73
+ for (let i = 0; i < n; i++) {
74
+ const coords = [...startCoords];
75
+ const span = specs[i].range[1] - specs[i].range[0];
76
+ // Perturb by 20% of the range
77
+ coords[i] = startCoords[i] + span * 0.2;
78
+ simplex.push({
79
+ coords,
80
+ score: scorePoint(coords, specs, adapter),
81
+ });
82
+ }
83
+ let iteration = 0;
84
+ while (iteration < budget) {
85
+ // Sort simplex by score (ascending = better)
86
+ simplex.sort((a, b) => a.score - b.score);
87
+ const best = simplex[0];
88
+ const worst = simplex[n];
89
+ const secondWorst = simplex[n - 1];
90
+ if (onProgress && iteration % 100 === 0) {
91
+ onProgress(iteration, best.score);
92
+ }
93
+ // Check convergence: if all scores are the same, we're stuck
94
+ if (simplex[n].score - simplex[0].score < 1e-15 &&
95
+ iteration > 100) {
96
+ break;
97
+ }
98
+ // Compute centroid of all but worst
99
+ const centroid = new Array(n).fill(0);
100
+ for (let i = 0; i < n; i++) {
101
+ for (let j = 0; j < n; j++) {
102
+ centroid[j] += simplex[i].coords[j] / n;
103
+ }
104
+ }
105
+ // Reflection
106
+ const reflected = centroid.map((c, j) => c + alpha * (c - worst.coords[j]));
107
+ const reflectedScore = scorePoint(reflected, specs, adapter);
108
+ iteration++;
109
+ if (reflectedScore < best.score) {
110
+ // Expansion
111
+ const expanded = centroid.map((c, j) => c + gamma * (reflected[j] - c));
112
+ const expandedScore = scorePoint(expanded, specs, adapter);
113
+ iteration++;
114
+ if (expandedScore < reflectedScore) {
115
+ simplex[n] = { coords: expanded, score: expandedScore };
116
+ }
117
+ else {
118
+ simplex[n] = { coords: reflected, score: reflectedScore };
119
+ }
120
+ }
121
+ else if (reflectedScore < secondWorst.score) {
122
+ simplex[n] = { coords: reflected, score: reflectedScore };
123
+ }
124
+ else {
125
+ // Contraction
126
+ const useReflected = reflectedScore < worst.score;
127
+ const contractionBase = useReflected ? reflected : worst.coords;
128
+ const contracted = centroid.map((c, j) => c + rho * (contractionBase[j] - c));
129
+ const contractedScore = scorePoint(contracted, specs, adapter);
130
+ iteration++;
131
+ if (contractedScore < (useReflected ? reflectedScore : worst.score)) {
132
+ simplex[n] = { coords: contracted, score: contractedScore };
133
+ }
134
+ else {
135
+ // Shrink
136
+ for (let i = 1; i <= n; i++) {
137
+ simplex[i].coords = simplex[0].coords.map((c, j) => c + sigma * (simplex[i].coords[j] - c));
138
+ simplex[i].score = scorePoint(simplex[i].coords, specs, adapter);
139
+ iteration++;
140
+ }
141
+ }
142
+ }
143
+ }
144
+ // Sort final simplex
145
+ simplex.sort((a, b) => a.score - b.score);
146
+ const bestCoords = applyIntegerConstraints(simplex[0].coords, specs);
147
+ const bestParams = coordsToParams(bestCoords, specs);
148
+ const finalMetrics = (0, metrics_1.evaluate)(adapter, bestParams);
149
+ return {
150
+ params: bestParams,
151
+ maxError: finalMetrics.maxError,
152
+ mae: finalMetrics.mae,
153
+ rmse: finalMetrics.rmse,
154
+ budgetUsed: iteration,
155
+ };
156
+ }
157
+ /**
158
+ * Simulated Annealing search strategy.
159
+ * More robust than Nelder-Mead for integer parameters and multimodal objectives.
160
+ * Uses 3 independent restarts, taking the global best.
161
+ */
162
+ function searchSA(adapter, budget, onProgress) {
163
+ const RESTARTS = 3;
164
+ const budgetPerRun = Math.floor(budget / RESTARTS);
165
+ let globalBest = null;
166
+ for (let r = 0; r < RESTARTS; r++) {
167
+ // Random initialisation within param ranges
168
+ let current = {};
169
+ for (const p of adapter.params) {
170
+ current[p.name] = p.range[0] + Math.random() * (p.range[1] - p.range[0]);
171
+ if (p.integer)
172
+ current[p.name] = Math.round(current[p.name]);
173
+ }
174
+ // T: 1.0 → 1e-4 over budgetPerRun iterations
175
+ let T = 1.0;
176
+ const cooling = Math.pow(1e-4, 1 / budgetPerRun);
177
+ let currentError = (0, metrics_1.evaluate)(adapter, current).maxError;
178
+ let bestLocal = { params: { ...current }, error: currentError };
179
+ for (let i = 0; i < budgetPerRun; i++) {
180
+ T *= cooling;
181
+ // Perturb one random param by ±10% of its range
182
+ const neighbor = { ...current };
183
+ const spec = adapter.params[Math.floor(Math.random() * adapter.params.length)];
184
+ const step = (spec.range[1] - spec.range[0]) * 0.1 * (Math.random() * 2 - 1);
185
+ neighbor[spec.name] = Math.max(spec.range[0], Math.min(spec.range[1], neighbor[spec.name] + step));
186
+ if (spec.integer)
187
+ neighbor[spec.name] = Math.round(neighbor[spec.name]);
188
+ const neighborError = (0, metrics_1.evaluate)(adapter, neighbor).maxError;
189
+ const delta = neighborError - currentError;
190
+ if (delta < 0 || Math.random() < Math.exp(-delta / T)) {
191
+ current = neighbor;
192
+ currentError = neighborError;
193
+ }
194
+ if (currentError < bestLocal.error) {
195
+ bestLocal = { params: { ...current }, error: currentError };
196
+ }
197
+ const globalIter = r * budgetPerRun + i;
198
+ if (onProgress && globalIter % 100 === 0) {
199
+ onProgress(globalIter, globalBest?.error ?? bestLocal.error);
200
+ }
201
+ }
202
+ if (!globalBest || bestLocal.error < globalBest.error) {
203
+ globalBest = bestLocal;
204
+ }
205
+ }
206
+ const finalMetrics = (0, metrics_1.evaluate)(adapter, globalBest.params);
207
+ return {
208
+ params: globalBest.params,
209
+ maxError: finalMetrics.maxError,
210
+ mae: finalMetrics.mae,
211
+ rmse: finalMetrics.rmse,
212
+ budgetUsed: budget,
213
+ };
214
+ }
215
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Error metrics for tuner adapters.
3
+ */
4
+ import { TunerAdapter } from './types';
5
+ export interface EvaluationResult {
6
+ maxError: number;
7
+ mae: number;
8
+ rmse: number;
9
+ }
10
+ /**
11
+ * Evaluate an adapter with given params across all sample inputs.
12
+ * Returns max_error, mae, and rmse relative to the reference function.
13
+ * Penalizes overflow by returning Infinity for all metrics.
14
+ */
15
+ export declare function evaluate(adapter: TunerAdapter, params: Record<string, number>): EvaluationResult;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * Error metrics for tuner adapters.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.evaluate = evaluate;
7
+ /**
8
+ * Evaluate an adapter with given params across all sample inputs.
9
+ * Returns max_error, mae, and rmse relative to the reference function.
10
+ * Penalizes overflow by returning Infinity for all metrics.
11
+ */
12
+ function evaluate(adapter, params) {
13
+ const inputs = adapter.sampleInputs();
14
+ let maxError = 0;
15
+ let sumAbsError = 0;
16
+ let sumSqError = 0;
17
+ let count = 0;
18
+ for (const input of inputs) {
19
+ const simResult = adapter.simulate(input, params);
20
+ const refResult = adapter.reference(input);
21
+ // Penalize overflow or NaN
22
+ if (!isFinite(simResult) || isNaN(simResult)) {
23
+ return { maxError: Infinity, mae: Infinity, rmse: Infinity };
24
+ }
25
+ if (!isFinite(refResult) || isNaN(refResult)) {
26
+ continue; // skip degenerate reference points
27
+ }
28
+ // Both are in fixed-point; normalize to compare in floating-point units
29
+ const SCALE = 10000;
30
+ const simFloat = simResult / SCALE;
31
+ const refFloat = refResult / SCALE;
32
+ const absError = Math.abs(simFloat - refFloat);
33
+ if (absError === Infinity) {
34
+ return { maxError: Infinity, mae: Infinity, rmse: Infinity };
35
+ }
36
+ if (absError > maxError)
37
+ maxError = absError;
38
+ sumAbsError += absError;
39
+ sumSqError += absError * absError;
40
+ count++;
41
+ }
42
+ if (count === 0) {
43
+ return { maxError: Infinity, mae: Infinity, rmse: Infinity };
44
+ }
45
+ return {
46
+ maxError,
47
+ mae: sumAbsError / count,
48
+ rmse: Math.sqrt(sumSqError / count),
49
+ };
50
+ }
51
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * MC int32 arithmetic simulation.
3
+ * Minecraft scoreboards use 32-bit signed integers (Java int).
4
+ */
5
+ export declare const INT32_MAX = 2147483647;
6
+ export declare const INT32_MIN = -2147483648;
7
+ /**
8
+ * Truncate to int32 using JavaScript bitwise (same as Java int cast).
9
+ */
10
+ export declare function i32(x: number): number;
11
+ /**
12
+ * Check if a value is within int32 range (before truncation).
13
+ */
14
+ export declare function isOverflow(x: number): boolean;
15
+ /**
16
+ * Fixed-point multiply: compute i32(i32(a * b) / scale).
17
+ * Returns Infinity if overflow is detected before truncation.
18
+ */
19
+ export declare function fixedMul(a: number, b: number, scale: number): number;
20
+ /**
21
+ * Safe i32 addition - returns Infinity on overflow.
22
+ */
23
+ export declare function safeAdd(a: number, b: number): number;
24
+ /**
25
+ * Safe i32 subtraction - returns Infinity on overflow.
26
+ */
27
+ export declare function safeSub(a: number, b: number): number;
28
+ /**
29
+ * Safe i32 multiply - returns Infinity on overflow.
30
+ */
31
+ export declare function safeMul(a: number, b: number): number;
32
+ /**
33
+ * Safe i32 division - returns Infinity on division by zero.
34
+ */
35
+ export declare function safeDiv(a: number, b: number): number;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /**
3
+ * MC int32 arithmetic simulation.
4
+ * Minecraft scoreboards use 32-bit signed integers (Java int).
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.INT32_MIN = exports.INT32_MAX = void 0;
8
+ exports.i32 = i32;
9
+ exports.isOverflow = isOverflow;
10
+ exports.fixedMul = fixedMul;
11
+ exports.safeAdd = safeAdd;
12
+ exports.safeSub = safeSub;
13
+ exports.safeMul = safeMul;
14
+ exports.safeDiv = safeDiv;
15
+ exports.INT32_MAX = 2147483647;
16
+ exports.INT32_MIN = -2147483648;
17
+ /**
18
+ * Truncate to int32 using JavaScript bitwise (same as Java int cast).
19
+ */
20
+ function i32(x) {
21
+ return x | 0;
22
+ }
23
+ /**
24
+ * Check if a value is within int32 range (before truncation).
25
+ */
26
+ function isOverflow(x) {
27
+ return x > exports.INT32_MAX || x < exports.INT32_MIN || !isFinite(x) || isNaN(x);
28
+ }
29
+ /**
30
+ * Fixed-point multiply: compute i32(i32(a * b) / scale).
31
+ * Returns Infinity if overflow is detected before truncation.
32
+ */
33
+ function fixedMul(a, b, scale) {
34
+ const product = a * b;
35
+ if (isOverflow(product))
36
+ return Infinity;
37
+ const truncated = i32(product);
38
+ const divided = truncated / scale;
39
+ if (isOverflow(divided))
40
+ return Infinity;
41
+ return i32(divided);
42
+ }
43
+ /**
44
+ * Safe i32 addition - returns Infinity on overflow.
45
+ */
46
+ function safeAdd(a, b) {
47
+ const result = a + b;
48
+ if (isOverflow(result))
49
+ return Infinity;
50
+ return i32(result);
51
+ }
52
+ /**
53
+ * Safe i32 subtraction - returns Infinity on overflow.
54
+ */
55
+ function safeSub(a, b) {
56
+ const result = a - b;
57
+ if (isOverflow(result))
58
+ return Infinity;
59
+ return i32(result);
60
+ }
61
+ /**
62
+ * Safe i32 multiply - returns Infinity on overflow.
63
+ */
64
+ function safeMul(a, b) {
65
+ const result = a * b;
66
+ if (isOverflow(result))
67
+ return Infinity;
68
+ return i32(result);
69
+ }
70
+ /**
71
+ * Safe i32 division - returns Infinity on division by zero.
72
+ */
73
+ function safeDiv(a, b) {
74
+ if (b === 0)
75
+ return Infinity;
76
+ return i32(a / b);
77
+ }
78
+ //# sourceMappingURL=simulator.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Shared types for the redscript tuner system.
3
+ */
4
+ export interface ParamSpec {
5
+ name: string;
6
+ range: [number, number];
7
+ integer: boolean;
8
+ }
9
+ export interface ResultMeta {
10
+ maxError: number;
11
+ mae: number;
12
+ rmse: number;
13
+ estimatedCmds: number;
14
+ tuneDate: string;
15
+ budgetUsed: number;
16
+ }
17
+ export interface TunerAdapter {
18
+ name: string;
19
+ description: string;
20
+ params: ParamSpec[];
21
+ simulate(input: number, params: Record<string, number>): number;
22
+ reference(input: number): number;
23
+ sampleInputs(): number[];
24
+ generateCode(params: Record<string, number>, meta: ResultMeta): string;
25
+ }
26
+ export interface SearchResult {
27
+ params: Record<string, number>;
28
+ maxError: number;
29
+ mae: number;
30
+ rmse: number;
31
+ budgetUsed: number;
32
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Shared types for the redscript tuner system.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ //# sourceMappingURL=types.js.map