Skip to content

Commit

Permalink
feat: support INT rules (#13)
Browse files Browse the repository at this point in the history
* feat: support INT rules

* feat: improve error message

* feat: improve error message
  • Loading branch information
rei1024 authored Oct 24, 2024
1 parent 48c6665 commit b3aadd0
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 26 deletions.
8 changes: 6 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,14 @@ <h2>Data</h2>
<h2>Note</h2>
<ul>
<li>
Outer-totalistic cellular automata are supported (without B0).
Outer-totalistic rules and isotropic non-totalistic rules are
supported (without B0).
</li>
<li>The supplied pattern must be a phase of an oscillator.</li>
<li>The maximum period that can be analyzed is 50,000.</li>
<li>
The maximum period that can be analyzed is 50,000 for outer
totalistic rules and 2,000 for isotropic non-totalistic rules.
</li>
</ul>
</section>
<section>
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"test": "vitest"
},
"devDependencies": {
"@ca-ts/algo": "npm:@jsr/ca-ts__algo@^0.5.0",
"@ca-ts/algo": "npm:@jsr/ca-ts__algo@^0.6.0",
"@ca-ts/rle": "npm:@jsr/ca-ts__rle@^0.8.0",
"@ca-ts/rule": "npm:@jsr/ca-ts__rule@^0.4.0",
"typescript": "^5.6.3",
Expand Down
17 changes: 14 additions & 3 deletions src/lib/WorldWithHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,16 @@ export class WorldWithHistory {
constructor({
cells,
bufferSize,
transition,
rule,
}: {
cells: { x: number; y: number }[];
transition: { birth: number[]; survive: number[] };
rule:
| {
transition: { birth: number[]; survive: number[] };
}
| {
intTransition: { birth: string[]; survive: string[] };
};
bufferSize?: number;
}) {
this.bufferSize = bufferSize ?? 32;
Expand All @@ -35,7 +41,12 @@ export class WorldWithHistory {
width: sizeX + this.bufferSize,
height: sizeY + this.bufferSize,
});
this.bitWorld.setRule(transition);
if ("transition" in rule && rule.transition !== undefined) {
this.bitWorld.setRule(rule.transition);
} else if ("intTransition" in rule && rule.intTransition !== undefined) {
this.bitWorld.setINTRule(rule.intTransition);
}

setCellsToBitGrid(this.bitWorld.bitGrid, cells, { sizeX, sizeY });

this.initialBitGrid = this.bitWorld.bitGrid.clone();
Expand Down
8 changes: 5 additions & 3 deletions src/lib/analyzeOscillator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ describe("analyzeOscillator", () => {
cells: parseRLE(`ooo`)
.cells.filter((x) => x.state === 1)
.map((x) => x.position),
transition: {
birth: [3],
survive: [2, 3],
rule: {
transition: {
birth: [3],
survive: [2, 3],
},
},
maxGeneration: 1000,
});
Expand Down
22 changes: 17 additions & 5 deletions src/lib/runOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,39 @@ import { WorldSizeError, WorldWithHistory } from "./WorldWithHistory";

export type RunOscillatorConfig = {
cells: { x: number; y: number }[];
transition: { birth: number[]; survive: number[] };
rule:
| {
transition: { birth: number[]; survive: number[] };
}
| {
intTransition: { birth: string[]; survive: string[] };
};
maxGeneration: number;
};

export type RunOscillatorResult = {
world: WorldWithHistory;
};

export class MaxGenerationError extends Error {
constructor(maxGen: number) {
super("Maximum generation is " + maxGen);
}
}

export function runOscillator(
config: RunOscillatorConfig
): RunOscillatorResult {
const { cells, transition, maxGeneration } = config;
const { cells, rule, maxGeneration } = config;
let bufferSize = 32;
for (let i = 0; i < 5; i++) {
try {
const world = new WorldWithHistory({ cells, bufferSize, transition });
const world = new WorldWithHistory({ cells, bufferSize, rule });
const result = world.run({
forceStop: () => world.getGen() >= maxGeneration,
});
if (result === "forced-stop") {
throw new Error("Max Generations.");
throw new MaxGenerationError(config.maxGeneration);
}
return {
world,
Expand All @@ -36,5 +48,5 @@ export function runOscillator(
}
}

throw new Error("Error: analyzeOscillator");
throw new Error("Error: Oscillator not detected");
}
24 changes: 16 additions & 8 deletions src/worker.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { analyzeOscillator, type AnalyzeResult } from "./lib/analyzeOscillator";
import { parseRLE } from "@ca-ts/rle";
import { parseRule } from "@ca-ts/rule";
import { MaxGenerationError } from "./lib/runOscillator";

export type WorkerRequestMessage = {
kind: "request-analyze";
Expand Down Expand Up @@ -37,14 +38,12 @@ function handleRequest(data: WorkerRequestMessage): WorkerResponseMessage {
};
}

if (rule.type !== "outer-totalistic") {
if (rule.type === "outer-totalistic" && rule.transition.birth.includes(0)) {
return {
kind: "response-error",
message: "Unsupported rule",
message: "Rules containing B0 is not supported",
};
}

if (rule.transition.birth.includes(0)) {
} else if (rule.type === "int" && rule.transition.birth.includes("0")) {
return {
kind: "response-error",
message: "Rules containing B0 is not supported",
Expand All @@ -58,16 +57,25 @@ function handleRequest(data: WorkerRequestMessage): WorkerResponseMessage {
message: "Empty pattern",
};
}

const maxGeneration = rule.type === "int" ? 2_000 : 50_000;
try {
const result = analyzeOscillator({
cells: cells,
transition: rule.transition,
maxGeneration: 50_000,
rule:
rule.type === "int"
? { intTransition: rule.transition }
: { transition: rule.transition },
maxGeneration: maxGeneration,
});
return { kind: "response-analyzed", data: result };
} catch (error) {
console.error(error);
if (error instanceof MaxGenerationError) {
return {
kind: "response-error",
message: `maximum period is ${maxGeneration.toLocaleString()}`,
};
}
return {
kind: "response-error",
message: "Analyzation Error",
Expand Down

0 comments on commit b3aadd0

Please sign in to comment.