-# Cachex AI
+# Cachex Arena
-A game-playing AI agent for **Cachex**, a hex-based connection game, built for the University of Melbourne **COMP30024 Artificial Intelligence** project (Semester 1, 2022).
+**Play our COMP30024 minimax agent, watch AI vs AI, and step through our A\* search, in the browser.**
-[](https://www.python.org/)
-[](https://handbook.unimelb.edu.au/2022/subjects/comp30024)
-[](#approach)
-[](LICENSE)
+[](https://github.com/rNLKJA/Cachex-AI/actions/workflows/ci.yml)
+[](https://nextjs.org/)
+[](https://www.typescriptlang.org/)
+[](https://handbook.unimelb.edu.au/2022/subjects/comp30024)
+[](LICENSE)
+
+**Live demo: [cachex-ai.vercel.app](https://cachex-ai.vercel.app)**
+ Our A* search came up empty: the page you asked for doesn't exist or has moved.
+
+
+
+
+ );
+}
diff --git a/web/src/app/opengraph-image.tsx b/web/src/app/opengraph-image.tsx
new file mode 100644
index 0000000..18c632b
--- /dev/null
+++ b/web/src/app/opengraph-image.tsx
@@ -0,0 +1,65 @@
+import { ImageResponse } from "next/og";
+
+export const alt = "Cachex Arena: play the COMP30024 minimax agent";
+export const size = { width: 1200, height: 630 };
+export const contentType = "image/png";
+
+function hexPoints(cx: number, cy: number, r: number) {
+ return Array.from({ length: 6 }, (_, k) => {
+ const a = (Math.PI / 180) * (60 * k - 90);
+ return `${(cx + r * Math.cos(a)).toFixed(1)},${(cy + r * Math.sin(a)).toFixed(1)}`;
+ }).join(" ");
+}
+
+export default function OpengraphImage() {
+ const n = 6;
+ const R = 34;
+ const w = Math.sqrt(3) * R;
+ const red = new Set(["0,2", "1,2", "2,1", "3,1", "4,1", "5,0"]);
+ const blue = new Set(["2,3", "3,2", "1,4", "4,3", "2,0"]);
+ const hexes = [];
+ for (let r = 0; r < n; r++) {
+ for (let q = 0; q < n; q++) {
+ const key = `${r},${q}`;
+ const fill = red.has(key) ? "#f0524f" : blue.has(key) ? "#4f9cf0" : "#2a2940";
+ hexes.push(
+ ,
+ );
+ }
+ }
+ return new ImageResponse(
+
+
+
+ COMP30024 · UNIMELB · 2022
+
+
+ Cachex Arena
+
+
+ Play our minimax agent, watch AI vs AI, and step through A* search.
+
+
+
+
,
+ size,
+ );
+}
diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx
new file mode 100644
index 0000000..e8cbcc0
--- /dev/null
+++ b/web/src/app/page.tsx
@@ -0,0 +1,503 @@
+import { ArrowRight, Bot, BrainCircuit, GitBranch, Route, Swords } from "lucide-react";
+import Link from "next/link";
+
+import { HexBoard } from "@/components/board/hex-board";
+import { StaticBoard } from "@/components/landing/static-board";
+import { GitHubIcon } from "@/components/layout/github-icon";
+import { ColourDot } from "@/components/play/primitives";
+import { Button } from "@/components/ui/button";
+import { FEATURES } from "@/lib/agent/evaluation";
+import { TARGET_RATES } from "@/lib/agent/player";
+import { deterministicSelfPlay } from "@/lib/agent/self-play";
+import benchmark from "@/lib/data/agent-benchmark.json";
+import { SITE } from "@/lib/site";
+
+export default function HomePage() {
+ const { game } = deterministicSelfPlay(7);
+ const cells: ("red" | "blue" | null)[] = [];
+ for (let r = 0; r < 7; r++) for (let q = 0; q < 7; q++) cells.push(game.board.get(r, q));
+ const winning = game.result?.kind === "win" ? game.result.cluster : null;
+ const last = game.log.at(-1)!;
+ const lastMove = last.action[0] === "PLACE" ? ([last.action[1], last.action[2]] as const) : null;
+
+ const totals = benchmark.results.reduce(
+ (acc, r) => ({ wins: acc.wins + r.wins, games: acc.games + r.games }),
+ { wins: 0, games: 0 },
+ );
+ const winRate = Math.round((totals.wins / totals.games) * 100);
+
+ return (
+
+ {/* Hero */}
+
+
+
+ {SITE.subject.code} · {SITE.subject.name} · University of Melbourne
+
+
+ Cachex
+
+
+ Arena
+
+
+
+ In 2022 we built a game-playing agent for{" "}
+ Cachex, a Hex-like race to connect opposite
+ edges of a hexagonal board, with captures and a first-move steal. Here it is again,
+ ported line by line from Python to run in your browser.
+
+
+
+
+
+
+
+
+
+
+
+ A real game: the ported agent playing itself on 7 × 7. Red wins in {game.nturns} turns.
+
+
+
+
+ {/* Rules */}
+
+
+
+ Two players take turns placing a tile on any empty hex. Whoever links their two edges
+ first wins.
+
+
+
+
+
+
+
+
+
+
+ Before
+
+
+
+
+
+ After Blue plays
+
+
+
+
+
+
+
+
+
+
+
+ {/* Coursework */}
+
+
+ The project came in two parts. We have paraphrased the brief here; the original
+ specification is not reproduced.
+
+
+
+
+
+
Part A · Search
+
+
+ The task: given a board with some
+ occupied cells, find a shortest chain of empty cells from a start to a goal using A*
+ with an admissible heuristic, and print its length and cells.
+
+
+ What we built: a{" "}
+ CachexBoard of{" "}
+ HexNodes with a priority-queue A* over the
+ six hex neighbours, Minkowski heuristics (Manhattan or Euclidean), and an optional
+ colour that blocks the search. A notebook experiment compared the heuristics on
+ hundreds of random boards.
+
+
+
+
+
+
+
Part B · Game-playing agent
+
+
+ The task: write a player the
+ subject's referee could run against random, greedy and search-based opponents,
+ within time and memory limits.
+
+
+
+ Minimax with alpha-beta pruning, Red
+ maximising and Blue minimising.
+
+
+ Dynamic depth: depth 1 while at least{" "}
+ {TARGET_RATES[0] * 100}% of cells are empty, then 2, 3 and 4 below{" "}
+ {TARGET_RATES[0] * 100}%, {TARGET_RATES[1] * 100}% and {TARGET_RATES[2] * 100}%.
+
+
+ Opening book for the first two turns,
+ and an instant-win check before any
+ search.
+
+
+
+
+
+
+
+
The evaluation function
+
+ Six hand-tuned features from weights.json, scored
+ from Red's point of view (Red's count adds, Blue's subtracts).
+
+
+ The agent and search results come from running the original Python, unchanged, with the
+ subject's referee. The port is then checked against those same runs.
+
+
+
+
+
+
+
+
+
Agent _4399 vs the random baseline
+
+ {benchmark.results[0].games} seeded games per row, generated by{" "}
+ scripts/benchmark_agent.py.
+
+ Parity fixtures are produced by running the original code with{" "}
+ uv.
+
+
+
+
Source and integrity
+
+ The original submission is preserved unchanged in the repository's{" "}
+ coursework/ folder for reference. If you are taking{" "}
+ {SITE.subject.code}, please respect academic integrity and do not copy it.
+
+ Paint tiles, move the start and goal, and watch our original A* search expand the board.
+ The port keeps the original priority queue and tie-breaking, so paths and node counts
+ match the Python program exactly.
+
+
+
+
+
+
+ {
+ const i = r * board.n + q;
+ if (markers.get(i) === "start") return "start";
+ if (markers.get(i) === "goal") return "goal";
+ const o = overlays.get(i);
+ return o === "path" ? `path step ${labels.get(i)}` : o;
+ }}
+ />
+
+
+
+ S
+
+ Start
+
+
+
+ G
+
+ Goal
+
+
+ Open (queued)
+
+
+ Closed (expanded)
+
+
+ Path, numbered like the original display
+
+
+ );
+}
diff --git a/web/src/components/astar/heuristic-study.tsx b/web/src/components/astar/heuristic-study.tsx
new file mode 100644
index 0000000..68510ad
--- /dev/null
+++ b/web/src/components/astar/heuristic-study.tsx
@@ -0,0 +1,218 @@
+"use client";
+
+import { FlaskConical, Loader2 } from "lucide-react";
+
+import { Button } from "@/components/ui/button";
+import { useAstarBenchmark } from "@/hooks/use-astar-benchmark";
+import { useElementWidth } from "@/hooks/use-element-width";
+import type { BenchmarkRow } from "@/lib/astar/random-board";
+import { randomSeed } from "@/lib/rng";
+
+// The notebook looped `for i in range(100)`, skipping i < 2: every size from 2 to 99.
+const DIMENSIONS = Array.from({ length: 98 }, (_, i) => i + 2);
+const FIRST = DIMENSIONS[0];
+const LAST = DIMENSIONS.at(-1)!;
+
+export function HeuristicStudy() {
+ const { state, run } = useAstarBenchmark();
+
+ return (
+
+
+
+
+ Heuristic study
+
+
+ Manhattan vs Euclidean, revisited
+
+
+ Our report compared node expansions on random boards from the notebook's generator
+ (random barriers, random start and goal) and found the two heuristics similar on small
+ boards, with Manhattan expanding slightly fewer nodes as boards grew. Re-run the
+ experiment here: one random board for every size from {FIRST} × {FIRST} to {LAST} ×{" "}
+ {LAST}, counted the way the notebook counted them.
+
+
+
+
+
+
+ {state.status === "idle" && (
+
+ Press “Run the study” to generate {DIMENSIONS.length} random boards in a Web
+ Worker.
+
+
+ );
+}
diff --git a/web/src/components/layout/theme-provider.tsx b/web/src/components/layout/theme-provider.tsx
new file mode 100644
index 0000000..43bcebe
--- /dev/null
+++ b/web/src/components/layout/theme-provider.tsx
@@ -0,0 +1,8 @@
+"use client";
+
+import { ThemeProvider as NextThemesProvider } from "next-themes";
+import type { ComponentProps } from "react";
+
+export function ThemeProvider(props: ComponentProps) {
+ return ;
+}
diff --git a/web/src/components/layout/theme-toggle.tsx b/web/src/components/layout/theme-toggle.tsx
new file mode 100644
index 0000000..54102c7
--- /dev/null
+++ b/web/src/components/layout/theme-toggle.tsx
@@ -0,0 +1,21 @@
+"use client";
+
+import { Moon, Sun } from "lucide-react";
+import { useTheme } from "next-themes";
+
+import { Button } from "@/components/ui/button";
+
+export function ThemeToggle() {
+ const { resolvedTheme, setTheme } = useTheme();
+ return (
+
+ );
+}
diff --git a/web/src/components/play/board-legend.tsx b/web/src/components/play/board-legend.tsx
new file mode 100644
index 0000000..baee9f8
--- /dev/null
+++ b/web/src/components/play/board-legend.tsx
@@ -0,0 +1,26 @@
+import { ColourDot } from "./primitives";
+
+export function BoardLegend() {
+ return (
+
+
+
+ Red
+
+
Connect the top and bottom edges.
+
+
+
+ Blue
+
+
Connect the left and right edges.
+
+
+
Capture
+
+ Close a diamond around two enemy tiles and both are removed.
+
+
+
+ );
+}
diff --git a/web/src/components/play/eval-trend.tsx b/web/src/components/play/eval-trend.tsx
new file mode 100644
index 0000000..16463d8
--- /dev/null
+++ b/web/src/components/play/eval-trend.tsx
@@ -0,0 +1,83 @@
+"use client";
+
+import { useId } from "react";
+
+import { formatScore } from "./explain-panel";
+
+/**
+ * Sparkline of the original evaluation function after each move.
+ * Above the midline favours Red, below favours Blue.
+ */
+export function EvalTrend({ values }: { values: readonly number[] }) {
+ const id = useId().replace(/:/g, "");
+ const W = 320;
+ const H = 96;
+ const pad = 6;
+ const maxAbs = Math.max(10, ...values.map((v) => Math.abs(v)));
+ const x = (i: number) => pad + (i / Math.max(1, values.length - 1)) * (W - pad * 2);
+ const y = (v: number) => H / 2 - (v / maxAbs) * (H / 2 - pad);
+ const points = values.map((v, i) => `${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(" ");
+ const last = values.at(-1) ?? 0;
+
+ if (values.length < 2) {
+ return (
+
+ The trend appears after the first move.
+
+ );
+ }
+
+ return (
+
+
+
+ Original evaluation after each move · higher favours Red
+ {formatScore(last)}
+
+
+ );
+}
diff --git a/web/src/components/play/explain-panel.tsx b/web/src/components/play/explain-panel.tsx
new file mode 100644
index 0000000..53c8f6a
--- /dev/null
+++ b/web/src/components/play/explain-panel.tsx
@@ -0,0 +1,255 @@
+"use client";
+
+import { BookOpen, Dice5, Sparkles, Trophy } from "lucide-react";
+
+import type { MoveMeta } from "@/hooks/use-cachex-match";
+import type { Action, Colour } from "@/lib/cachex/types";
+import { sameAction } from "@/lib/cachex/types";
+import { cn } from "@/lib/utils";
+import { ColourDot, colourName } from "./primitives";
+
+/** Round to the one decimal place shown in the UI (infinities pass through). */
+const roundScore = (s: number) => (Number.isFinite(s) ? Math.round(s * 10) / 10 + 0 : s);
+
+const hasTies = (scores: number[]) => new Set(scores).size < scores.length;
+
+export const formatScore = (s: number) =>
+ s === Infinity ? "+∞" : s === -Infinity ? "−∞" : roundScore(s).toLocaleString("en-AU");
+
+const actionLabel = (a: Action) => (a[0] === "STEAL" ? "STEAL" : `(${a[1]}, ${a[2]})`);
+
+export function ExplainPanel({
+ meta,
+ action,
+ colour,
+ turn,
+}: {
+ meta: MoveMeta | undefined;
+ action: Action | undefined;
+ colour: Colour | undefined;
+ turn: number | undefined;
+}) {
+ if (!meta || !action || !colour) {
+ return (
+
+ When the minimax agent moves, its reasoning appears here: the opening book, an instant win,
+ or the scores its search assigned to each candidate and the evaluation features behind the
+ chosen move.
+
+ );
+ }
+
+ const { depth, nodes, candidates, features, score } = explanation;
+ // Show the chosen move first among equal scores, then bar lengths by how
+ // good each candidate is for the mover (Red wants high, Blue wants low).
+ const sign = colour === "red" ? 1 : -1;
+ const ordered = [...candidates].sort((a, b) => {
+ const d = sign * (b.score - a.score);
+ if (d !== 0 && !Number.isNaN(d)) return d;
+ return Number(sameAction(b.action, action)) - Number(sameAction(a.action, action));
+ });
+ const top = ordered.slice(0, 6);
+ // Bars compare scores at the precision they are displayed: the original
+ // agent multiplies each score by a random 1 or 1 + 1e-5 to break ties, and
+ // those ~1e-4 differences must not look like real gaps.
+ const shownGoodness = (score: number) => sign * roundScore(score);
+ const goodness = top.map((c) => shownGoodness(c.score)).filter(Number.isFinite);
+ const lo = Math.min(...goodness);
+ const hi = Math.max(...goodness);
+ const allTied = goodness.length === 0 || hi - lo < 0.05;
+
+ return (
+
+ Scores are from Red's point of view: Red maximises, Blue minimises.
+ {depth > 1 &&
+ " With alpha-beta pruning, scores other than the chosen move can be bounds rather than exact values."}
+
+ The opponent is a faithful TypeScript port of our Python minimax agent, running in a Web
+ Worker. Red moves first; Blue may steal Red's opening tile.
+
+ {children}
+
+ );
+}
diff --git a/web/src/components/play/spectate-client.tsx b/web/src/components/play/spectate-client.tsx
new file mode 100644
index 0000000..8c019d2
--- /dev/null
+++ b/web/src/components/play/spectate-client.tsx
@@ -0,0 +1,209 @@
+"use client";
+
+import { Pause, Play, Repeat, Shuffle, StepForward } from "lucide-react";
+import { useMemo, useState } from "react";
+
+import { Button } from "@/components/ui/button";
+import { Label } from "@/components/ui/label";
+import { Slider } from "@/components/ui/slider";
+import { Switch } from "@/components/ui/switch";
+import { type MatchConfig, useCachexMatch } from "@/hooks/use-cachex-match";
+import { randomSeed } from "@/lib/rng";
+import { BoardLegend } from "./board-legend";
+import { EvalTrend } from "./eval-trend";
+import { ExplainPanel } from "./explain-panel";
+import { MatchBoard } from "./match-board";
+import { MatchStatus } from "./match-status";
+import { MoveLog } from "./move-log";
+import { BoardSizeSelect, ColourDot, Field, Panel, Segmented } from "./primitives";
+
+type Agent = "minimax" | "random";
+
+const AGENT_OPTIONS = [
+ { value: "minimax" as const, label: "Minimax" },
+ { value: "random" as const, label: "Random" },
+];
+
+export function SpectateClient() {
+ const [n, setN] = useState(6);
+ const [red, setRed] = useState("minimax");
+ const [blue, setBlue] = useState("minimax");
+ const [seed, setSeed] = useState(2022);
+ const [playing, setPlaying] = useState(false);
+ const [delay, setDelay] = useState(600);
+ const [showCoords, setShowCoords] = useState(false);
+ const [selected, setSelected] = useState(null);
+
+ const config: MatchConfig = useMemo(() => ({ n, red, blue, seed }), [blue, n, red, seed]);
+ const match = useCachexMatch(config, { autoPlay: playing, moveDelayMs: delay });
+ const { game } = match.view;
+ const over = game.over();
+
+ const restart = (changes: Partial<{ n: number; red: Agent; blue: Agent; seed: number }> = {}) => {
+ if (changes.n !== undefined) setN(changes.n);
+ if (changes.red !== undefined) setRed(changes.red);
+ if (changes.blue !== undefined) setBlue(changes.blue);
+ setSeed(changes.seed ?? seed);
+ setSelected(null);
+ // A finished game ends auto-play: restarting from it starts paused.
+ if (over) setPlaying(false);
+ match.reset();
+ };
+
+ const lastExplained = Object.keys(match.meta)
+ .map(Number)
+ .sort((a, b) => b - a)[0];
+ const shown = selected !== null && match.meta[selected] ? selected : lastExplained;
+
+ return (
+
+
+
+
+ Spectator mode
+
+
AI vs AI
+
+ Pit the minimax agent against itself or the random baseline. Every game is reproducible
+ from its seed, which drives the move shuffle and the tie-breaking bias the original
+ agent used.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/web/src/components/ui/button.tsx b/web/src/components/ui/button.tsx
new file mode 100644
index 0000000..18407c9
--- /dev/null
+++ b/web/src/components/ui/button.tsx
@@ -0,0 +1,66 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+import { cn } from "cn"
+import { Slot } from "radix-ui"
+
+const buttonVariants = cva(
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
+ outline:
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
+ secondary:
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
+ ghost:
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
+ destructive:
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default:
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ icon: "size-8",
+ "icon-xs":
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
+ "icon-sm":
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
+ "icon-lg": "size-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+function Button({
+ className,
+ variant = "default",
+ size = "default",
+ asChild = false,
+ ...props
+}: React.ComponentProps<"button"> &
+ VariantProps & {
+ asChild?: boolean
+ }) {
+ const Comp = asChild ? Slot.Root : "button"
+
+ return (
+
+ )
+}
+
+export { Button, buttonVariants }
diff --git a/web/src/components/ui/label.tsx b/web/src/components/ui/label.tsx
new file mode 100644
index 0000000..5aff746
--- /dev/null
+++ b/web/src/components/ui/label.tsx
@@ -0,0 +1,23 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { Label as LabelPrimitive } from "radix-ui"
+
+function Label({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+export { Label }
diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx
new file mode 100644
index 0000000..cdd962b
--- /dev/null
+++ b/web/src/components/ui/select.tsx
@@ -0,0 +1,191 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { Select as SelectPrimitive } from "radix-ui"
+import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react"
+
+function Select({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectGroup({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectValue({
+ ...props
+}: React.ComponentProps) {
+ return
+}
+
+function SelectTrigger({
+ className,
+ size = "default",
+ children,
+ ...props
+}: React.ComponentProps & {
+ size?: "sm" | "default"
+}) {
+ return (
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectContent({
+ className,
+ children,
+ position = "item-aligned",
+ align = "center",
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ )
+}
+
+function SelectLabel({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectItem({
+ className,
+ children,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+
+
+
+ {children}
+
+ )
+}
+
+function SelectSeparator({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ )
+}
+
+function SelectScrollUpButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+function SelectScrollDownButton({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+
+
+ )
+}
+
+export {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectScrollDownButton,
+ SelectScrollUpButton,
+ SelectSeparator,
+ SelectTrigger,
+ SelectValue,
+}
diff --git a/web/src/components/ui/slider.tsx b/web/src/components/ui/slider.tsx
new file mode 100644
index 0000000..81b27a3
--- /dev/null
+++ b/web/src/components/ui/slider.tsx
@@ -0,0 +1,73 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { Slider as SliderPrimitive } from "radix-ui"
+
+// Radix puts role="slider" on each Thumb, so the accessible name and value
+// text are forwarded there (an aria-label on Root would not reach the thumb).
+function Slider({
+ className,
+ defaultValue,
+ value,
+ min = 0,
+ max = 100,
+ "aria-label": ariaLabel,
+ "aria-labelledby": ariaLabelledBy,
+ getValueText,
+ ...props
+}: React.ComponentProps & {
+ /** Human-readable value for screen readers (aria-valuetext). */
+ getValueText?: (value: number) => string
+}) {
+ const _values = React.useMemo(
+ () =>
+ Array.isArray(value)
+ ? value
+ : Array.isArray(defaultValue)
+ ? defaultValue
+ : [min, max],
+ [value, defaultValue, min, max]
+ )
+
+ return (
+
+
+
+
+ {Array.from({ length: _values.length }, (_, index) => (
+
+ ))}
+
+ )
+}
+
+export { Slider }
diff --git a/web/src/components/ui/switch.tsx b/web/src/components/ui/switch.tsx
new file mode 100644
index 0000000..c7bc52e
--- /dev/null
+++ b/web/src/components/ui/switch.tsx
@@ -0,0 +1,32 @@
+"use client"
+
+import * as React from "react"
+import { cn } from "cn"
+import { Switch as SwitchPrimitive } from "radix-ui"
+
+function Switch({
+ className,
+ size = "default",
+ ...props
+}: React.ComponentProps & {
+ size?: "sm" | "default"
+}) {
+ return (
+
+
+
+ )
+}
+
+export { Switch }
diff --git a/web/src/components/ui/textarea.tsx b/web/src/components/ui/textarea.tsx
new file mode 100644
index 0000000..5141de7
--- /dev/null
+++ b/web/src/components/ui/textarea.tsx
@@ -0,0 +1,17 @@
+import * as React from "react"
+import { cn } from "cn"
+
+function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
+ return (
+
+ )
+}
+
+export { Textarea }
diff --git a/web/src/components/ui/toggle-group.tsx b/web/src/components/ui/toggle-group.tsx
new file mode 100644
index 0000000..b8bebe3
--- /dev/null
+++ b/web/src/components/ui/toggle-group.tsx
@@ -0,0 +1,89 @@
+"use client"
+
+import * as React from "react"
+import { type VariantProps } from "class-variance-authority"
+import { cn } from "cn"
+import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui"
+
+import { toggleVariants } from "@/components/ui/toggle"
+
+const ToggleGroupContext = React.createContext<
+ VariantProps & {
+ spacing?: number
+ orientation?: "horizontal" | "vertical"
+ }
+>({
+ size: "default",
+ variant: "default",
+ spacing: 2,
+ orientation: "horizontal",
+})
+
+function ToggleGroup({
+ className,
+ variant,
+ size,
+ spacing = 2,
+ orientation = "horizontal",
+ children,
+ ...props
+}: React.ComponentProps &
+ VariantProps & {
+ spacing?: number
+ orientation?: "horizontal" | "vertical"
+ }) {
+ return (
+
+
+ {children}
+
+
+ )
+}
+
+function ToggleGroupItem({
+ className,
+ children,
+ variant = "default",
+ size = "default",
+ ...props
+}: React.ComponentProps &
+ VariantProps) {
+ const context = React.useContext(ToggleGroupContext)
+
+ return (
+
+ {children}
+
+ )
+}
+
+export { ToggleGroup, ToggleGroupItem }
diff --git a/web/src/components/ui/toggle.tsx b/web/src/components/ui/toggle.tsx
new file mode 100644
index 0000000..ee892ce
--- /dev/null
+++ b/web/src/components/ui/toggle.tsx
@@ -0,0 +1,46 @@
+"use client"
+
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+import { cn } from "cn"
+import { Toggle as TogglePrimitive } from "radix-ui"
+
+const toggleVariants = cva(
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:bg-muted data-[state=on]:bg-muted dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ {
+ variants: {
+ variant: {
+ default: "bg-transparent",
+ outline: "border border-input bg-transparent hover:bg-muted",
+ },
+ size: {
+ default:
+ "h-8 min-w-8 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
+ lg: "h-9 min-w-9 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ }
+)
+
+function Toggle({
+ className,
+ variant = "default",
+ size = "default",
+ ...props
+}: React.ComponentProps &
+ VariantProps) {
+ return (
+
+ )
+}
+
+export { Toggle, toggleVariants }
diff --git a/web/src/hooks/use-agent-worker.ts b/web/src/hooks/use-agent-worker.ts
new file mode 100644
index 0000000..ef2d7dd
--- /dev/null
+++ b/web/src/hooks/use-agent-worker.ts
@@ -0,0 +1,59 @@
+"use client";
+
+import { useCallback, useEffect, useRef } from "react";
+
+import { type AgentRequest, type AgentResponse, runAgent } from "@/lib/agent/run-agent";
+
+type Pending = Map void>;
+
+/**
+ * Owns one agent Web Worker for the lifetime of the component and returns a
+ * promise-based `request` function. Falls back to the main thread if workers
+ * are unavailable.
+ */
+export function useAgentWorker() {
+ const workerRef = useRef(null);
+ const pendingRef = useRef(new Map());
+ const nextId = useRef(0);
+
+ useEffect(() => {
+ const pending = pendingRef.current;
+ let worker: Worker | null = null;
+ try {
+ worker = new Worker(new URL("../workers/agent.worker.ts", import.meta.url), {
+ type: "module",
+ });
+ worker.onmessage = (event: MessageEvent) => {
+ const resolve = pending.get(event.data.id);
+ pending.delete(event.data.id);
+ resolve?.(event.data);
+ };
+ worker.onerror = () => {
+ for (const [id, resolve] of pending)
+ resolve({ id, ok: false, error: "The agent worker crashed." });
+ pending.clear();
+ };
+ } catch {
+ worker = null;
+ }
+ workerRef.current = worker;
+ return () => {
+ worker?.terminate();
+ workerRef.current = null;
+ pending.clear();
+ };
+ }, []);
+
+ return useCallback((req: Omit) => {
+ const id = ++nextId.current;
+ return new Promise((resolve) => {
+ const worker = workerRef.current;
+ if (worker) {
+ pendingRef.current.set(id, resolve);
+ worker.postMessage({ ...req, id });
+ } else {
+ setTimeout(() => resolve(runAgent({ ...req, id })), 0);
+ }
+ });
+ }, []);
+}
diff --git a/web/src/hooks/use-astar-benchmark.ts b/web/src/hooks/use-astar-benchmark.ts
new file mode 100644
index 0000000..3992385
--- /dev/null
+++ b/web/src/hooks/use-astar-benchmark.ts
@@ -0,0 +1,66 @@
+"use client";
+
+import { useCallback, useEffect, useRef, useState } from "react";
+
+import { type BenchmarkRow, runHeuristicBenchmark } from "@/lib/astar/random-board";
+import type { BenchmarkResponse } from "@/workers/astar-benchmark.worker";
+
+type State =
+ | { status: "idle" }
+ | { status: "running"; seed: number }
+ | { status: "done"; seed: number; rows: BenchmarkRow[]; elapsedMs: number }
+ | { status: "error"; message: string };
+
+/** Runs the heuristic study in a Web Worker (main-thread fallback). */
+export function useAstarBenchmark() {
+ const [state, setState] = useState({ status: "idle" });
+ const workerRef = useRef(null);
+ const latest = useRef(0);
+
+ useEffect(() => {
+ let worker: Worker | null = null;
+ try {
+ worker = new Worker(new URL("../workers/astar-benchmark.worker.ts", import.meta.url), {
+ type: "module",
+ });
+ worker.onmessage = (event: MessageEvent) => {
+ const res = event.data;
+ if (res.id !== latest.current) return;
+ setState((prev) =>
+ res.ok
+ ? {
+ status: "done",
+ seed: prev.status === "running" ? prev.seed : 0,
+ rows: res.rows,
+ elapsedMs: res.elapsedMs,
+ }
+ : { status: "error", message: res.error },
+ );
+ };
+ worker.onerror = () =>
+ setState({ status: "error", message: "The benchmark worker crashed." });
+ } catch {
+ worker = null;
+ }
+ workerRef.current = worker;
+ return () => worker?.terminate();
+ }, []);
+
+ const run = useCallback((dimensions: number[], seed: number) => {
+ const id = ++latest.current;
+ setState({ status: "running", seed });
+ const worker = workerRef.current;
+ if (worker) {
+ worker.postMessage({ id, dimensions, seed });
+ } else {
+ setTimeout(() => {
+ const started = performance.now();
+ const rows = runHeuristicBenchmark(dimensions, seed);
+ if (id === latest.current)
+ setState({ status: "done", seed, rows, elapsedMs: performance.now() - started });
+ }, 0);
+ }
+ }, []);
+
+ return { state, run };
+}
diff --git a/web/src/hooks/use-cachex-match.ts b/web/src/hooks/use-cachex-match.ts
new file mode 100644
index 0000000..532bfe7
--- /dev/null
+++ b/web/src/hooks/use-cachex-match.ts
@@ -0,0 +1,173 @@
+"use client";
+
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+
+import type { MoveExplanation } from "@/lib/agent/player";
+import type { AgentResponse } from "@/lib/agent/run-agent";
+import {
+ type PlayerKind,
+ deriveMatchView,
+ evaluationTrend,
+ undoToHumanTurn,
+} from "@/lib/cachex/match";
+import { Game } from "@/lib/cachex/game";
+import type { Action, Colour } from "@/lib/cachex/types";
+import { useAgentWorker } from "./use-agent-worker";
+
+export interface MatchConfig {
+ n: number;
+ red: PlayerKind;
+ blue: PlayerKind;
+ seed: number;
+}
+
+export interface MatchOptions {
+ /** Let AI players move automatically. */
+ autoPlay: boolean;
+ /** Minimum time an AI move takes on screen, in ms. */
+ moveDelayMs: number;
+}
+
+export interface MoveMeta {
+ explanation: MoveExplanation;
+ elapsedMs: number;
+}
+
+/**
+ * Game state for a match between any mix of humans and agents. The action
+ * list is the single source of truth; everything else is derived from it.
+ */
+export function useCachexMatch(config: MatchConfig, options: MatchOptions) {
+ const request = useAgentWorker();
+ const [actions, setActions] = useState([]);
+ const [meta, setMeta] = useState>({});
+ const [error, setError] = useState(null);
+ const [inFlight, setInFlight] = useState(0);
+ const busy = inFlight > 0;
+ const actionsRef = useRef(actions);
+ useEffect(() => {
+ actionsRef.current = actions;
+ }, [actions]);
+
+ const view = useMemo(() => deriveMatchView(config.n, actions), [config.n, actions]);
+ const trend = useMemo(() => evaluationTrend(config.n, actions), [config.n, actions]);
+ const { game } = view;
+ const toMove: Colour = game.turnPlayer();
+ const toMoveKind = config[toMove];
+ const isOver = game.over();
+ const isAiTurn = !isOver && toMoveKind !== "human";
+
+ const applyResponse = useCallback((snapshot: Action[], res: AgentResponse) => {
+ if (actionsRef.current !== snapshot) return; // the position changed (undo/reset)
+ if (!res.ok) {
+ setError(res.error);
+ return;
+ }
+ const index = snapshot.length;
+ const next = [...snapshot, res.decision.action];
+ actionsRef.current = next;
+ setActions(next);
+ setMeta((prev) => ({
+ ...prev,
+ [index]: { explanation: res.decision.explanation, elapsedMs: res.elapsedMs },
+ }));
+ }, []);
+
+ const askAgent = useCallback(
+ (snapshot: Action[], minDelay: number, isCancelled: () => boolean = () => false) => {
+ const kind = config[snapshot.length % 2 === 0 ? "red" : "blue"];
+ if (kind === "human") return Promise.resolve();
+ const started = performance.now();
+ return request({
+ kind,
+ n: config.n,
+ history: snapshot,
+ colour: snapshot.length % 2 === 0 ? "red" : "blue",
+ seed: (config.seed + snapshot.length * 7919) >>> 0,
+ }).then(
+ (res) =>
+ new Promise((resolve) => {
+ const wait = Math.max(0, minDelay - (performance.now() - started));
+ setTimeout(() => {
+ if (!isCancelled()) applyResponse(snapshot, res);
+ resolve();
+ }, wait);
+ }),
+ );
+ },
+ [applyResponse, config, request],
+ );
+
+ // Automatic AI moves.
+ useEffect(() => {
+ if (!isAiTurn || !options.autoPlay || error) return;
+ let cancelled = false;
+ const snapshot = actions;
+ const timer = setTimeout(() => {
+ if (cancelled) return;
+ setInFlight((c) => c + 1);
+ askAgent(snapshot, options.moveDelayMs, () => cancelled).finally(() =>
+ setInFlight((c) => c - 1),
+ );
+ }, 0);
+ return () => {
+ cancelled = true;
+ clearTimeout(timer);
+ };
+ }, [actions, askAgent, error, isAiTurn, options.autoPlay, options.moveDelayMs]);
+
+ const play = useCallback(
+ (action: Action) => {
+ const current = actionsRef.current;
+ const g = Game.fromActions(config.n, current);
+ if (config[g.turnPlayer()] !== "human" || !g.isLegal(action)) return false;
+ const next = [...current, action];
+ actionsRef.current = next;
+ setActions(next);
+ return true;
+ },
+ [config],
+ );
+
+ /** Advance one AI move (used by the spectator's Step button). */
+ const step = useCallback(() => {
+ if (!isAiTurn || busy) return;
+ setInFlight((c) => c + 1);
+ askAgent(actionsRef.current, 0).finally(() => setInFlight((c) => c - 1));
+ }, [askAgent, busy, isAiTurn]);
+
+ const undo = useCallback(() => {
+ const next = undoToHumanTurn(actionsRef.current, { red: config.red, blue: config.blue });
+ actionsRef.current = next;
+ setError(null);
+ setActions(next);
+ setMeta((m) => Object.fromEntries(Object.entries(m).filter(([k]) => Number(k) < next.length)));
+ }, [config.blue, config.red]);
+
+ const reset = useCallback(() => {
+ const next: Action[] = [];
+ actionsRef.current = next;
+ setError(null);
+ setMeta({});
+ setActions(next);
+ }, []);
+
+ const canUndo = actions.some((_, i) => config[i % 2 === 0 ? "red" : "blue"] === "human");
+
+ return {
+ actions,
+ view,
+ trend,
+ meta,
+ error,
+ toMove,
+ toMoveKind,
+ isAiTurn,
+ thinking: isAiTurn && (busy || options.autoPlay) && !error,
+ play,
+ step,
+ undo,
+ reset,
+ canUndo,
+ };
+}
diff --git a/web/src/hooks/use-element-width.ts b/web/src/hooks/use-element-width.ts
new file mode 100644
index 0000000..21518d1
--- /dev/null
+++ b/web/src/hooks/use-element-width.ts
@@ -0,0 +1,27 @@
+"use client";
+
+import { type RefObject, useEffect, useRef, useState } from "react";
+
+/**
+ * Tracks an element's content-box width with a ResizeObserver, so SVG charts
+ * can be drawn at their real pixel width (keeping axis text legible on phones).
+ */
+export function useElementWidth(
+ fallback: number,
+): [RefObject, number] {
+ const ref = useRef(null);
+ const [width, setWidth] = useState(fallback);
+
+ useEffect(() => {
+ const el = ref.current;
+ if (!el || typeof ResizeObserver === "undefined") return;
+ const observer = new ResizeObserver(([entry]) => {
+ const w = Math.round(entry.contentRect.width);
+ if (w > 0) setWidth(w);
+ });
+ observer.observe(el);
+ return () => observer.disconnect();
+ }, []);
+
+ return [ref, width];
+}
diff --git a/web/src/lib/__fixtures__/load.ts b/web/src/lib/__fixtures__/load.ts
new file mode 100644
index 0000000..08713f3
--- /dev/null
+++ b/web/src/lib/__fixtures__/load.ts
@@ -0,0 +1,88 @@
+/**
+ * Typed loaders for the parity fixtures produced by
+ * scripts/generate_parity_fixtures.py (which runs the ORIGINAL Python code).
+ * Read with fs so tsc does not have to infer types for large JSON files.
+ */
+import { readFileSync } from "node:fs";
+
+import type { Action, Colour } from "@/lib/cachex/types";
+
+export type PyNumber = number | "inf" | "-inf";
+export const fromPy = (x: PyNumber): number =>
+ x === "inf" ? Infinity : x === "-inf" ? -Infinity : x;
+
+export type PyAction = ["PLACE", number, number] | ["STEAL"];
+export const toAction = (a: PyAction): Action => (a[0] === "STEAL" ? ["STEAL"] : ["PLACE", a[1], a[2]]);
+
+function load(name: string): T {
+ return JSON.parse(readFileSync(new URL(`./${name}`, import.meta.url), "utf8")) as T;
+}
+
+export interface PartAFixtures {
+ meta: { python: string };
+ neighbourOrders: Record;
+ cases: {
+ name: string;
+ input: { n: number; board: [string, number, number][]; start: [number, number]; goal: [number, number] };
+ heuristic: "manhattan" | "euclidean";
+ block: "Red" | "Blue" | null;
+ path: [number, number][];
+ pops: number;
+ pushes: number;
+ }[];
+}
+
+export type PositionRef = { game: number; cut: number } | { n: number; actions: PyAction[] };
+
+interface ColourCountsPy {
+ red: PyNumber;
+ blue: PyNumber;
+}
+
+export interface PartBFixtures {
+ meta: { python: string };
+ scoreMatrices: Record;
+ refereeGames: {
+ n: number;
+ actions: PyAction[];
+ steps: { captures: [number, number][]; board: string; result: string | null }[];
+ }[];
+ evalPositions: {
+ game: number;
+ cut: number;
+ features: {
+ empty: number;
+ triangle: ColourCountsPy;
+ tokens: ColourCountsPy;
+ location: ColourCountsPy;
+ diamond: ColourCountsPy;
+ weakness: ColourCountsPy;
+ };
+ eval: PyNumber;
+ }[];
+ minimax: {
+ game: number;
+ cut: number;
+ depth: number;
+ maximizing: boolean;
+ score: PyNumber;
+ action: PyAction | null;
+ }[];
+ agentMoves: (PositionRef & { colour: Colour; action: PyAction })[];
+ agentGames: { n: number; actions: PyAction[]; result: string }[];
+}
+
+export const partA = () => load("parity-part-a.json");
+export const partB = () => load("parity-part-b.json");
+
+/** Resolve a (game, cut) reference to the board size and action prefix. */
+export function position(
+ fixtures: PartBFixtures,
+ ref: PositionRef,
+): { n: number; actions: Action[] } {
+ if ("game" in ref) {
+ const game = fixtures.refereeGames[ref.game];
+ return { n: game.n, actions: game.actions.slice(0, ref.cut).map(toAction) };
+ }
+ return { n: ref.n, actions: ref.actions.map(toAction) };
+}
diff --git a/web/src/lib/__fixtures__/parity-part-a.json b/web/src/lib/__fixtures__/parity-part-a.json
new file mode 100644
index 0000000..d1d6c72
--- /dev/null
+++ b/web/src/lib/__fixtures__/parity-part-a.json
@@ -0,0 +1 @@
+{"meta":{"generatedBy":"scripts/generate_parity_fixtures.py","python":"3.12.7","implementation":"CPython"},"neighbourOrders":{"1":[[]],"2":[[[0,1],[1,0]],[[1,0],[1,1],[0,0]],[[0,1],[1,1],[0,0]],[[0,1],[1,0]]],"3":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,2],[2,2]],[[1,0],[1,1],[2,1]],[[1,2],[1,1],[2,0],[2,2]],[[1,2],[2,1]]],"4":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,2],[1,3]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,3],[2,3],[2,2]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[3,3],[2,2],[3,2],[1,3]],[[3,1],[2,0],[2,1]],[[2,1],[3,0],[2,2],[3,2]],[[3,1],[2,3],[3,3],[2,2]],[[2,3],[3,2]]],"5":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[1,3],[0,3],[1,4]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[2,3],[1,3]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,4],[2,3],[3,3]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3]],[[3,1],[4,1],[3,0]],[[4,0],[3,1],[4,2],[3,2]],[[4,3],[3,3],[3,2],[4,1]],[[4,4],[3,4],[4,2],[3,3]],[[3,4],[4,3]]],"6":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[1,4],[0,4],[1,5]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,5],[2,5]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[3,5]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,5]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[3,5]],[[4,0],[4,1],[5,1]],[[4,2],[5,0],[4,1],[5,2]],[[4,3],[5,1],[4,2],[5,3]],[[4,4],[4,3],[5,4],[5,2]],[[4,4],[5,5],[4,5],[5,3]],[[4,5],[5,4]]],"7":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[1,6],[1,5],[0,5]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[1,5],[0,6],[2,6],[2,5]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[3,6],[1,6],[2,5],[3,5]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[4,6],[4,5],[2,6],[3,5]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[4,5],[5,6],[3,6]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[6,6]],[[6,1],[5,0],[5,1]],[[6,2],[5,1],[6,0],[5,2]],[[6,1],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[5,3]],[[5,5],[6,5],[5,4],[6,3]],[[5,5],[6,4],[5,6],[6,6]],[[5,6],[6,5]]],"8":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[1,6],[1,7],[0,6]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[2,6],[1,6]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,7],[2,6],[3,6]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[2,7],[4,6],[3,6],[4,7]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,7],[4,6],[5,7],[5,6]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[6,7],[5,6],[6,6],[4,7]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,7],[7,6],[6,6]],[[6,1],[7,1],[6,0]],[[6,2],[6,1],[7,0],[7,2]],[[6,2],[7,1],[7,3],[6,3]],[[7,4],[6,4],[7,2],[6,3]],[[6,5],[6,4],[7,3],[7,5]],[[7,4],[6,5],[7,6],[6,6]],[[7,7],[6,7],[6,6],[7,5]],[[6,7],[7,6]]],"9":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[1,7]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[1,7],[0,8],[2,8]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[4,8],[4,7],[2,8]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[5,7],[4,7]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[6,8],[5,7],[6,7],[4,8]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[7,8]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8]],[[7,0],[7,1],[8,1]],[[7,1],[8,0],[7,2],[8,2]],[[8,1],[7,3],[8,3],[7,2]],[[7,4],[8,4],[7,3],[8,2]],[[7,4],[8,3],[7,5],[8,5]],[[8,4],[7,6],[8,6],[7,5]],[[7,7],[8,7],[7,6],[8,5]],[[8,8],[7,7],[8,6],[7,8]],[[8,7],[7,8]]],"10":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[0,9],[1,7]],[[0,8],[1,8],[1,9]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[0,9],[1,7],[0,8],[1,9],[2,8]],[[1,8],[0,9],[2,9],[2,8]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8],[2,9],[1,9]],[[3,8],[3,9],[1,9],[2,8]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[2,9],[3,9],[4,8],[4,7],[2,8]],[[3,8],[4,9],[2,9],[4,8]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[4,9],[5,7],[3,9],[4,7]],[[5,8],[3,9],[4,8],[5,9]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[4,9],[6,8],[5,7],[6,7],[4,8],[5,9]],[[5,8],[4,9],[6,8],[6,9]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[5,9],[6,9],[7,8]],[[6,8],[7,9],[5,9],[7,8]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8],[7,9],[6,9]],[[8,8],[8,9],[6,9],[7,8]],[[9,0],[7,1],[8,1],[7,0]],[[9,0],[7,1],[8,0],[7,2],[8,2],[9,1]],[[8,1],[9,2],[7,3],[8,3],[7,2],[9,1]],[[7,4],[8,4],[9,3],[9,2],[7,3],[8,2]],[[7,4],[9,3],[8,3],[7,5],[8,5],[9,4]],[[8,4],[9,5],[7,6],[8,6],[7,5],[9,4]],[[7,7],[8,7],[9,6],[9,5],[7,6],[8,5]],[[8,8],[7,7],[9,6],[8,6],[9,7],[7,8]],[[8,7],[7,9],[8,9],[9,8],[9,7],[7,8]],[[8,8],[9,9],[7,9],[9,8]],[[9,1],[8,0],[8,1]],[[9,0],[8,1],[9,2],[8,2]],[[9,3],[8,3],[8,2],[9,1]],[[8,4],[9,2],[8,3],[9,4]],[[8,4],[9,3],[9,5],[8,5]],[[9,6],[8,6],[8,5],[9,4]],[[8,7],[9,5],[8,6],[9,7]],[[8,8],[8,7],[9,6],[9,8]],[[8,8],[9,9],[8,9],[9,7]],[[8,9],[9,8]]],"11":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[0,9],[1,7]],[[0,10],[1,8],[0,8],[1,9]],[[1,9],[0,9],[1,10]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[0,9],[1,7],[0,8],[1,9],[2,8]],[[0,10],[1,8],[0,9],[2,9],[1,10],[2,8]],[[0,10],[2,10],[2,9],[1,9]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8],[2,9],[1,9]],[[3,8],[2,10],[3,9],[1,10],[1,9],[2,8]],[[3,10],[2,9],[3,9],[1,10]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[2,9],[3,9],[4,8],[4,7],[2,8]],[[3,8],[4,9],[2,10],[3,10],[2,9],[4,8]],[[4,10],[4,9],[2,10],[3,9]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[4,9],[5,7],[3,9],[4,7]],[[4,10],[5,8],[3,10],[3,9],[4,8],[5,9]],[[4,9],[3,10],[5,10],[5,9]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[4,9],[6,8],[5,7],[6,7],[4,8],[5,9]],[[4,10],[5,8],[4,9],[6,8],[5,10],[6,9]],[[4,10],[6,10],[5,9],[6,9]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[5,9],[6,9],[7,8]],[[6,8],[7,9],[5,10],[6,10],[5,9],[7,8]],[[7,10],[7,9],[5,10],[6,9]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8],[7,9],[6,9]],[[8,8],[7,10],[8,9],[6,10],[6,9],[7,8]],[[8,10],[7,9],[8,9],[6,10]],[[9,0],[7,1],[8,1],[7,0]],[[9,0],[7,1],[8,0],[7,2],[8,2],[9,1]],[[8,1],[9,2],[7,3],[8,3],[7,2],[9,1]],[[7,4],[8,4],[9,3],[9,2],[7,3],[8,2]],[[7,4],[9,3],[8,3],[7,5],[8,5],[9,4]],[[8,4],[9,5],[7,6],[8,6],[7,5],[9,4]],[[7,7],[8,7],[9,6],[9,5],[7,6],[8,5]],[[8,8],[7,7],[9,6],[8,6],[9,7],[7,8]],[[8,7],[7,9],[8,9],[9,8],[9,7],[7,8]],[[8,8],[9,9],[7,10],[8,10],[7,9],[9,8]],[[9,10],[9,9],[7,10],[8,9]],[[8,1],[8,0],[10,0],[9,1]],[[9,0],[8,1],[10,1],[9,2],[10,0],[8,2]],[[9,3],[10,1],[8,3],[8,2],[9,1],[10,2]],[[8,4],[9,2],[8,3],[10,3],[10,2],[9,4]],[[8,4],[9,3],[10,4],[9,5],[10,3],[8,5]],[[10,5],[10,4],[9,6],[8,6],[8,5],[9,4]],[[10,5],[8,7],[9,5],[10,6],[8,6],[9,7]],[[8,8],[8,7],[9,6],[10,7],[10,6],[9,8]],[[8,8],[10,8],[9,9],[10,7],[8,9],[9,7]],[[9,10],[10,8],[8,10],[8,9],[9,8],[10,9]],[[9,9],[8,10],[10,10],[10,9]],[[10,1],[9,0],[9,1]],[[9,2],[10,0],[9,1],[10,2]],[[9,3],[10,1],[9,2],[10,3]],[[9,3],[10,4],[10,2],[9,4]],[[10,5],[9,5],[10,3],[9,4]],[[10,4],[9,6],[9,5],[10,6]],[[10,5],[9,6],[10,7],[9,7]],[[10,8],[10,6],[9,8],[9,7]],[[9,9],[10,7],[9,8],[10,9]],[[9,10],[10,8],[9,9],[10,10]],[[9,10],[10,9]]],"12":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[0,9],[1,7]],[[0,10],[1,8],[0,8],[1,9]],[[0,9],[1,10],[1,9],[0,11]],[[1,11],[1,10],[0,10]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[0,9],[1,7],[0,8],[1,9],[2,8]],[[0,10],[1,8],[0,9],[2,9],[1,10],[2,8]],[[0,10],[1,11],[2,10],[2,9],[1,9],[0,11]],[[2,10],[1,10],[2,11],[0,11]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8],[2,9],[1,9]],[[3,8],[2,10],[3,9],[1,10],[1,9],[2,8]],[[1,11],[3,10],[2,9],[3,9],[1,10],[2,11]],[[1,11],[2,10],[3,10],[3,11]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[2,9],[3,9],[4,8],[4,7],[2,8]],[[3,8],[4,9],[2,10],[3,10],[2,9],[4,8]],[[4,10],[4,9],[2,10],[3,9],[2,11],[3,11]],[[4,10],[3,10],[4,11],[2,11]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[4,9],[5,7],[3,9],[4,7]],[[4,10],[5,8],[3,10],[3,9],[4,8],[5,9]],[[4,9],[3,10],[5,10],[5,9],[4,11],[3,11]],[[4,10],[5,11],[5,10],[3,11]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[4,9],[6,8],[5,7],[6,7],[4,8],[5,9]],[[4,10],[5,8],[4,9],[6,8],[5,10],[6,9]],[[4,10],[5,11],[6,10],[5,9],[4,11],[6,9]],[[6,11],[5,10],[6,10],[4,11]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[5,9],[6,9],[7,8]],[[6,8],[7,9],[5,10],[6,10],[5,9],[7,8]],[[5,11],[6,11],[7,10],[7,9],[5,10],[6,9]],[[5,11],[7,10],[6,10],[7,11]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8],[7,9],[6,9]],[[8,8],[7,10],[8,9],[6,10],[6,9],[7,8]],[[6,11],[8,10],[7,9],[8,9],[6,10],[7,11]],[[6,11],[7,10],[8,10],[8,11]],[[9,0],[7,1],[8,1],[7,0]],[[9,0],[7,1],[8,0],[7,2],[8,2],[9,1]],[[8,1],[9,2],[7,3],[8,3],[7,2],[9,1]],[[7,4],[8,4],[9,3],[9,2],[7,3],[8,2]],[[7,4],[9,3],[8,3],[7,5],[8,5],[9,4]],[[8,4],[9,5],[7,6],[8,6],[7,5],[9,4]],[[7,7],[8,7],[9,6],[9,5],[7,6],[8,5]],[[8,8],[7,7],[9,6],[8,6],[9,7],[7,8]],[[8,7],[7,9],[8,9],[9,8],[9,7],[7,8]],[[8,8],[9,9],[7,10],[8,10],[7,9],[9,8]],[[9,10],[9,9],[7,10],[8,9],[7,11],[8,11]],[[9,10],[8,10],[9,11],[7,11]],[[8,1],[8,0],[10,0],[9,1]],[[9,0],[8,1],[10,1],[9,2],[10,0],[8,2]],[[9,3],[10,1],[8,3],[8,2],[9,1],[10,2]],[[8,4],[9,2],[8,3],[10,3],[10,2],[9,4]],[[8,4],[9,3],[10,4],[9,5],[10,3],[8,5]],[[10,5],[10,4],[9,6],[8,6],[8,5],[9,4]],[[10,5],[8,7],[9,5],[10,6],[8,6],[9,7]],[[8,8],[8,7],[9,6],[10,7],[10,6],[9,8]],[[8,8],[10,8],[9,9],[10,7],[8,9],[9,7]],[[9,10],[10,8],[8,10],[8,9],[9,8],[10,9]],[[9,9],[8,10],[10,10],[10,9],[9,11],[8,11]],[[9,10],[10,11],[10,10],[8,11]],[[9,0],[11,0],[10,1],[9,1]],[[11,1],[11,0],[9,2],[10,0],[9,1],[10,2]],[[11,1],[9,3],[10,1],[9,2],[11,2],[10,3]],[[9,3],[10,4],[11,3],[11,2],[10,2],[9,4]],[[10,5],[11,3],[9,5],[10,3],[11,4],[9,4]],[[10,4],[9,6],[9,5],[10,6],[11,5],[11,4]],[[10,5],[9,6],[10,7],[11,6],[11,5],[9,7]],[[11,7],[10,8],[11,6],[10,6],[9,8],[9,7]],[[11,7],[9,9],[10,7],[9,8],[10,9],[11,8]],[[9,10],[10,8],[9,9],[11,9],[10,10],[11,8]],[[9,10],[10,11],[11,10],[11,9],[10,9],[9,11]],[[11,10],[10,10],[9,11],[11,11]],[[11,1],[10,0],[10,1]],[[11,0],[10,1],[11,2],[10,2]],[[11,1],[11,3],[10,3],[10,2]],[[10,4],[11,2],[10,3],[11,4]],[[10,5],[10,4],[11,3],[11,5]],[[10,5],[11,6],[10,6],[11,4]],[[11,7],[10,7],[10,6],[11,5]],[[10,8],[10,7],[11,6],[11,8]],[[11,7],[10,8],[11,9],[10,9]],[[11,10],[10,10],[10,9],[11,8]],[[10,11],[11,9],[10,10],[11,11]],[[10,11],[11,10]]],"13":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[0,9],[1,7]],[[0,10],[1,8],[0,8],[1,9]],[[0,9],[1,10],[1,9],[0,11]],[[0,10],[1,11],[0,12],[1,10]],[[1,12],[1,11],[0,11]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[0,9],[1,7],[0,8],[1,9],[2,8]],[[0,10],[1,8],[0,9],[2,9],[1,10],[2,8]],[[0,10],[1,11],[2,10],[2,9],[1,9],[0,11]],[[1,12],[2,10],[0,12],[1,10],[2,11],[0,11]],[[1,11],[0,12],[2,12],[2,11]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8],[2,9],[1,9]],[[3,8],[2,10],[3,9],[1,10],[1,9],[2,8]],[[1,11],[3,10],[2,9],[3,9],[1,10],[2,11]],[[1,12],[1,11],[2,10],[3,10],[2,12],[3,11]],[[1,12],[3,12],[2,11],[3,11]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[2,9],[3,9],[4,8],[4,7],[2,8]],[[3,8],[4,9],[2,10],[3,10],[2,9],[4,8]],[[4,10],[4,9],[2,10],[3,9],[2,11],[3,11]],[[4,10],[3,10],[2,12],[3,12],[4,11],[2,11]],[[4,12],[2,12],[4,11],[3,11]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[4,9],[5,7],[3,9],[4,7]],[[4,10],[5,8],[3,10],[3,9],[4,8],[5,9]],[[4,9],[3,10],[5,10],[5,9],[4,11],[3,11]],[[4,10],[5,11],[4,12],[5,10],[3,12],[3,11]],[[5,11],[3,12],[4,11],[5,12]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[4,9],[6,8],[5,7],[6,7],[4,8],[5,9]],[[4,10],[5,8],[4,9],[6,8],[5,10],[6,9]],[[4,10],[5,11],[6,10],[5,9],[4,11],[6,9]],[[6,11],[4,12],[5,10],[6,10],[4,11],[5,12]],[[6,12],[5,11],[6,11],[4,12]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[5,9],[6,9],[7,8]],[[6,8],[7,9],[5,10],[6,10],[5,9],[7,8]],[[5,11],[6,11],[7,10],[7,9],[5,10],[6,9]],[[6,12],[5,11],[7,10],[6,10],[7,11],[5,12]],[[6,11],[7,12],[7,11],[5,12]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8],[7,9],[6,9]],[[8,8],[7,10],[8,9],[6,10],[6,9],[7,8]],[[6,11],[8,10],[7,9],[8,9],[6,10],[7,11]],[[6,12],[6,11],[7,10],[8,10],[7,12],[8,11]],[[6,12],[8,12],[7,11],[8,11]],[[9,0],[7,1],[8,1],[7,0]],[[9,0],[7,1],[8,0],[7,2],[8,2],[9,1]],[[8,1],[9,2],[7,3],[8,3],[7,2],[9,1]],[[7,4],[8,4],[9,3],[9,2],[7,3],[8,2]],[[7,4],[9,3],[8,3],[7,5],[8,5],[9,4]],[[8,4],[9,5],[7,6],[8,6],[7,5],[9,4]],[[7,7],[8,7],[9,6],[9,5],[7,6],[8,5]],[[8,8],[7,7],[9,6],[8,6],[9,7],[7,8]],[[8,7],[7,9],[8,9],[9,8],[9,7],[7,8]],[[8,8],[9,9],[7,10],[8,10],[7,9],[9,8]],[[9,10],[9,9],[7,10],[8,9],[7,11],[8,11]],[[9,10],[8,10],[7,12],[8,12],[9,11],[7,11]],[[9,12],[7,12],[9,11],[8,11]],[[8,1],[8,0],[10,0],[9,1]],[[9,0],[8,1],[10,1],[9,2],[10,0],[8,2]],[[9,3],[10,1],[8,3],[8,2],[9,1],[10,2]],[[8,4],[9,2],[8,3],[10,3],[10,2],[9,4]],[[8,4],[9,3],[10,4],[9,5],[10,3],[8,5]],[[10,5],[10,4],[9,6],[8,6],[8,5],[9,4]],[[10,5],[8,7],[9,5],[10,6],[8,6],[9,7]],[[8,8],[8,7],[9,6],[10,7],[10,6],[9,8]],[[8,8],[10,8],[9,9],[10,7],[8,9],[9,7]],[[9,10],[10,8],[8,10],[8,9],[9,8],[10,9]],[[9,9],[8,10],[10,10],[10,9],[9,11],[8,11]],[[9,10],[10,11],[9,12],[10,10],[8,12],[8,11]],[[10,11],[8,12],[9,11],[10,12]],[[9,0],[11,0],[10,1],[9,1]],[[11,1],[11,0],[9,2],[10,0],[9,1],[10,2]],[[11,1],[9,3],[10,1],[9,2],[11,2],[10,3]],[[9,3],[10,4],[11,3],[11,2],[10,2],[9,4]],[[10,5],[11,3],[9,5],[10,3],[11,4],[9,4]],[[10,4],[9,6],[9,5],[10,6],[11,5],[11,4]],[[10,5],[9,6],[10,7],[11,6],[11,5],[9,7]],[[11,7],[10,8],[11,6],[10,6],[9,8],[9,7]],[[11,7],[9,9],[10,7],[9,8],[10,9],[11,8]],[[9,10],[10,8],[9,9],[11,9],[10,10],[11,8]],[[9,10],[10,11],[11,10],[11,9],[10,9],[9,11]],[[11,10],[9,12],[10,10],[9,11],[10,12],[11,11]],[[10,11],[9,12],[11,12],[11,11]],[[11,1],[12,0],[10,1],[10,0]],[[12,1],[11,0],[12,0],[10,1],[11,2],[10,2]],[[11,1],[12,1],[11,3],[12,2],[10,3],[10,2]],[[10,4],[12,3],[11,2],[12,2],[10,3],[11,4]],[[12,4],[10,5],[10,4],[11,3],[12,3],[11,5]],[[12,4],[10,5],[11,6],[10,6],[12,5],[11,4]],[[11,7],[10,7],[12,6],[10,6],[11,5],[12,5]],[[12,7],[10,8],[10,7],[11,6],[12,6],[11,8]],[[11,7],[12,7],[10,8],[11,9],[10,9],[12,8]],[[11,10],[12,9],[10,10],[10,9],[11,8],[12,8]],[[10,11],[12,10],[11,9],[12,9],[10,10],[11,11]],[[10,11],[11,10],[12,10],[11,12],[12,11],[10,12]],[[12,12],[12,11],[10,12],[11,11]],[[11,1],[12,1],[11,0]],[[11,1],[12,0],[11,2],[12,2]],[[12,1],[11,3],[12,3],[11,2]],[[12,4],[11,3],[12,2],[11,4]],[[12,3],[11,5],[12,5],[11,4]],[[12,4],[11,6],[12,6],[11,5]],[[11,7],[12,7],[11,6],[12,5]],[[11,7],[12,6],[11,8],[12,8]],[[12,7],[11,9],[12,9],[11,8]],[[11,10],[12,10],[11,9],[12,8]],[[11,10],[12,9],[12,11],[11,11]],[[12,10],[11,12],[12,12],[11,11]],[[11,12],[12,11]]],"14":[[[0,1],[1,0]],[[0,0],[1,1],[0,2],[1,0]],[[0,1],[1,2],[1,1],[0,3]],[[1,2],[0,4],[0,2],[1,3]],[[0,3],[1,4],[0,5],[1,3]],[[0,4],[1,5],[1,4],[0,6]],[[0,7],[1,5],[0,5],[1,6]],[[0,6],[1,7],[1,6],[0,8]],[[0,7],[1,8],[0,9],[1,7]],[[0,10],[1,8],[0,8],[1,9]],[[0,9],[1,10],[1,9],[0,11]],[[0,10],[1,11],[0,12],[1,10]],[[1,12],[1,11],[0,13],[0,11]],[[0,12],[1,12],[1,13]],[[0,1],[0,0],[1,1],[2,0]],[[0,1],[1,2],[2,1],[2,0],[0,2],[1,0]],[[2,1],[1,1],[0,3],[0,2],[2,2],[1,3]],[[1,2],[0,4],[0,3],[1,4],[2,3],[2,2]],[[2,4],[0,4],[1,5],[2,3],[0,5],[1,3]],[[2,4],[1,4],[0,6],[0,5],[1,6],[2,5]],[[0,7],[1,5],[0,6],[1,7],[2,6],[2,5]],[[0,7],[2,7],[1,8],[2,6],[1,6],[0,8]],[[2,7],[0,9],[1,7],[0,8],[1,9],[2,8]],[[0,10],[1,8],[0,9],[2,9],[1,10],[2,8]],[[0,10],[1,11],[2,10],[2,9],[1,9],[0,11]],[[1,12],[2,10],[0,12],[1,10],[2,11],[0,11]],[[1,11],[0,13],[0,12],[1,13],[2,12],[2,11]],[[1,12],[0,13],[2,13],[2,12]],[[2,1],[1,1],[3,0],[1,0]],[[1,2],[3,1],[1,1],[2,0],[3,0],[2,2]],[[1,2],[2,1],[3,1],[2,3],[3,2],[1,3]],[[2,4],[1,4],[3,3],[2,2],[3,2],[1,3]],[[3,4],[1,5],[1,4],[2,3],[3,3],[2,5]],[[2,4],[3,4],[1,5],[2,6],[1,6],[3,5]],[[2,7],[1,7],[3,6],[1,6],[2,5],[3,5]],[[3,7],[1,8],[1,7],[2,6],[3,6],[2,8]],[[3,8],[2,7],[3,7],[1,8],[2,9],[1,9]],[[3,8],[2,10],[3,9],[1,10],[1,9],[2,8]],[[1,11],[3,10],[2,9],[3,9],[1,10],[2,11]],[[1,12],[1,11],[2,10],[3,10],[2,12],[3,11]],[[1,12],[2,13],[1,13],[3,12],[2,11],[3,11]],[[3,13],[1,13],[2,12],[3,12]],[[4,0],[2,1],[3,1],[2,0]],[[4,0],[2,1],[3,0],[2,2],[3,2],[4,1]],[[3,1],[4,2],[2,3],[3,3],[2,2],[4,1]],[[2,4],[3,4],[4,3],[4,2],[2,3],[3,2]],[[4,4],[2,4],[4,3],[3,3],[2,5],[3,5]],[[4,4],[3,4],[4,5],[2,6],[3,6],[2,5]],[[2,7],[3,7],[4,6],[4,5],[2,6],[3,5]],[[3,8],[2,7],[4,6],[3,6],[4,7],[2,8]],[[3,7],[2,9],[3,9],[4,8],[4,7],[2,8]],[[3,8],[4,9],[2,10],[3,10],[2,9],[4,8]],[[4,10],[4,9],[2,10],[3,9],[2,11],[3,11]],[[4,10],[3,10],[2,12],[3,12],[4,11],[2,11]],[[4,12],[2,13],[3,13],[2,12],[4,11],[3,11]],[[4,13],[4,12],[2,13],[3,12]],[[3,1],[3,0],[5,0],[4,1]],[[4,0],[3,1],[5,1],[4,2],[5,0],[3,2]],[[4,3],[5,1],[3,3],[3,2],[4,1],[5,2]],[[4,4],[3,4],[4,2],[3,3],[5,3],[5,2]],[[3,4],[4,3],[5,4],[4,5],[5,3],[3,5]],[[4,4],[5,5],[5,4],[4,6],[3,6],[3,5]],[[5,5],[3,7],[4,5],[5,6],[3,6],[4,7]],[[3,8],[3,7],[4,6],[5,7],[5,6],[4,8]],[[3,8],[5,8],[4,9],[5,7],[3,9],[4,7]],[[4,10],[5,8],[3,10],[3,9],[4,8],[5,9]],[[4,9],[3,10],[5,10],[5,9],[4,11],[3,11]],[[4,10],[5,11],[4,12],[5,10],[3,12],[3,11]],[[5,11],[4,13],[3,13],[3,12],[4,11],[5,12]],[[4,12],[5,13],[3,13],[5,12]],[[4,0],[5,1],[6,0],[4,1]],[[6,1],[4,2],[5,0],[6,0],[4,1],[5,2]],[[6,2],[4,3],[6,1],[5,1],[4,2],[5,3]],[[4,4],[6,2],[4,3],[5,4],[6,3],[5,2]],[[4,4],[5,5],[6,4],[4,5],[5,3],[6,3]],[[6,5],[5,4],[4,6],[6,4],[4,5],[5,6]],[[5,5],[6,5],[4,6],[5,7],[6,6],[4,7]],[[5,8],[6,7],[5,6],[4,8],[6,6],[4,7]],[[4,9],[6,8],[5,7],[6,7],[4,8],[5,9]],[[4,10],[5,8],[4,9],[6,8],[5,10],[6,9]],[[4,10],[5,11],[6,10],[5,9],[4,11],[6,9]],[[6,11],[4,12],[5,10],[6,10],[4,11],[5,12]],[[6,12],[5,11],[4,13],[6,11],[4,12],[5,13]],[[6,12],[4,13],[6,13],[5,12]],[[6,1],[7,0],[5,1],[5,0]],[[6,2],[7,1],[7,0],[5,1],[6,0],[5,2]],[[7,1],[6,1],[7,2],[5,3],[6,3],[5,2]],[[6,2],[5,4],[6,4],[7,3],[7,2],[5,3]],[[7,4],[5,5],[6,5],[5,4],[7,3],[6,3]],[[7,4],[5,5],[6,4],[5,6],[6,6],[7,5]],[[6,5],[5,7],[6,7],[7,6],[5,6],[7,5]],[[7,7],[5,8],[6,8],[5,7],[7,6],[6,6]],[[7,7],[5,8],[6,7],[5,9],[6,9],[7,8]],[[6,8],[7,9],[5,10],[6,10],[5,9],[7,8]],[[5,11],[6,11],[7,10],[7,9],[5,10],[6,9]],[[6,12],[5,11],[7,10],[6,10],[7,11],[5,12]],[[6,11],[5,13],[6,13],[7,12],[7,11],[5,12]],[[6,12],[7,13],[5,13],[7,12]],[[7,1],[6,1],[8,0],[6,0]],[[6,2],[8,1],[6,1],[7,0],[8,0],[7,2]],[[6,2],[7,1],[8,1],[7,3],[8,2],[6,3]],[[7,4],[6,4],[8,3],[7,2],[8,2],[6,3]],[[8,4],[6,5],[6,4],[7,3],[8,3],[7,5]],[[7,4],[8,4],[6,5],[7,6],[6,6],[8,5]],[[7,7],[6,7],[8,6],[6,6],[7,5],[8,5]],[[8,7],[6,8],[6,7],[7,6],[8,6],[7,8]],[[8,8],[7,7],[8,7],[6,8],[7,9],[6,9]],[[8,8],[7,10],[8,9],[6,10],[6,9],[7,8]],[[6,11],[8,10],[7,9],[8,9],[6,10],[7,11]],[[6,12],[6,11],[7,10],[8,10],[7,12],[8,11]],[[6,12],[7,13],[6,13],[8,12],[7,11],[8,11]],[[8,13],[6,13],[7,12],[8,12]],[[9,0],[7,1],[8,1],[7,0]],[[9,0],[7,1],[8,0],[7,2],[8,2],[9,1]],[[8,1],[9,2],[7,3],[8,3],[7,2],[9,1]],[[7,4],[8,4],[9,3],[9,2],[7,3],[8,2]],[[7,4],[9,3],[8,3],[7,5],[8,5],[9,4]],[[8,4],[9,5],[7,6],[8,6],[7,5],[9,4]],[[7,7],[8,7],[9,6],[9,5],[7,6],[8,5]],[[8,8],[7,7],[9,6],[8,6],[9,7],[7,8]],[[8,7],[7,9],[8,9],[9,8],[9,7],[7,8]],[[8,8],[9,9],[7,10],[8,10],[7,9],[9,8]],[[9,10],[9,9],[7,10],[8,9],[7,11],[8,11]],[[9,10],[8,10],[7,12],[8,12],[9,11],[7,11]],[[9,12],[7,13],[8,13],[7,12],[9,11],[8,11]],[[9,13],[9,12],[7,13],[8,12]],[[8,1],[8,0],[10,0],[9,1]],[[9,0],[8,1],[10,1],[9,2],[10,0],[8,2]],[[9,3],[10,1],[8,3],[8,2],[9,1],[10,2]],[[8,4],[9,2],[8,3],[10,3],[10,2],[9,4]],[[8,4],[9,3],[10,4],[9,5],[10,3],[8,5]],[[10,5],[10,4],[9,6],[8,6],[8,5],[9,4]],[[10,5],[8,7],[9,5],[10,6],[8,6],[9,7]],[[8,8],[8,7],[9,6],[10,7],[10,6],[9,8]],[[8,8],[10,8],[9,9],[10,7],[8,9],[9,7]],[[9,10],[10,8],[8,10],[8,9],[9,8],[10,9]],[[9,9],[8,10],[10,10],[10,9],[9,11],[8,11]],[[9,10],[10,11],[9,12],[10,10],[8,12],[8,11]],[[10,11],[9,13],[8,13],[8,12],[9,11],[10,12]],[[9,12],[10,13],[8,13],[10,12]],[[9,0],[11,0],[10,1],[9,1]],[[11,1],[11,0],[9,2],[10,0],[9,1],[10,2]],[[11,1],[9,3],[10,1],[9,2],[11,2],[10,3]],[[9,3],[10,4],[11,3],[11,2],[10,2],[9,4]],[[10,5],[11,3],[9,5],[10,3],[11,4],[9,4]],[[10,4],[9,6],[9,5],[10,6],[11,5],[11,4]],[[10,5],[9,6],[10,7],[11,6],[11,5],[9,7]],[[11,7],[10,8],[11,6],[10,6],[9,8],[9,7]],[[11,7],[9,9],[10,7],[9,8],[10,9],[11,8]],[[9,10],[10,8],[9,9],[11,9],[10,10],[11,8]],[[9,10],[10,11],[11,10],[11,9],[10,9],[9,11]],[[11,10],[9,12],[10,10],[9,11],[10,12],[11,11]],[[10,11],[9,13],[9,12],[10,13],[11,12],[11,11]],[[9,13],[11,13],[11,12],[10,12]],[[11,1],[12,0],[10,1],[10,0]],[[12,1],[11,0],[12,0],[10,1],[11,2],[10,2]],[[11,1],[12,1],[11,3],[12,2],[10,3],[10,2]],[[10,4],[12,3],[11,2],[12,2],[10,3],[11,4]],[[12,4],[10,5],[10,4],[11,3],[12,3],[11,5]],[[12,4],[10,5],[11,6],[10,6],[12,5],[11,4]],[[11,7],[10,7],[12,6],[10,6],[11,5],[12,5]],[[12,7],[10,8],[10,7],[11,6],[12,6],[11,8]],[[11,7],[12,7],[10,8],[11,9],[10,9],[12,8]],[[11,10],[12,9],[10,10],[10,9],[11,8],[12,8]],[[10,11],[12,10],[11,9],[12,9],[10,10],[11,11]],[[10,11],[11,10],[12,10],[11,12],[12,11],[10,12]],[[11,13],[10,13],[12,12],[12,11],[10,12],[11,11]],[[12,13],[10,13],[11,12],[12,12]],[[11,1],[12,1],[11,0],[13,0]],[[11,1],[13,1],[12,0],[13,0],[11,2],[12,2]],[[12,1],[13,1],[11,3],[12,3],[11,2],[13,2]],[[12,4],[11,3],[13,3],[12,2],[13,2],[11,4]],[[13,4],[12,3],[13,3],[11,5],[12,5],[11,4]],[[12,4],[13,4],[11,6],[12,6],[11,5],[13,5]],[[11,7],[12,7],[11,6],[13,6],[12,5],[13,5]],[[11,7],[13,7],[12,6],[13,6],[11,8],[12,8]],[[13,8],[12,7],[13,7],[11,9],[12,9],[11,8]],[[13,8],[11,10],[12,10],[11,9],[13,9],[12,8]],[[11,10],[13,10],[12,9],[13,9],[12,11],[11,11]],[[12,10],[13,10],[11,12],[12,12],[13,11],[11,11]],[[11,13],[12,13],[11,12],[13,12],[12,11],[13,11]],[[11,13],[13,13],[12,12],[13,12]],[[12,0],[12,1],[13,1]],[[12,1],[13,0],[12,2],[13,2]],[[13,1],[12,3],[13,3],[12,2]],[[12,4],[13,4],[12,3],[13,2]],[[12,4],[13,3],[12,5],[13,5]],[[13,4],[12,6],[13,6],[12,5]],[[12,7],[13,7],[12,6],[13,5]],[[13,8],[12,7],[13,6],[12,8]],[[13,7],[12,9],[13,9],[12,8]],[[13,8],[12,10],[13,10],[12,9]],[[12,10],[13,9],[12,11],[13,11]],[[13,10],[12,12],[13,12],[12,11]],[[12,13],[13,13],[12,12],[13,11]],[[12,13],[13,12]]]},"cases":[{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":14,"pushes":19},{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":"Blue","path":[[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":14,"pushes":19},{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":"Red","path":[[4,2],[3,2],[3,1],[2,1],[1,1],[0,1],[0,0]],"pops":15,"pushes":20},{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":17,"pushes":20},{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":"Blue","path":[[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":17,"pushes":20},{"name":"sample_input.json","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":"Red","path":[[4,2],[3,2],[2,2],[1,2],[1,1],[0,1],[0,0]],"pops":18,"pushes":24},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[[4,2],[4,1],[4,0],[3,0],[2,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":16,"pushes":17},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":"Blue","path":[[4,2],[4,1],[4,0],[3,0],[2,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":16,"pushes":17},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"manhattan","block":"Red","path":[[4,2],[3,2],[3,1],[2,1],[1,1],[0,1],[0,0]],"pops":15,"pushes":20},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[[4,2],[4,1],[4,0],[3,0],[2,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":17,"pushes":17},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":"Blue","path":[[4,2],[4,1],[4,0],[3,0],[2,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":17,"pushes":17},{"name":"sample_input2.json","input":{"n":5,"board":[["b",3,1],["b",3,2],["b",3,3],["b",3,4],["b",1,0],["b",1,1],["b",1,2],["b",1,3]],"start":[4,2],"goal":[0,0]},"heuristic":"euclidean","block":"Red","path":[[4,2],[3,2],[2,2],[1,2],[1,1],[0,1],[0,0]],"pops":18,"pushes":24},{"name":"notebook-1","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[1,4]},"heuristic":"manhattan","block":null,"path":[[4,2],[3,3],[2,4],[1,4]],"pops":4,"pushes":8},{"name":"notebook-1","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,2],"goal":[1,4]},"heuristic":"euclidean","block":null,"path":[[4,2],[3,3],[2,4],[1,4]],"pops":4,"pushes":8},{"name":"notebook-2","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,0],"goal":[0,4]},"heuristic":"manhattan","block":null,"path":[[4,0],[3,1],[2,2],[1,2],[0,3],[0,4]],"pops":6,"pushes":11},{"name":"notebook-2","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3]],"start":[4,0],"goal":[0,4]},"heuristic":"euclidean","block":null,"path":[[4,0],[3,1],[2,2],[1,2],[0,3],[0,4]],"pops":6,"pushes":11},{"name":"notebook-3","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3]],"start":[0,0],"goal":[0,4]},"heuristic":"manhattan","block":null,"path":[[0,0],[0,1],[0,2],[1,2],[2,2],[2,3],[1,4],[0,4]],"pops":8,"pushes":12},{"name":"notebook-3","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3]],"start":[0,0],"goal":[0,4]},"heuristic":"euclidean","block":null,"path":[[0,0],[0,1],[0,2],[1,2],[2,2],[2,3],[1,4],[0,4]],"pops":8,"pushes":12},{"name":"notebook-4","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3],["b",2,3]],"start":[4,4],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":19,"pushes":19},{"name":"notebook-4","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3],["b",2,3]],"start":[4,4],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[[4,4],[4,3],[4,2],[4,1],[3,1],[2,1],[1,2],[0,2],[0,1],[0,0]],"pops":19,"pushes":19},{"name":"notebook-5","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3],["b",1,2]],"start":[4,0],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[],"pops":16,"pushes":16},{"name":"notebook-5","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",0,3],["b",1,2]],"start":[4,0],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[],"pops":16,"pushes":16},{"name":"notebook-6","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",1,2]],"start":[4,0],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[[4,0],[3,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":16,"pushes":19},{"name":"notebook-6","input":{"n":5,"board":[["b",1,0],["b",1,1],["b",3,2],["b",1,3],["b",1,2]],"start":[4,0],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[[4,0],[3,1],[2,2],[2,3],[1,4],[0,4],[0,3],[0,2],[0,1],[0,0]],"pops":19,"pushes":20},{"name":"random-0","input":{"n":5,"board":[["r",0,3],["r",1,0],["b",3,1],["r",4,0]],"start":[4,2],"goal":[2,3]},"heuristic":"manhattan","block":"Red","path":[[4,2],[3,3],[2,3]],"pops":3,"pushes":8},{"name":"random-0","input":{"n":5,"board":[["r",0,3],["r",1,0],["b",3,1],["r",4,0]],"start":[4,2],"goal":[2,3]},"heuristic":"euclidean","block":"Red","path":[[4,2],[3,3],[2,3]],"pops":3,"pushes":8},{"name":"random-1","input":{"n":14,"board":[["b",0,1],["b",0,2],["b",0,4],["b",0,5],["b",0,6],["r",0,7],["r",0,8],["b",0,10],["r",0,11],["b",1,0],["r",1,3],["b",1,6],["b",1,9],["b",1,11],["b",2,0],["r",2,1],["r",2,2],["r",2,3],["b",2,4],["b",2,5],["b",2,7],["b",2,9],["r",2,12],["r",2,13],["r",3,4],["b",3,6],["r",3,8],["b",3,9],["r",3,10],["b",3,11],["r",4,0],["r",4,1],["b",4,2],["r",4,3],["r",4,4],["r",4,6],["b",4,7],["b",4,10],["b",4,12],["r",5,1],["b",5,2],["b",5,3],["r",5,5],["r",5,6],["r",5,7],["r",5,10],["r",5,11],["b",5,12],["r",6,0],["r",6,1],["b",6,2],["r",6,3],["b",6,7],["r",6,10],["b",6,11],["r",6,12],["r",7,1],["b",7,3],["r",7,5],["r",7,6],["b",7,8],["r",7,9],["r",7,12],["r",7,13],["r",8,1],["b",8,6],["b",8,10],["r",9,0],["r",9,1],["r",9,4],["r",9,5],["r",9,8],["b",9,11],["b",9,13],["r",10,0],["r",10,1],["b",10,2],["r",10,3],["r",10,10],["b",10,11],["b",10,12],["r",10,13],["b",11,0],["r",11,2],["b",11,3],["b",11,4],["r",11,5],["r",11,7],["r",11,8],["r",11,9],["b",11,10],["b",12,0],["r",12,1],["b",12,2],["r",12,3],["r",12,5],["b",12,6],["r",12,8],["b",12,11],["r",12,13],["b",13,1],["r",13,2],["b",13,3],["r",13,4],["r",13,5],["b",13,6],["b",13,8],["r",13,9],["b",13,10],["b",13,11]],"start":[3,2],"goal":[12,9]},"heuristic":"manhattan","block":"Blue","path":[[3,2],[3,3],[3,4],[4,4],[5,4],[5,5],[6,5],[6,6],[7,6],[7,7],[8,7],[8,8],[8,9],[9,9],[10,9],[11,9],[12,9]],"pops":50,"pushes":71},{"name":"random-1","input":{"n":14,"board":[["b",0,1],["b",0,2],["b",0,4],["b",0,5],["b",0,6],["r",0,7],["r",0,8],["b",0,10],["r",0,11],["b",1,0],["r",1,3],["b",1,6],["b",1,9],["b",1,11],["b",2,0],["r",2,1],["r",2,2],["r",2,3],["b",2,4],["b",2,5],["b",2,7],["b",2,9],["r",2,12],["r",2,13],["r",3,4],["b",3,6],["r",3,8],["b",3,9],["r",3,10],["b",3,11],["r",4,0],["r",4,1],["b",4,2],["r",4,3],["r",4,4],["r",4,6],["b",4,7],["b",4,10],["b",4,12],["r",5,1],["b",5,2],["b",5,3],["r",5,5],["r",5,6],["r",5,7],["r",5,10],["r",5,11],["b",5,12],["r",6,0],["r",6,1],["b",6,2],["r",6,3],["b",6,7],["r",6,10],["b",6,11],["r",6,12],["r",7,1],["b",7,3],["r",7,5],["r",7,6],["b",7,8],["r",7,9],["r",7,12],["r",7,13],["r",8,1],["b",8,6],["b",8,10],["r",9,0],["r",9,1],["r",9,4],["r",9,5],["r",9,8],["b",9,11],["b",9,13],["r",10,0],["r",10,1],["b",10,2],["r",10,3],["r",10,10],["b",10,11],["b",10,12],["r",10,13],["b",11,0],["r",11,2],["b",11,3],["b",11,4],["r",11,5],["r",11,7],["r",11,8],["r",11,9],["b",11,10],["b",12,0],["r",12,1],["b",12,2],["r",12,3],["r",12,5],["b",12,6],["r",12,8],["b",12,11],["r",12,13],["b",13,1],["r",13,2],["b",13,3],["r",13,4],["r",13,5],["b",13,6],["b",13,8],["r",13,9],["b",13,10],["b",13,11]],"start":[3,2],"goal":[12,9]},"heuristic":"euclidean","block":"Blue","path":[[3,2],[3,3],[4,3],[4,4],[5,4],[6,4],[7,4],[8,4],[8,5],[9,5],[9,6],[10,6],[10,7],[11,7],[11,8],[11,9],[12,9]],"pops":77,"pushes":99},{"name":"random-2","input":{"n":3,"board":[["b",0,0],["r",0,2]],"start":[1,1],"goal":[0,1]},"heuristic":"manhattan","block":null,"path":[[1,1],[0,1]],"pops":2,"pushes":6},{"name":"random-2","input":{"n":3,"board":[["b",0,0],["r",0,2]],"start":[1,1],"goal":[0,1]},"heuristic":"euclidean","block":null,"path":[[1,1],[0,1]],"pops":2,"pushes":6},{"name":"random-3","input":{"n":13,"board":[["r",0,9],["b",1,1],["b",1,2],["b",1,5],["r",1,7],["b",1,8],["r",1,10],["r",1,11],["b",1,12],["r",2,1],["r",2,2],["b",2,5],["r",2,6],["r",2,8],["r",2,9],["r",3,0],["b",3,1],["r",3,4],["b",3,6],["b",3,7],["r",3,10],["b",3,11],["r",4,3],["b",4,5],["b",4,10],["r",4,12],["r",5,0],["r",5,1],["b",5,5],["b",5,8],["r",5,11],["r",6,1],["r",6,2],["b",6,3],["r",6,5],["b",6,7],["r",7,3],["r",7,7],["b",7,9],["r",7,12],["r",8,3],["b",8,5],["b",8,10],["r",8,11],["r",9,2],["r",9,3],["b",9,5],["r",9,12],["b",10,1],["r",10,6],["b",10,7],["r",10,9],["r",10,10],["b",10,11],["b",11,1],["r",11,7],["b",11,8],["r",11,10],["b",11,11],["r",11,12],["b",12,3],["b",12,7],["r",12,8],["b",12,9],["b",12,10],["r",12,12]],"start":[2,7],"goal":[8,4]},"heuristic":"manhattan","block":"Red","path":[[2,7],[3,6],[4,5],[5,4],[6,4],[7,4],[8,4]],"pops":7,"pushes":16},{"name":"random-3","input":{"n":13,"board":[["r",0,9],["b",1,1],["b",1,2],["b",1,5],["r",1,7],["b",1,8],["r",1,10],["r",1,11],["b",1,12],["r",2,1],["r",2,2],["b",2,5],["r",2,6],["r",2,8],["r",2,9],["r",3,0],["b",3,1],["r",3,4],["b",3,6],["b",3,7],["r",3,10],["b",3,11],["r",4,3],["b",4,5],["b",4,10],["r",4,12],["r",5,0],["r",5,1],["b",5,5],["b",5,8],["r",5,11],["r",6,1],["r",6,2],["b",6,3],["r",6,5],["b",6,7],["r",7,3],["r",7,7],["b",7,9],["r",7,12],["r",8,3],["b",8,5],["b",8,10],["r",8,11],["r",9,2],["r",9,3],["b",9,5],["r",9,12],["b",10,1],["r",10,6],["b",10,7],["r",10,9],["r",10,10],["b",10,11],["b",11,1],["r",11,7],["b",11,8],["r",11,10],["b",11,11],["r",11,12],["b",12,3],["b",12,7],["r",12,8],["b",12,9],["b",12,10],["r",12,12]],"start":[2,7],"goal":[8,4]},"heuristic":"euclidean","block":"Red","path":[[2,7],[3,6],[4,5],[5,4],[6,4],[7,4],[8,4]],"pops":7,"pushes":16},{"name":"random-4","input":{"n":10,"board":[["b",0,7],["b",0,9],["r",1,1],["r",1,4],["b",1,5],["r",1,6],["r",1,7],["b",1,8],["b",2,1],["b",2,3],["b",2,5],["r",2,8],["r",2,9],["r",3,1],["b",3,2],["r",3,4],["r",3,5],["b",3,8],["r",4,1],["b",4,2],["r",4,5],["b",4,8],["r",5,1],["b",5,3],["r",5,4],["r",5,5],["r",5,6],["r",5,7],["r",6,0],["r",6,4],["b",6,9],["r",7,0],["b",7,2],["b",7,3],["r",7,4],["r",7,6],["b",7,9],["r",8,2],["b",9,2],["r",9,4],["b",9,7],["b",9,8]],"start":[8,9],"goal":[6,5]},"heuristic":"manhattan","block":"Blue","path":[[8,9],[8,8],[8,7],[7,7],[6,7],[6,6],[6,5]],"pops":13,"pushes":23},{"name":"random-4","input":{"n":10,"board":[["b",0,7],["b",0,9],["r",1,1],["r",1,4],["b",1,5],["r",1,6],["r",1,7],["b",1,8],["b",2,1],["b",2,3],["b",2,5],["r",2,8],["r",2,9],["r",3,1],["b",3,2],["r",3,4],["r",3,5],["b",3,8],["r",4,1],["b",4,2],["r",4,5],["b",4,8],["r",5,1],["b",5,3],["r",5,4],["r",5,5],["r",5,6],["r",5,7],["r",6,0],["r",6,4],["b",6,9],["r",7,0],["b",7,2],["b",7,3],["r",7,4],["r",7,6],["b",7,9],["r",8,2],["b",9,2],["r",9,4],["b",9,7],["b",9,8]],"start":[8,9],"goal":[6,5]},"heuristic":"euclidean","block":"Blue","path":[[8,9],[8,8],[8,7],[7,7],[7,6],[6,6],[6,5]],"pops":14,"pushes":23},{"name":"random-5","input":{"n":12,"board":[["r",1,2],["b",1,8],["b",2,0],["b",3,0],["r",3,7],["r",3,9],["b",4,3],["b",4,4],["r",5,0],["r",5,2],["b",6,4],["b",6,6],["b",6,8],["b",7,0],["b",8,0],["r",8,3],["r",8,8],["r",9,10]],"start":[8,5],"goal":[0,2]},"heuristic":"manhattan","block":"Blue","path":[[8,5],[8,4],[7,4],[7,3],[7,2],[6,2],[5,2],[4,2],[3,2],[2,2],[1,2],[0,2]],"pops":33,"pushes":54},{"name":"random-5","input":{"n":12,"board":[["r",1,2],["b",1,8],["b",2,0],["b",3,0],["r",3,7],["r",3,9],["b",4,3],["b",4,4],["r",5,0],["r",5,2],["b",6,4],["b",6,6],["b",6,8],["b",7,0],["b",8,0],["r",8,3],["r",8,8],["r",9,10]],"start":[8,5],"goal":[0,2]},"heuristic":"euclidean","block":"Blue","path":[[8,5],[7,5],[6,5],[5,5],[4,5],[3,5],[3,4],[2,4],[1,4],[1,3],[1,2],[0,2]],"pops":43,"pushes":73},{"name":"random-6","input":{"n":6,"board":[["r",0,3],["r",1,0],["r",1,2],["b",1,5],["r",2,2],["b",2,3],["b",3,0],["b",3,1],["b",3,3],["b",5,0],["b",5,2],["r",5,3],["b",5,5]],"start":[0,5],"goal":[1,4]},"heuristic":"manhattan","block":"Red","path":[[0,5],[1,4]],"pops":2,"pushes":4},{"name":"random-6","input":{"n":6,"board":[["r",0,3],["r",1,0],["r",1,2],["b",1,5],["r",2,2],["b",2,3],["b",3,0],["b",3,1],["b",3,3],["b",5,0],["b",5,2],["r",5,3],["b",5,5]],"start":[0,5],"goal":[1,4]},"heuristic":"euclidean","block":"Red","path":[[0,5],[1,4]],"pops":2,"pushes":4},{"name":"random-7","input":{"n":11,"board":[["r",0,1],["b",0,4],["r",0,5],["r",0,7],["r",0,8],["r",1,5],["r",1,6],["b",1,9],["b",2,1],["r",2,2],["r",2,3],["b",2,4],["r",2,6],["r",2,7],["r",2,8],["r",2,9],["r",2,10],["r",3,1],["b",3,2],["b",3,3],["b",3,4],["r",3,5],["r",3,6],["b",3,8],["r",3,10],["b",4,0],["b",4,5],["r",4,6],["b",4,9],["b",5,7],["r",5,8],["r",5,9],["r",6,1],["r",6,3],["b",6,4],["r",6,5],["r",6,8],["b",7,0],["r",7,4],["r",8,0],["b",8,1],["b",8,3],["b",8,4],["b",8,8],["r",8,9],["b",8,10],["r",9,3],["b",9,4],["r",9,7],["r",9,8],["b",10,1],["b",10,3],["r",10,6],["b",10,7],["b",10,8],["r",10,10]],"start":[2,5],"goal":[5,6]},"heuristic":"manhattan","block":"Blue","path":[[2,5],[2,6],[3,6],[4,6],[5,6]],"pops":6,"pushes":14},{"name":"random-7","input":{"n":11,"board":[["r",0,1],["b",0,4],["r",0,5],["r",0,7],["r",0,8],["r",1,5],["r",1,6],["b",1,9],["b",2,1],["r",2,2],["r",2,3],["b",2,4],["r",2,6],["r",2,7],["r",2,8],["r",2,9],["r",2,10],["r",3,1],["b",3,2],["b",3,3],["b",3,4],["r",3,5],["r",3,6],["b",3,8],["r",3,10],["b",4,0],["b",4,5],["r",4,6],["b",4,9],["b",5,7],["r",5,8],["r",5,9],["r",6,1],["r",6,3],["b",6,4],["r",6,5],["r",6,8],["b",7,0],["r",7,4],["r",8,0],["b",8,1],["b",8,3],["b",8,4],["b",8,8],["r",8,9],["b",8,10],["r",9,3],["b",9,4],["r",9,7],["r",9,8],["b",10,1],["b",10,3],["r",10,6],["b",10,7],["b",10,8],["r",10,10]],"start":[2,5],"goal":[5,6]},"heuristic":"euclidean","block":"Blue","path":[[2,5],[3,5],[3,6],[4,6],[5,6]],"pops":6,"pushes":14},{"name":"random-8","input":{"n":14,"board":[["r",0,0],["b",0,7],["r",0,8],["b",0,10],["b",0,13],["b",1,3],["r",1,4],["b",1,5],["r",1,9],["b",1,11],["r",1,13],["b",2,5],["b",3,0],["r",3,2],["r",3,3],["r",3,7],["b",3,9],["b",3,10],["b",4,0],["r",4,1],["b",4,2],["b",4,4],["b",4,5],["r",4,10],["r",4,11],["b",4,12],["r",4,13],["b",5,0],["b",5,2],["r",5,7],["r",5,9],["r",5,10],["b",5,11],["b",5,12],["b",6,5],["r",6,8],["r",6,9],["b",6,13],["r",7,1],["b",7,2],["r",7,3],["b",7,4],["r",8,3],["b",8,7],["r",8,9],["b",8,13],["b",9,2],["b",9,7],["b",9,12],["b",10,2],["b",10,3],["r",10,10],["b",10,11],["b",10,13],["b",11,0],["r",11,1],["r",11,3],["b",11,5],["b",11,6],["b",11,13],["r",12,0],["r",12,2],["b",12,5],["b",12,7],["b",12,13],["b",13,1],["b",13,2],["r",13,4],["r",13,5],["b",13,6],["r",13,11]],"start":[9,13],"goal":[3,1]},"heuristic":"manhattan","block":"Red","path":[[9,13],[9,12],[8,12],[7,12],[7,11],[7,10],[7,9],[7,8],[7,7],[6,7],[6,6],[6,5],[5,5],[5,4],[5,3],[5,2],[5,1],[5,0],[4,0],[3,1]],"pops":109,"pushes":137},{"name":"random-8","input":{"n":14,"board":[["r",0,0],["b",0,7],["r",0,8],["b",0,10],["b",0,13],["b",1,3],["r",1,4],["b",1,5],["r",1,9],["b",1,11],["r",1,13],["b",2,5],["b",3,0],["r",3,2],["r",3,3],["r",3,7],["b",3,9],["b",3,10],["b",4,0],["r",4,1],["b",4,2],["b",4,4],["b",4,5],["r",4,10],["r",4,11],["b",4,12],["r",4,13],["b",5,0],["b",5,2],["r",5,7],["r",5,9],["r",5,10],["b",5,11],["b",5,12],["b",6,5],["r",6,8],["r",6,9],["b",6,13],["r",7,1],["b",7,2],["r",7,3],["b",7,4],["r",8,3],["b",8,7],["r",8,9],["b",8,13],["b",9,2],["b",9,7],["b",9,12],["b",10,2],["b",10,3],["r",10,10],["b",10,11],["b",10,13],["b",11,0],["r",11,1],["r",11,3],["b",11,5],["b",11,6],["b",11,13],["r",12,0],["r",12,2],["b",12,5],["b",12,7],["b",12,13],["b",13,1],["b",13,2],["r",13,4],["r",13,5],["b",13,6],["r",13,11]],"start":[9,13],"goal":[3,1]},"heuristic":"euclidean","block":"Red","path":[[9,13],[9,12],[9,11],[9,10],[9,9],[9,8],[9,7],[8,7],[8,6],[7,6],[7,5],[7,4],[6,4],[5,4],[5,3],[5,2],[5,1],[5,0],[4,0],[3,1]],"pops":129,"pushes":148},{"name":"random-9","input":{"n":6,"board":[["r",1,2],["r",1,5],["b",2,1],["b",2,2],["b",2,4],["r",3,2],["b",4,3],["r",4,4],["b",5,4],["b",5,5]],"start":[3,4],"goal":[4,2]},"heuristic":"manhattan","block":null,"path":[[3,4],[3,3],[4,2]],"pops":3,"pushes":6},{"name":"random-9","input":{"n":6,"board":[["r",1,2],["r",1,5],["b",2,1],["b",2,2],["b",2,4],["r",3,2],["b",4,3],["r",4,4],["b",5,4],["b",5,5]],"start":[3,4],"goal":[4,2]},"heuristic":"euclidean","block":null,"path":[[3,4],[3,3],[4,2]],"pops":3,"pushes":6},{"name":"random-10","input":{"n":8,"board":[["b",0,3],["b",1,0],["b",1,1],["r",1,6],["r",2,3],["b",3,1],["r",3,2],["r",4,0],["r",4,1],["b",4,4],["b",4,5],["r",5,1],["r",5,2],["r",5,3],["r",5,4],["r",5,6],["b",5,7],["r",6,0],["r",6,1],["b",6,7],["b",7,3],["b",7,5],["b",7,7]],"start":[7,0],"goal":[7,1]},"heuristic":"manhattan","block":"Red","path":[[7,0],[7,1]],"pops":2,"pushes":2},{"name":"random-10","input":{"n":8,"board":[["b",0,3],["b",1,0],["b",1,1],["r",1,6],["r",2,3],["b",3,1],["r",3,2],["r",4,0],["r",4,1],["b",4,4],["b",4,5],["r",5,1],["r",5,2],["r",5,3],["r",5,4],["r",5,6],["b",5,7],["r",6,0],["r",6,1],["b",6,7],["b",7,3],["b",7,5],["b",7,7]],"start":[7,0],"goal":[7,1]},"heuristic":"euclidean","block":"Red","path":[[7,0],[7,1]],"pops":2,"pushes":2},{"name":"random-11","input":{"n":6,"board":[["b",2,0],["b",3,5],["b",5,1]],"start":[4,4],"goal":[2,3]},"heuristic":"manhattan","block":"Blue","path":[[4,4],[3,4],[2,4],[2,3]],"pops":6,"pushes":15},{"name":"random-11","input":{"n":6,"board":[["b",2,0],["b",3,5],["b",5,1]],"start":[4,4],"goal":[2,3]},"heuristic":"euclidean","block":"Blue","path":[[4,4],[3,4],[2,4],[2,3]],"pops":6,"pushes":15},{"name":"random-12","input":{"n":14,"board":[["b",0,1],["r",0,5],["r",0,6],["r",0,7],["r",0,12],["b",1,1],["b",1,3],["r",1,5],["b",1,6],["r",1,7],["b",1,9],["b",1,11],["b",2,1],["r",2,2],["r",2,5],["b",2,6],["r",2,7],["b",2,9],["b",2,10],["r",3,0],["r",3,1],["r",3,3],["r",3,4],["r",3,6],["b",3,8],["b",3,9],["b",3,10],["b",3,11],["b",3,13],["b",4,1],["r",4,2],["r",4,3],["b",4,7],["b",4,11],["r",5,1],["r",5,2],["r",5,3],["b",5,4],["r",5,8],["b",5,9],["r",5,11],["r",5,12],["b",6,1],["b",6,2],["b",6,3],["r",6,5],["r",6,6],["b",6,11],["b",6,12],["r",7,0],["b",7,2],["r",7,6],["r",7,10],["b",8,0],["b",8,3],["r",8,5],["b",8,6],["b",8,11],["r",8,13],["r",9,1],["b",9,2],["b",9,3],["r",9,5],["r",9,6],["b",9,8],["r",9,9],["r",9,11],["r",9,13],["r",10,0],["r",10,2],["r",10,3],["r",10,5],["r",10,8],["b",10,9],["r",11,0],["r",11,1],["b",11,3],["r",11,8],["b",11,11],["r",11,13],["b",12,0],["b",12,5],["b",12,6],["r",12,8],["r",12,10],["r",12,11],["r",13,3],["r",13,5],["b",13,6],["r",13,9],["b",13,12]],"start":[0,3],"goal":[6,7]},"heuristic":"manhattan","block":null,"path":[],"pops":8,"pushes":8},{"name":"random-12","input":{"n":14,"board":[["b",0,1],["r",0,5],["r",0,6],["r",0,7],["r",0,12],["b",1,1],["b",1,3],["r",1,5],["b",1,6],["r",1,7],["b",1,9],["b",1,11],["b",2,1],["r",2,2],["r",2,5],["b",2,6],["r",2,7],["b",2,9],["b",2,10],["r",3,0],["r",3,1],["r",3,3],["r",3,4],["r",3,6],["b",3,8],["b",3,9],["b",3,10],["b",3,11],["b",3,13],["b",4,1],["r",4,2],["r",4,3],["b",4,7],["b",4,11],["r",5,1],["r",5,2],["r",5,3],["b",5,4],["r",5,8],["b",5,9],["r",5,11],["r",5,12],["b",6,1],["b",6,2],["b",6,3],["r",6,5],["r",6,6],["b",6,11],["b",6,12],["r",7,0],["b",7,2],["r",7,6],["r",7,10],["b",8,0],["b",8,3],["r",8,5],["b",8,6],["b",8,11],["r",8,13],["r",9,1],["b",9,2],["b",9,3],["r",9,5],["r",9,6],["b",9,8],["r",9,9],["r",9,11],["r",9,13],["r",10,0],["r",10,2],["r",10,3],["r",10,5],["r",10,8],["b",10,9],["r",11,0],["r",11,1],["b",11,3],["r",11,8],["b",11,11],["r",11,13],["b",12,0],["b",12,5],["b",12,6],["r",12,8],["r",12,10],["r",12,11],["r",13,3],["r",13,5],["b",13,6],["r",13,9],["b",13,12]],"start":[0,3],"goal":[6,7]},"heuristic":"euclidean","block":null,"path":[],"pops":8,"pushes":8},{"name":"random-13","input":{"n":12,"board":[["r",1,2],["r",2,5],["b",2,11],["r",3,9],["r",3,10],["r",4,10],["b",5,2],["r",6,0],["b",9,1],["r",9,5],["r",9,7],["r",9,11],["r",10,3],["b",11,4]],"start":[0,11],"goal":[5,4]},"heuristic":"manhattan","block":null,"path":[[0,11],[1,10],[2,9],[3,8],[4,7],[5,6],[5,5],[5,4]],"pops":8,"pushes":21},{"name":"random-13","input":{"n":12,"board":[["r",1,2],["r",2,5],["b",2,11],["r",3,9],["r",3,10],["r",4,10],["b",5,2],["r",6,0],["b",9,1],["r",9,5],["r",9,7],["r",9,11],["r",10,3],["b",11,4]],"start":[0,11],"goal":[5,4]},"heuristic":"euclidean","block":null,"path":[[0,11],[1,10],[2,9],[3,8],[4,7],[5,6],[5,5],[5,4]],"pops":8,"pushes":21},{"name":"random-14","input":{"n":4,"board":[["b",0,3],["r",1,1],["r",2,0],["r",2,3],["r",3,1],["b",3,3]],"start":[3,2],"goal":[3,0]},"heuristic":"manhattan","block":null,"path":[[3,2],[2,2],[2,1],[3,0]],"pops":4,"pushes":6},{"name":"random-14","input":{"n":4,"board":[["b",0,3],["r",1,1],["r",2,0],["r",2,3],["r",3,1],["b",3,3]],"start":[3,2],"goal":[3,0]},"heuristic":"euclidean","block":null,"path":[[3,2],[2,2],[2,1],[3,0]],"pops":4,"pushes":6},{"name":"random-15","input":{"n":2,"board":[["r",0,1],["r",1,1]],"start":[0,0],"goal":[1,0]},"heuristic":"manhattan","block":"Blue","path":[[0,0],[1,0]],"pops":2,"pushes":3},{"name":"random-15","input":{"n":2,"board":[["r",0,1],["r",1,1]],"start":[0,0],"goal":[1,0]},"heuristic":"euclidean","block":"Blue","path":[[0,0],[1,0]],"pops":2,"pushes":3},{"name":"random-16","input":{"n":9,"board":[["b",0,1],["b",0,3],["r",0,7],["r",1,0],["b",1,3],["b",1,5],["b",1,6],["b",1,8],["b",2,1],["b",2,6],["b",2,7],["b",2,8],["b",3,2],["r",3,6],["b",3,7],["b",3,8],["r",4,0],["r",4,1],["b",4,2],["r",4,3],["r",4,4],["r",4,5],["r",4,7],["r",4,8],["r",5,2],["b",5,4],["r",5,5],["b",5,6],["b",5,8],["b",6,0],["b",6,1],["r",6,5],["r",6,6],["b",7,0],["r",7,1],["b",7,2],["b",7,3],["r",7,4],["b",7,6],["b",7,7],["r",8,0],["b",8,1],["r",8,2],["b",8,4],["r",8,5],["b",8,6]],"start":[5,3],"goal":[0,0]},"heuristic":"manhattan","block":"Blue","path":[[5,3],[4,3],[3,3],[2,3],[2,2],[1,2],[1,1],[1,0],[0,0]],"pops":18,"pushes":24},{"name":"random-16","input":{"n":9,"board":[["b",0,1],["b",0,3],["r",0,7],["r",1,0],["b",1,3],["b",1,5],["b",1,6],["b",1,8],["b",2,1],["b",2,6],["b",2,7],["b",2,8],["b",3,2],["r",3,6],["b",3,7],["b",3,8],["r",4,0],["r",4,1],["b",4,2],["r",4,3],["r",4,4],["r",4,5],["r",4,7],["r",4,8],["r",5,2],["b",5,4],["r",5,5],["b",5,6],["b",5,8],["b",6,0],["b",6,1],["r",6,5],["r",6,6],["b",7,0],["r",7,1],["b",7,2],["b",7,3],["r",7,4],["b",7,6],["b",7,7],["r",8,0],["b",8,1],["r",8,2],["b",8,4],["r",8,5],["b",8,6]],"start":[5,3],"goal":[0,0]},"heuristic":"euclidean","block":"Blue","path":[[5,3],[4,3],[3,3],[2,3],[2,2],[1,2],[1,1],[1,0],[0,0]],"pops":22,"pushes":30},{"name":"random-17","input":{"n":11,"board":[["r",0,0],["r",0,8],["b",0,10],["r",1,0],["r",1,1],["b",1,2],["b",1,5],["b",1,6],["r",1,8],["b",2,1],["r",2,3],["r",2,9],["r",3,0],["r",3,2],["b",3,4],["r",3,6],["b",3,8],["r",3,9],["r",3,10],["r",4,0],["r",4,1],["r",4,7],["r",4,9],["r",4,10],["r",5,2],["b",5,4],["r",5,8],["b",5,10],["r",6,0],["b",6,2],["b",6,3],["b",6,4],["b",6,5],["b",6,6],["r",6,9],["b",7,0],["b",7,3],["r",7,6],["r",7,8],["b",7,9],["r",7,10],["r",8,1],["r",8,5],["r",8,6],["b",8,10],["r",9,2],["r",9,6],["b",9,8],["r",10,1],["b",10,3],["r",10,6],["b",10,7],["r",10,8],["b",10,9],["r",10,10]],"start":[2,5],"goal":[2,4]},"heuristic":"manhattan","block":"Blue","path":[[2,5],[2,4]],"pops":2,"pushes":4},{"name":"random-17","input":{"n":11,"board":[["r",0,0],["r",0,8],["b",0,10],["r",1,0],["r",1,1],["b",1,2],["b",1,5],["b",1,6],["r",1,8],["b",2,1],["r",2,3],["r",2,9],["r",3,0],["r",3,2],["b",3,4],["r",3,6],["b",3,8],["r",3,9],["r",3,10],["r",4,0],["r",4,1],["r",4,7],["r",4,9],["r",4,10],["r",5,2],["b",5,4],["r",5,8],["b",5,10],["r",6,0],["b",6,2],["b",6,3],["b",6,4],["b",6,5],["b",6,6],["r",6,9],["b",7,0],["b",7,3],["r",7,6],["r",7,8],["b",7,9],["r",7,10],["r",8,1],["r",8,5],["r",8,6],["b",8,10],["r",9,2],["r",9,6],["b",9,8],["r",10,1],["b",10,3],["r",10,6],["b",10,7],["r",10,8],["b",10,9],["r",10,10]],"start":[2,5],"goal":[2,4]},"heuristic":"euclidean","block":"Blue","path":[[2,5],[2,4]],"pops":2,"pushes":4},{"name":"random-18","input":{"n":13,"board":[["b",0,8],["r",0,10],["r",0,12],["r",1,2],["r",1,5],["b",1,6],["r",1,8],["r",1,10],["r",2,1],["b",2,5],["b",2,7],["r",3,5],["b",3,11],["b",4,7],["r",5,5],["r",5,6],["b",5,7],["r",6,0],["b",6,7],["b",6,8],["b",6,11],["b",7,0],["r",7,7],["b",7,12],["r",8,0],["b",8,6],["r",8,11],["r",8,12],["b",9,8],["b",9,9],["r",10,1],["b",10,2],["b",10,10],["r",11,2],["b",11,8],["b",11,10],["b",12,5]],"start":[1,9],"goal":[4,9]},"heuristic":"manhattan","block":"Red","path":[[1,9],[2,9],[3,9],[4,9]],"pops":4,"pushes":10},{"name":"random-18","input":{"n":13,"board":[["b",0,8],["r",0,10],["r",0,12],["r",1,2],["r",1,5],["b",1,6],["r",1,8],["r",1,10],["r",2,1],["b",2,5],["b",2,7],["r",3,5],["b",3,11],["b",4,7],["r",5,5],["r",5,6],["b",5,7],["r",6,0],["b",6,7],["b",6,8],["b",6,11],["b",7,0],["r",7,7],["b",7,12],["r",8,0],["b",8,6],["r",8,11],["r",8,12],["b",9,8],["b",9,9],["r",10,1],["b",10,2],["b",10,10],["r",11,2],["b",11,8],["b",11,10],["b",12,5]],"start":[1,9],"goal":[4,9]},"heuristic":"euclidean","block":"Red","path":[[1,9],[2,9],[3,9],[4,9]],"pops":4,"pushes":10},{"name":"random-19","input":{"n":10,"board":[["b",0,6],["r",0,7],["r",1,5],["b",1,7],["b",2,8],["b",3,7],["r",4,8],["r",7,3],["b",7,6],["b",7,9],["r",8,0],["r",8,7],["b",9,1]],"start":[0,1],"goal":[3,9]},"heuristic":"manhattan","block":"Red","path":[[0,1],[1,1],[1,2],[2,2],[2,3],[2,4],[3,4],[3,5],[3,6],[3,7],[3,8],[3,9]],"pops":32,"pushes":46},{"name":"random-19","input":{"n":10,"board":[["b",0,6],["r",0,7],["r",1,5],["b",1,7],["b",2,8],["b",3,7],["r",4,8],["r",7,3],["b",7,6],["b",7,9],["r",8,0],["r",8,7],["b",9,1]],"start":[0,1],"goal":[3,9]},"heuristic":"euclidean","block":"Red","path":[[0,1],[0,2],[0,3],[0,4],[0,5],[0,6],[1,6],[1,7],[2,7],[2,8],[3,8],[3,9]],"pops":32,"pushes":46},{"name":"random-20","input":{"n":2,"board":[["b",1,0]],"start":[0,0],"goal":[0,1]},"heuristic":"manhattan","block":null,"path":[[0,0],[0,1]],"pops":2,"pushes":2},{"name":"random-20","input":{"n":2,"board":[["b",1,0]],"start":[0,0],"goal":[0,1]},"heuristic":"euclidean","block":null,"path":[[0,0],[0,1]],"pops":2,"pushes":2},{"name":"random-21","input":{"n":4,"board":[["b",0,0],["b",3,3]],"start":[2,2],"goal":[1,1]},"heuristic":"manhattan","block":"Red","path":[[2,2],[1,2],[1,1]],"pops":4,"pushes":12},{"name":"random-21","input":{"n":4,"board":[["b",0,0],["b",3,3]],"start":[2,2],"goal":[1,1]},"heuristic":"euclidean","block":"Red","path":[[2,2],[1,2],[1,1]],"pops":4,"pushes":12},{"name":"random-22","input":{"n":8,"board":[["b",0,0],["r",0,1],["b",0,2],["b",0,5],["r",0,6],["r",1,1],["r",1,3],["r",1,4],["b",1,6],["b",1,7],["r",2,3],["r",2,7],["b",3,1],["r",3,2],["b",3,3],["b",3,7],["r",4,1],["b",4,3],["r",4,4],["r",5,6],["b",5,7],["b",6,0],["r",6,1],["b",6,5],["b",7,0],["r",7,1],["r",7,3]],"start":[3,4],"goal":[0,3]},"heuristic":"manhattan","block":null,"path":[[3,4],[3,5],[4,5],[5,4],[5,3],[5,2],[5,1],[5,0],[4,0],[3,0],[2,1],[1,2],[0,3]],"pops":28,"pushes":32},{"name":"random-22","input":{"n":8,"board":[["b",0,0],["r",0,1],["b",0,2],["b",0,5],["r",0,6],["r",1,1],["r",1,3],["r",1,4],["b",1,6],["b",1,7],["r",2,3],["r",2,7],["b",3,1],["r",3,2],["b",3,3],["b",3,7],["r",4,1],["b",4,3],["r",4,4],["r",5,6],["b",5,7],["b",6,0],["r",6,1],["b",6,5],["b",7,0],["r",7,1],["r",7,3]],"start":[3,4],"goal":[0,3]},"heuristic":"euclidean","block":null,"path":[[3,4],[3,5],[4,5],[5,4],[5,3],[5,2],[5,1],[5,0],[4,0],[3,0],[2,1],[1,2],[0,3]],"pops":27,"pushes":30},{"name":"random-23","input":{"n":10,"board":[["b",0,0],["b",0,1],["r",0,4],["r",0,5],["b",0,7],["r",1,0],["r",1,3],["r",1,4],["r",1,5],["b",1,6],["b",1,7],["b",1,8],["r",2,0],["r",2,1],["r",2,3],["b",2,6],["b",2,9],["b",3,0],["r",3,2],["r",3,3],["r",3,4],["b",3,5],["r",3,9],["r",4,0],["b",4,1],["b",4,4],["r",4,5],["r",4,7],["r",4,8],["b",5,2],["r",5,3],["r",5,5],["r",5,7],["b",5,8],["b",6,1],["b",6,2],["r",6,5],["b",6,6],["r",6,7],["r",6,8],["r",7,0],["b",7,2],["b",7,3],["b",7,4],["r",7,6],["r",7,7],["r",7,8],["r",8,0],["r",8,2],["r",8,4],["b",8,6],["b",8,7],["r",8,9],["r",9,4],["b",9,5],["r",9,6],["r",9,7],["b",9,8],["b",9,9]],"start":[0,9],"goal":[0,6]},"heuristic":"manhattan","block":"Red","path":[[0,9],[0,8],[0,7],[0,6]],"pops":4,"pushes":8},{"name":"random-23","input":{"n":10,"board":[["b",0,0],["b",0,1],["r",0,4],["r",0,5],["b",0,7],["r",1,0],["r",1,3],["r",1,4],["r",1,5],["b",1,6],["b",1,7],["b",1,8],["r",2,0],["r",2,1],["r",2,3],["b",2,6],["b",2,9],["b",3,0],["r",3,2],["r",3,3],["r",3,4],["b",3,5],["r",3,9],["r",4,0],["b",4,1],["b",4,4],["r",4,5],["r",4,7],["r",4,8],["b",5,2],["r",5,3],["r",5,5],["r",5,7],["b",5,8],["b",6,1],["b",6,2],["r",6,5],["b",6,6],["r",6,7],["r",6,8],["r",7,0],["b",7,2],["b",7,3],["b",7,4],["r",7,6],["r",7,7],["r",7,8],["r",8,0],["r",8,2],["r",8,4],["b",8,6],["b",8,7],["r",8,9],["r",9,4],["b",9,5],["r",9,6],["r",9,7],["b",9,8],["b",9,9]],"start":[0,9],"goal":[0,6]},"heuristic":"euclidean","block":"Red","path":[[0,9],[0,8],[0,7],[0,6]],"pops":4,"pushes":8},{"name":"random-24","input":{"n":9,"board":[["r",0,3],["r",0,5],["r",1,4],["b",4,0],["b",4,1],["b",4,7],["b",6,6],["r",7,0],["b",7,8]],"start":[2,6],"goal":[1,1]},"heuristic":"manhattan","block":"Blue","path":[[2,6],[1,6],[1,5],[1,4],[1,3],[1,2],[1,1]],"pops":12,"pushes":28},{"name":"random-24","input":{"n":9,"board":[["r",0,3],["r",0,5],["r",1,4],["b",4,0],["b",4,1],["b",4,7],["b",6,6],["r",7,0],["b",7,8]],"start":[2,6],"goal":[1,1]},"heuristic":"euclidean","block":"Blue","path":[[2,6],[2,5],[2,4],[2,3],[2,2],[1,2],[1,1]],"pops":15,"pushes":32},{"name":"random-25","input":{"n":3,"board":[],"start":[2,2],"goal":[2,0]},"heuristic":"manhattan","block":"Red","path":[[2,2],[2,1],[2,0]],"pops":3,"pushes":5},{"name":"random-25","input":{"n":3,"board":[],"start":[2,2],"goal":[2,0]},"heuristic":"euclidean","block":"Red","path":[[2,2],[2,1],[2,0]],"pops":3,"pushes":5},{"name":"random-26","input":{"n":7,"board":[["r",0,0],["r",0,2],["r",0,3],["b",0,4],["b",1,0],["r",1,1],["b",1,5],["r",2,2],["b",2,3],["b",2,6],["r",3,0],["r",3,2],["b",3,4],["r",3,6],["r",4,0],["b",4,4],["r",4,6],["r",5,1],["b",5,2],["r",5,3],["r",5,5],["r",5,6],["b",6,1],["r",6,2],["b",6,3],["b",6,4]],"start":[3,1],"goal":[1,4]},"heuristic":"manhattan","block":"Blue","path":[[3,1],[2,2],[1,3],[1,4]],"pops":4,"pushes":11},{"name":"random-26","input":{"n":7,"board":[["r",0,0],["r",0,2],["r",0,3],["b",0,4],["b",1,0],["r",1,1],["b",1,5],["r",2,2],["b",2,3],["b",2,6],["r",3,0],["r",3,2],["b",3,4],["r",3,6],["r",4,0],["b",4,4],["r",4,6],["r",5,1],["b",5,2],["r",5,3],["r",5,5],["r",5,6],["b",6,1],["r",6,2],["b",6,3],["b",6,4]],"start":[3,1],"goal":[1,4]},"heuristic":"euclidean","block":"Blue","path":[[3,1],[2,2],[1,3],[1,4]],"pops":4,"pushes":11},{"name":"random-27","input":{"n":9,"board":[["r",0,2],["b",0,3],["b",0,5],["b",0,6],["r",0,7],["b",1,0],["b",1,3],["b",1,7],["b",1,8],["r",2,0],["b",2,1],["b",2,2],["b",2,5],["b",2,8],["r",3,0],["b",3,1],["b",3,4],["b",3,6],["r",4,1],["b",4,3],["b",4,7],["r",5,0],["b",5,1],["r",5,4],["r",5,5],["r",5,6],["r",5,8],["r",6,0],["r",6,1],["b",6,2],["r",6,4],["b",6,5],["b",6,8],["r",7,0],["r",7,1],["b",7,6],["b",7,7],["b",7,8],["b",8,1],["r",8,2],["r",8,3],["r",8,4],["r",8,6],["b",8,7],["b",8,8]],"start":[6,6],"goal":[4,0]},"heuristic":"manhattan","block":"Red","path":[[6,6],[6,5],[7,4],[7,3],[7,2],[6,2],[5,2],[4,2],[3,2],[3,1],[4,0]],"pops":32,"pushes":43},{"name":"random-27","input":{"n":9,"board":[["r",0,2],["b",0,3],["b",0,5],["b",0,6],["r",0,7],["b",1,0],["b",1,3],["b",1,7],["b",1,8],["r",2,0],["b",2,1],["b",2,2],["b",2,5],["b",2,8],["r",3,0],["b",3,1],["b",3,4],["b",3,6],["r",4,1],["b",4,3],["b",4,7],["r",5,0],["b",5,1],["r",5,4],["r",5,5],["r",5,6],["r",5,8],["r",6,0],["r",6,1],["b",6,2],["r",6,4],["b",6,5],["b",6,8],["r",7,0],["r",7,1],["b",7,6],["b",7,7],["b",7,8],["b",8,1],["r",8,2],["r",8,3],["r",8,4],["r",8,6],["b",8,7],["b",8,8]],"start":[6,6],"goal":[4,0]},"heuristic":"euclidean","block":"Red","path":[[6,6],[6,5],[7,4],[7,3],[7,2],[6,2],[5,2],[4,2],[3,2],[3,1],[4,0]],"pops":33,"pushes":45},{"name":"random-28","input":{"n":14,"board":[["r",0,1],["b",0,2],["r",0,4],["r",0,7],["b",0,10],["r",0,11],["b",0,13],["b",1,2],["b",1,3],["b",1,5],["b",1,7],["b",1,8],["b",1,11],["r",2,3],["r",2,5],["r",2,6],["r",2,7],["r",2,8],["r",2,10],["b",2,11],["r",2,13],["b",3,2],["r",3,5],["r",3,6],["r",3,7],["r",3,10],["r",4,0],["b",4,5],["b",4,6],["b",4,8],["r",4,10],["r",5,2],["r",5,4],["r",6,1],["r",6,2],["b",6,3],["b",6,4],["b",6,5],["r",6,10],["b",6,12],["r",6,13],["r",7,1],["r",7,3],["r",7,4],["r",7,5],["b",7,8],["b",7,11],["b",8,1],["b",8,2],["b",8,3],["r",8,4],["b",8,5],["b",8,6],["r",8,10],["r",8,12],["r",9,2],["r",9,3],["r",9,8],["b",9,11],["r",10,0],["r",10,3],["r",10,6],["r",10,9],["r",10,10],["r",10,11],["r",10,13],["b",11,1],["r",11,2],["b",11,4],["b",11,6],["b",11,7],["b",11,8],["b",11,10],["b",11,11],["b",11,13],["b",12,0],["r",12,3],["b",12,5],["b",12,10],["r",12,13],["b",13,2],["r",13,6],["r",13,12]],"start":[6,8],"goal":[5,5]},"heuristic":"manhattan","block":"Blue","path":[[6,8],[5,8],[5,7],[5,6],[5,5]],"pops":7,"pushes":14},{"name":"random-28","input":{"n":14,"board":[["r",0,1],["b",0,2],["r",0,4],["r",0,7],["b",0,10],["r",0,11],["b",0,13],["b",1,2],["b",1,3],["b",1,5],["b",1,7],["b",1,8],["b",1,11],["r",2,3],["r",2,5],["r",2,6],["r",2,7],["r",2,8],["r",2,10],["b",2,11],["r",2,13],["b",3,2],["r",3,5],["r",3,6],["r",3,7],["r",3,10],["r",4,0],["b",4,5],["b",4,6],["b",4,8],["r",4,10],["r",5,2],["r",5,4],["r",6,1],["r",6,2],["b",6,3],["b",6,4],["b",6,5],["r",6,10],["b",6,12],["r",6,13],["r",7,1],["r",7,3],["r",7,4],["r",7,5],["b",7,8],["b",7,11],["b",8,1],["b",8,2],["b",8,3],["r",8,4],["b",8,5],["b",8,6],["r",8,10],["r",8,12],["r",9,2],["r",9,3],["r",9,8],["b",9,11],["r",10,0],["r",10,3],["r",10,6],["r",10,9],["r",10,10],["r",10,11],["r",10,13],["b",11,1],["r",11,2],["b",11,4],["b",11,6],["b",11,7],["b",11,8],["b",11,10],["b",11,11],["b",11,13],["b",12,0],["r",12,3],["b",12,5],["b",12,10],["r",12,13],["b",13,2],["r",13,6],["r",13,12]],"start":[6,8],"goal":[5,5]},"heuristic":"euclidean","block":"Blue","path":[[6,8],[6,7],[6,6],[5,6],[5,5]],"pops":8,"pushes":15},{"name":"random-29","input":{"n":7,"board":[["b",0,0],["b",0,1],["r",0,2],["b",0,3],["b",0,4],["b",0,6],["b",1,6],["r",2,2],["r",2,3],["r",2,5],["b",3,2],["r",4,0],["b",4,2],["r",4,4],["b",4,5],["r",4,6],["r",6,0],["b",6,2],["b",6,4]],"start":[5,5],"goal":[3,3]},"heuristic":"manhattan","block":"Red","path":[[5,5],[5,4],[5,3],[4,3],[3,3]],"pops":8,"pushes":18},{"name":"random-29","input":{"n":7,"board":[["b",0,0],["b",0,1],["r",0,2],["b",0,3],["b",0,4],["b",0,6],["b",1,6],["r",2,2],["r",2,3],["r",2,5],["b",3,2],["r",4,0],["b",4,2],["r",4,4],["b",4,5],["r",4,6],["r",6,0],["b",6,2],["b",6,4]],"start":[5,5],"goal":[3,3]},"heuristic":"euclidean","block":"Red","path":[[5,5],[5,4],[5,3],[4,3],[3,3]],"pops":8,"pushes":18},{"name":"random-30","input":{"n":5,"board":[["r",0,1],["b",1,0],["r",1,1],["b",1,3],["r",1,4],["b",2,0],["b",2,2],["b",2,3],["r",2,4],["b",3,1],["b",3,3],["r",3,4],["b",4,4]],"start":[4,0],"goal":[0,0]},"heuristic":"manhattan","block":"Blue","path":[[4,0],[3,0],[2,1],[1,1],[0,1],[0,0]],"pops":6,"pushes":9},{"name":"random-30","input":{"n":5,"board":[["r",0,1],["b",1,0],["r",1,1],["b",1,3],["r",1,4],["b",2,0],["b",2,2],["b",2,3],["r",2,4],["b",3,1],["b",3,3],["r",3,4],["b",4,4]],"start":[4,0],"goal":[0,0]},"heuristic":"euclidean","block":"Blue","path":[[4,0],[3,0],[2,1],[1,1],[0,1],[0,0]],"pops":6,"pushes":9},{"name":"random-31","input":{"n":13,"board":[["r",0,0],["r",0,3],["b",0,8],["r",1,1],["b",1,5],["r",1,6],["b",1,7],["r",2,0],["r",2,3],["r",3,1],["b",3,6],["r",3,7],["r",3,8],["b",3,10],["b",4,1],["b",4,7],["r",4,8],["r",4,10],["b",4,12],["b",5,0],["b",5,2],["b",5,4],["r",5,5],["r",5,7],["r",5,10],["r",5,12],["r",6,0],["b",6,10],["b",6,11],["b",7,5],["b",7,8],["r",8,0],["b",8,9],["r",9,12],["r",10,3],["b",10,8],["r",10,10],["b",10,11],["r",10,12],["b",11,1],["b",11,7],["r",11,8],["b",11,10],["r",12,6],["b",12,11]],"start":[10,1],"goal":[6,8]},"heuristic":"manhattan","block":"Blue","path":[[10,1],[9,2],[8,3],[7,4],[6,5],[6,6],[6,7],[6,8]],"pops":8,"pushes":23},{"name":"random-31","input":{"n":13,"board":[["r",0,0],["r",0,3],["b",0,8],["r",1,1],["b",1,5],["r",1,6],["b",1,7],["r",2,0],["r",2,3],["r",3,1],["b",3,6],["r",3,7],["r",3,8],["b",3,10],["b",4,1],["b",4,7],["r",4,8],["r",4,10],["b",4,12],["b",5,0],["b",5,2],["b",5,4],["r",5,5],["r",5,7],["r",5,10],["r",5,12],["r",6,0],["b",6,10],["b",6,11],["b",7,5],["b",7,8],["r",8,0],["b",8,9],["r",9,12],["r",10,3],["b",10,8],["r",10,10],["b",10,11],["r",10,12],["b",11,1],["b",11,7],["r",11,8],["b",11,10],["r",12,6],["b",12,11]],"start":[10,1],"goal":[6,8]},"heuristic":"euclidean","block":"Blue","path":[[10,1],[9,2],[8,3],[7,4],[6,5],[6,6],[6,7],[6,8]],"pops":8,"pushes":23},{"name":"random-32","input":{"n":13,"board":[["r",0,0],["r",0,5],["b",0,7],["r",0,8],["b",1,0],["r",1,1],["b",1,2],["b",1,3],["b",1,6],["b",1,7],["r",1,8],["b",1,9],["b",1,10],["b",2,0],["r",2,2],["r",2,3],["b",2,4],["b",2,6],["r",2,10],["r",2,11],["r",3,0],["b",3,1],["b",3,2],["r",3,3],["b",3,7],["b",3,10],["r",3,11],["r",3,12],["b",4,0],["r",4,3],["r",4,4],["b",4,5],["r",4,6],["r",4,8],["r",4,9],["b",4,12],["b",5,1],["b",5,2],["r",5,4],["b",5,9],["r",5,11],["b",6,1],["r",6,3],["r",6,4],["b",6,5],["b",6,6],["b",6,7],["r",6,8],["r",6,9],["r",6,11],["b",7,0],["r",7,2],["r",7,3],["b",7,5],["b",7,9],["r",7,10],["b",8,1],["b",8,2],["b",8,4],["r",8,8],["r",8,9],["r",8,10],["r",8,12],["b",9,0],["b",9,1],["r",9,2],["b",9,4],["b",9,5],["r",9,6],["b",9,9],["r",9,10],["b",9,11],["r",10,2],["r",10,5],["b",10,6],["b",10,11],["r",10,12],["b",11,1],["r",11,5],["b",11,7],["r",11,9],["r",11,11],["b",11,12],["b",12,0],["r",12,1],["r",12,2],["r",12,4],["r",12,8],["r",12,11],["r",12,12]],"start":[2,7],"goal":[0,9]},"heuristic":"manhattan","block":"Red","path":[[2,7],[2,8],[1,9],[0,9]],"pops":5,"pushes":14},{"name":"random-32","input":{"n":13,"board":[["r",0,0],["r",0,5],["b",0,7],["r",0,8],["b",1,0],["r",1,1],["b",1,2],["b",1,3],["b",1,6],["b",1,7],["r",1,8],["b",1,9],["b",1,10],["b",2,0],["r",2,2],["r",2,3],["b",2,4],["b",2,6],["r",2,10],["r",2,11],["r",3,0],["b",3,1],["b",3,2],["r",3,3],["b",3,7],["b",3,10],["r",3,11],["r",3,12],["b",4,0],["r",4,3],["r",4,4],["b",4,5],["r",4,6],["r",4,8],["r",4,9],["b",4,12],["b",5,1],["b",5,2],["r",5,4],["b",5,9],["r",5,11],["b",6,1],["r",6,3],["r",6,4],["b",6,5],["b",6,6],["b",6,7],["r",6,8],["r",6,9],["r",6,11],["b",7,0],["r",7,2],["r",7,3],["b",7,5],["b",7,9],["r",7,10],["b",8,1],["b",8,2],["b",8,4],["r",8,8],["r",8,9],["r",8,10],["r",8,12],["b",9,0],["b",9,1],["r",9,2],["b",9,4],["b",9,5],["r",9,6],["b",9,9],["r",9,10],["b",9,11],["r",10,2],["r",10,5],["b",10,6],["b",10,11],["r",10,12],["b",11,1],["r",11,5],["b",11,7],["r",11,9],["r",11,11],["b",11,12],["b",12,0],["r",12,1],["r",12,2],["r",12,4],["r",12,8],["r",12,11],["r",12,12]],"start":[2,7],"goal":[0,9]},"heuristic":"euclidean","block":"Red","path":[[2,7],[2,8],[1,9],[0,9]],"pops":5,"pushes":14},{"name":"random-33","input":{"n":5,"board":[["r",0,0],["b",0,1],["b",1,2],["r",2,4],["b",3,2],["b",4,0],["r",4,3]],"start":[1,1],"goal":[3,4]},"heuristic":"manhattan","block":"Blue","path":[[1,1],[2,1],[2,2],[2,3],[2,4],[3,4]],"pops":8,"pushes":17},{"name":"random-33","input":{"n":5,"board":[["r",0,0],["b",0,1],["b",1,2],["r",2,4],["b",3,2],["b",4,0],["r",4,3]],"start":[1,1],"goal":[3,4]},"heuristic":"euclidean","block":"Blue","path":[[1,1],[2,1],[2,2],[2,3],[2,4],[3,4]],"pops":9,"pushes":18},{"name":"random-34","input":{"n":9,"board":[["r",0,0],["r",0,1],["b",0,4],["b",0,5],["r",0,7],["b",1,1],["r",1,2],["b",1,3],["b",1,6],["r",2,5],["r",2,6],["b",3,1],["r",3,4],["r",3,5],["r",3,8],["b",4,7],["r",5,1],["b",6,2],["r",6,4],["r",6,5],["r",6,6],["b",6,8],["r",7,1],["r",7,4],["r",7,6],["r",7,7],["b",7,8],["r",8,6]],"start":[8,2],"goal":[7,0]},"heuristic":"manhattan","block":"Red","path":[[8,2],[8,1],[8,0],[7,0]],"pops":5,"pushes":9},{"name":"random-34","input":{"n":9,"board":[["r",0,0],["r",0,1],["b",0,4],["b",0,5],["r",0,7],["b",1,1],["r",1,2],["b",1,3],["b",1,6],["r",2,5],["r",2,6],["b",3,1],["r",3,4],["r",3,5],["r",3,8],["b",4,7],["r",5,1],["b",6,2],["r",6,4],["r",6,5],["r",6,6],["b",6,8],["r",7,1],["r",7,4],["r",7,6],["r",7,7],["b",7,8],["r",8,6]],"start":[8,2],"goal":[7,0]},"heuristic":"euclidean","block":"Red","path":[[8,2],[8,1],[8,0],[7,0]],"pops":5,"pushes":9},{"name":"random-35","input":{"n":3,"board":[["b",0,1],["r",1,0],["r",1,1]],"start":[1,2],"goal":[2,1]},"heuristic":"manhattan","block":"Red","path":[[1,2],[2,1]],"pops":2,"pushes":4},{"name":"random-35","input":{"n":3,"board":[["b",0,1],["r",1,0],["r",1,1]],"start":[1,2],"goal":[2,1]},"heuristic":"euclidean","block":"Red","path":[[1,2],[2,1]],"pops":2,"pushes":4},{"name":"random-36","input":{"n":13,"board":[["b",0,12],["r",1,5],["b",1,6],["b",2,0],["b",2,3],["b",2,4],["b",2,5],["b",2,6],["r",2,10],["b",2,12],["b",3,0],["r",3,4],["b",3,6],["r",3,12],["b",4,8],["r",5,0],["b",5,7],["b",6,8],["b",6,10],["b",6,11],["r",7,0],["b",7,3],["b",7,4],["r",9,0],["r",9,3],["b",9,6],["b",9,8],["b",9,12],["b",10,10],["r",10,11],["b",11,3],["r",11,9],["r",11,12],["r",12,4]],"start":[1,1],"goal":[9,4]},"heuristic":"manhattan","block":"Blue","path":[[1,1],[1,2],[2,2],[3,2],[4,2],[5,2],[6,2],[7,2],[8,2],[9,2],[9,3],[9,4]],"pops":32,"pushes":55},{"name":"random-36","input":{"n":13,"board":[["b",0,12],["r",1,5],["b",1,6],["b",2,0],["b",2,3],["b",2,4],["b",2,5],["b",2,6],["r",2,10],["b",2,12],["b",3,0],["r",3,4],["b",3,6],["r",3,12],["b",4,8],["r",5,0],["b",5,7],["b",6,8],["b",6,10],["b",6,11],["r",7,0],["b",7,3],["b",7,4],["r",9,0],["r",9,3],["b",9,6],["b",9,8],["b",9,12],["b",10,10],["r",10,11],["b",11,3],["r",11,9],["r",11,12],["r",12,4]],"start":[1,1],"goal":[9,4]},"heuristic":"euclidean","block":"Blue","path":[[1,1],[2,1],[3,1],[4,1],[5,1],[6,1],[6,2],[7,2],[8,2],[8,3],[8,4],[9,4]],"pops":39,"pushes":56},{"name":"random-37","input":{"n":9,"board":[["b",0,1],["r",1,4],["b",2,0],["b",2,6],["b",6,2],["b",8,0],["r",8,2]],"start":[5,2],"goal":[5,6]},"heuristic":"manhattan","block":"Blue","path":[[5,2],[5,3],[5,4],[5,5],[5,6]],"pops":5,"pushes":15},{"name":"random-37","input":{"n":9,"board":[["b",0,1],["r",1,4],["b",2,0],["b",2,6],["b",6,2],["b",8,0],["r",8,2]],"start":[5,2],"goal":[5,6]},"heuristic":"euclidean","block":"Blue","path":[[5,2],[5,3],[5,4],[5,5],[5,6]],"pops":5,"pushes":15},{"name":"random-38","input":{"n":14,"board":[["r",0,2],["b",0,5],["b",0,9],["b",0,10],["b",0,11],["b",2,0],["r",2,7],["b",2,9],["b",2,13],["b",3,2],["b",3,5],["b",3,9],["b",3,10],["b",4,0],["b",4,2],["b",4,8],["r",4,9],["r",4,10],["b",5,1],["r",5,4],["r",5,5],["r",5,10],["r",6,3],["r",6,9],["r",7,4],["b",7,5],["r",7,9],["b",8,2],["b",8,4],["b",8,5],["b",8,12],["r",9,12],["r",9,13],["r",10,4],["b",10,13],["b",11,11],["b",11,12],["r",12,1],["b",12,3],["r",12,5],["b",12,6],["b",12,10],["b",12,12],["r",13,1],["r",13,2],["b",13,4],["b",13,6],["r",13,11],["r",13,12]],"start":[1,11],"goal":[9,1]},"heuristic":"manhattan","block":null,"path":[[1,11],[1,10],[1,9],[2,8],[3,7],[4,6],[5,6],[6,5],[6,4],[7,3],[8,3],[9,2],[9,1]],"pops":16,"pushes":31},{"name":"random-38","input":{"n":14,"board":[["r",0,2],["b",0,5],["b",0,9],["b",0,10],["b",0,11],["b",2,0],["r",2,7],["b",2,9],["b",2,13],["b",3,2],["b",3,5],["b",3,9],["b",3,10],["b",4,0],["b",4,2],["b",4,8],["r",4,9],["r",4,10],["b",5,1],["r",5,4],["r",5,5],["r",5,10],["r",6,3],["r",6,9],["r",7,4],["b",7,5],["r",7,9],["b",8,2],["b",8,4],["b",8,5],["b",8,12],["r",9,12],["r",9,13],["r",10,4],["b",10,13],["b",11,11],["b",11,12],["r",12,1],["b",12,3],["r",12,5],["b",12,6],["b",12,10],["b",12,12],["r",13,1],["r",13,2],["b",13,4],["b",13,6],["r",13,11],["r",13,12]],"start":[1,11],"goal":[9,1]},"heuristic":"euclidean","block":null,"path":[[1,11],[1,10],[1,9],[2,8],[3,7],[4,6],[5,6],[6,5],[6,4],[7,3],[8,3],[9,2],[9,1]],"pops":16,"pushes":31},{"name":"random-39","input":{"n":12,"board":[["b",0,3],["r",0,7],["r",0,11],["r",1,0],["b",1,2],["b",1,5],["r",1,9],["r",1,10],["b",2,0],["r",2,5],["r",2,8],["r",3,0],["r",3,1],["b",3,8],["b",3,9],["b",4,0],["b",4,1],["r",4,3],["r",4,6],["r",4,7],["b",4,10],["b",5,0],["b",5,4],["b",5,9],["r",5,10],["b",6,3],["b",6,5],["r",6,7],["b",6,9],["b",6,10],["r",6,11],["r",7,3],["b",7,4],["b",7,5],["b",7,7],["b",7,8],["r",7,10],["r",7,11],["b",8,0],["r",8,2],["r",8,3],["r",8,4],["b",8,9],["b",8,10],["r",8,11],["b",9,0],["b",9,1],["r",9,2],["b",9,4],["r",9,5],["b",9,6],["b",9,7],["b",9,8],["b",9,9],["b",10,2],["b",10,3],["b",10,4],["r",10,5],["b",10,6],["r",10,7],["r",10,8],["b",10,9],["b",10,10],["b",11,0],["r",11,1],["b",11,3],["b",11,5],["b",11,7],["r",11,8],["b",11,10]],"start":[10,0],"goal":[5,11]},"heuristic":"manhattan","block":"Blue","path":[[10,0],[10,1],[9,2],[8,3],[8,4],[8,5],[7,6],[6,7],[5,8],[4,9],[3,10],[3,11],[4,11],[5,11]],"pops":28,"pushes":42},{"name":"random-39","input":{"n":12,"board":[["b",0,3],["r",0,7],["r",0,11],["r",1,0],["b",1,2],["b",1,5],["r",1,9],["r",1,10],["b",2,0],["r",2,5],["r",2,8],["r",3,0],["r",3,1],["b",3,8],["b",3,9],["b",4,0],["b",4,1],["r",4,3],["r",4,6],["r",4,7],["b",4,10],["b",5,0],["b",5,4],["b",5,9],["r",5,10],["b",6,3],["b",6,5],["r",6,7],["b",6,9],["b",6,10],["r",6,11],["r",7,3],["b",7,4],["b",7,5],["b",7,7],["b",7,8],["r",7,10],["r",7,11],["b",8,0],["r",8,2],["r",8,3],["r",8,4],["b",8,9],["b",8,10],["r",8,11],["b",9,0],["b",9,1],["r",9,2],["b",9,4],["r",9,5],["b",9,6],["b",9,7],["b",9,8],["b",9,9],["b",10,2],["b",10,3],["b",10,4],["r",10,5],["b",10,6],["r",10,7],["r",10,8],["b",10,9],["b",10,10],["b",11,0],["r",11,1],["b",11,3],["b",11,5],["b",11,7],["r",11,8],["b",11,10]],"start":[10,0],"goal":[5,11]},"heuristic":"euclidean","block":"Blue","path":[[10,0],[10,1],[9,2],[8,3],[8,4],[8,5],[8,6],[8,7],[8,8],[7,9],[7,10],[6,11],[5,11]],"pops":23,"pushes":33},{"name":"random-40","input":{"n":8,"board":[["b",0,3],["b",0,5],["r",0,6],["r",1,0],["b",1,2],["r",1,3],["r",1,7],["r",2,1],["r",2,3],["r",2,4],["b",2,7],["r",3,0],["r",3,1],["r",3,2],["r",3,6],["r",4,1],["r",4,2],["b",4,3],["b",4,5],["b",5,2],["b",5,3],["r",5,5],["b",6,2],["b",6,3],["r",6,4],["r",6,7],["r",7,1],["b",7,2],["r",7,3]],"start":[5,1],"goal":[5,0]},"heuristic":"manhattan","block":"Red","path":[[5,1],[5,0]],"pops":2,"pushes":5},{"name":"random-40","input":{"n":8,"board":[["b",0,3],["b",0,5],["r",0,6],["r",1,0],["b",1,2],["r",1,3],["r",1,7],["r",2,1],["r",2,3],["r",2,4],["b",2,7],["r",3,0],["r",3,1],["r",3,2],["r",3,6],["r",4,1],["r",4,2],["b",4,3],["b",4,5],["b",5,2],["b",5,3],["r",5,5],["b",6,2],["b",6,3],["r",6,4],["r",6,7],["r",7,1],["b",7,2],["r",7,3]],"start":[5,1],"goal":[5,0]},"heuristic":"euclidean","block":"Red","path":[[5,1],[5,0]],"pops":2,"pushes":5},{"name":"random-41","input":{"n":9,"board":[["b",0,5],["r",0,6],["r",0,8],["b",1,2],["b",1,4],["r",1,6],["r",1,8],["r",2,0],["b",2,1],["b",2,2],["r",2,3],["b",2,5],["r",2,6],["b",3,0],["b",3,1],["r",3,2],["r",3,4],["b",3,6],["b",3,7],["b",3,8],["b",4,0],["b",4,4],["b",4,8],["r",5,0],["b",5,3],["r",5,4],["r",5,6],["r",5,7],["r",5,8],["b",6,1],["r",6,4],["b",6,6],["r",7,2],["r",7,3],["b",7,4],["r",7,5],["r",8,1],["r",8,8]],"start":[3,5],"goal":[1,1]},"heuristic":"manhattan","block":"Blue","path":[[3,5],[3,4],[2,4],[2,3],[1,3],[0,3],[0,2],[1,1]],"pops":20,"pushes":33},{"name":"random-41","input":{"n":9,"board":[["b",0,5],["r",0,6],["r",0,8],["b",1,2],["b",1,4],["r",1,6],["r",1,8],["r",2,0],["b",2,1],["b",2,2],["r",2,3],["b",2,5],["r",2,6],["b",3,0],["b",3,1],["r",3,2],["r",3,4],["b",3,6],["b",3,7],["b",3,8],["b",4,0],["b",4,4],["b",4,8],["r",5,0],["b",5,3],["r",5,4],["r",5,6],["r",5,7],["r",5,8],["b",6,1],["r",6,4],["b",6,6],["r",7,2],["r",7,3],["b",7,4],["r",7,5],["r",8,1],["r",8,8]],"start":[3,5],"goal":[1,1]},"heuristic":"euclidean","block":"Blue","path":[[3,5],[3,4],[3,3],[2,3],[1,3],[0,3],[0,2],[1,1]],"pops":19,"pushes":32},{"name":"random-42","input":{"n":13,"board":[["r",0,1],["r",0,2],["b",0,3],["r",0,5],["b",0,6],["b",0,11],["r",0,12],["r",1,0],["b",1,4],["b",1,5],["r",1,12],["r",2,0],["r",2,3],["r",2,4],["r",2,5],["r",2,6],["r",2,9],["r",3,2],["b",3,4],["r",3,5],["r",3,8],["r",3,11],["r",4,0],["r",4,5],["b",4,8],["b",4,10],["r",5,2],["r",5,5],["b",5,11],["b",5,12],["b",6,0],["b",6,2],["r",6,3],["b",6,9],["r",6,10],["b",7,0],["r",7,3],["b",7,5],["b",7,8],["b",7,9],["r",7,10],["r",8,1],["r",8,4],["r",8,5],["r",8,7],["r",8,8],["b",8,10],["r",9,1],["r",9,2],["b",9,3],["b",9,6],["b",9,7],["b",9,9],["b",10,1],["r",10,4],["r",10,5],["b",10,7],["b",10,8],["r",10,11],["b",11,1],["r",11,5],["b",11,6],["r",11,8],["b",11,9],["b",11,10],["b",12,0],["r",12,1],["b",12,2],["r",12,5],["r",12,7],["b",12,9],["r",12,10],["r",12,11]],"start":[12,8],"goal":[5,1]},"heuristic":"manhattan","block":null,"path":[],"pops":1,"pushes":1},{"name":"random-42","input":{"n":13,"board":[["r",0,1],["r",0,2],["b",0,3],["r",0,5],["b",0,6],["b",0,11],["r",0,12],["r",1,0],["b",1,4],["b",1,5],["r",1,12],["r",2,0],["r",2,3],["r",2,4],["r",2,5],["r",2,6],["r",2,9],["r",3,2],["b",3,4],["r",3,5],["r",3,8],["r",3,11],["r",4,0],["r",4,5],["b",4,8],["b",4,10],["r",5,2],["r",5,5],["b",5,11],["b",5,12],["b",6,0],["b",6,2],["r",6,3],["b",6,9],["r",6,10],["b",7,0],["r",7,3],["b",7,5],["b",7,8],["b",7,9],["r",7,10],["r",8,1],["r",8,4],["r",8,5],["r",8,7],["r",8,8],["b",8,10],["r",9,1],["r",9,2],["b",9,3],["b",9,6],["b",9,7],["b",9,9],["b",10,1],["r",10,4],["r",10,5],["b",10,7],["b",10,8],["r",10,11],["b",11,1],["r",11,5],["b",11,6],["r",11,8],["b",11,9],["b",11,10],["b",12,0],["r",12,1],["b",12,2],["r",12,5],["r",12,7],["b",12,9],["r",12,10],["r",12,11]],"start":[12,8],"goal":[5,1]},"heuristic":"euclidean","block":null,"path":[],"pops":1,"pushes":1},{"name":"random-43","input":{"n":9,"board":[["r",0,3],["r",0,7],["b",3,0],["r",3,7],["r",5,1],["b",5,2],["b",5,3],["r",5,6],["b",6,4],["b",8,0],["b",8,2],["b",8,6]],"start":[5,0],"goal":[0,5]},"heuristic":"manhattan","block":"Blue","path":[[5,0],[4,1],[3,2],[2,3],[1,4],[0,5]],"pops":6,"pushes":17},{"name":"random-43","input":{"n":9,"board":[["r",0,3],["r",0,7],["b",3,0],["r",3,7],["r",5,1],["b",5,2],["b",5,3],["r",5,6],["b",6,4],["b",8,0],["b",8,2],["b",8,6]],"start":[5,0],"goal":[0,5]},"heuristic":"euclidean","block":"Blue","path":[[5,0],[4,1],[3,2],[2,3],[1,4],[0,5]],"pops":6,"pushes":17},{"name":"random-44","input":{"n":5,"board":[["b",0,1],["r",0,3],["r",0,4],["r",1,1],["b",1,2],["r",1,3],["r",2,0],["b",2,1],["b",3,1],["r",3,2],["r",3,3]],"start":[2,4],"goal":[1,4]},"heuristic":"manhattan","block":"Blue","path":[[2,4],[1,4]],"pops":2,"pushes":5},{"name":"random-44","input":{"n":5,"board":[["b",0,1],["r",0,3],["r",0,4],["r",1,1],["b",1,2],["r",1,3],["r",2,0],["b",2,1],["b",3,1],["r",3,2],["r",3,3]],"start":[2,4],"goal":[1,4]},"heuristic":"euclidean","block":"Blue","path":[[2,4],[1,4]],"pops":2,"pushes":5},{"name":"random-45","input":{"n":6,"board":[["r",0,1],["b",0,2],["b",0,3],["b",0,4],["b",1,1],["b",1,3],["b",2,0],["b",2,2],["r",2,4],["b",3,0],["b",3,1],["r",3,4],["b",3,5],["r",4,1],["b",4,2],["r",4,3],["b",5,0],["r",5,2],["r",5,3],["b",5,4]],"start":[4,4],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[],"pops":3,"pushes":3},{"name":"random-45","input":{"n":6,"board":[["r",0,1],["b",0,2],["b",0,3],["b",0,4],["b",1,1],["b",1,3],["b",2,0],["b",2,2],["r",2,4],["b",3,0],["b",3,1],["r",3,4],["b",3,5],["r",4,1],["b",4,2],["r",4,3],["b",5,0],["r",5,2],["r",5,3],["b",5,4]],"start":[4,4],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[],"pops":3,"pushes":3},{"name":"random-46","input":{"n":13,"board":[["r",0,0],["r",0,1],["b",0,3],["b",0,4],["b",0,5],["b",0,6],["r",0,7],["r",0,8],["r",0,9],["b",0,10],["r",0,11],["r",1,1],["r",1,2],["b",1,4],["r",1,5],["b",1,6],["b",1,7],["b",1,9],["r",1,10],["r",1,11],["b",1,12],["r",2,2],["b",2,5],["r",2,9],["r",2,10],["b",2,12],["r",3,0],["r",3,3],["b",3,4],["b",3,6],["b",3,7],["b",3,9],["b",3,10],["b",3,11],["r",3,12],["b",4,0],["b",4,2],["b",4,3],["b",4,4],["r",4,10],["b",4,11],["r",5,3],["r",5,4],["b",5,6],["r",5,7],["r",5,8],["r",5,9],["r",5,11],["b",6,0],["b",6,1],["r",6,4],["b",6,7],["r",6,8],["r",6,9],["b",7,0],["b",7,2],["b",7,4],["b",7,5],["b",7,6],["b",7,7],["b",7,8],["r",7,12],["b",8,4],["r",8,8],["r",8,9],["r",9,0],["b",9,5],["b",9,7],["r",9,10],["r",10,0],["b",10,1],["r",10,4],["r",10,5],["r",10,6],["r",10,8],["b",10,10],["b",10,11],["r",10,12],["b",11,0],["r",11,3],["r",11,4],["r",11,5],["b",11,6],["b",11,8],["b",11,9],["b",11,10],["r",12,0],["r",12,2],["r",12,4],["b",12,5],["b",12,6],["r",12,10]],"start":[4,8],"goal":[6,6]},"heuristic":"manhattan","block":"Red","path":[[4,8],[4,7],[5,6],[6,6]],"pops":4,"pushes":11},{"name":"random-46","input":{"n":13,"board":[["r",0,0],["r",0,1],["b",0,3],["b",0,4],["b",0,5],["b",0,6],["r",0,7],["r",0,8],["r",0,9],["b",0,10],["r",0,11],["r",1,1],["r",1,2],["b",1,4],["r",1,5],["b",1,6],["b",1,7],["b",1,9],["r",1,10],["r",1,11],["b",1,12],["r",2,2],["b",2,5],["r",2,9],["r",2,10],["b",2,12],["r",3,0],["r",3,3],["b",3,4],["b",3,6],["b",3,7],["b",3,9],["b",3,10],["b",3,11],["r",3,12],["b",4,0],["b",4,2],["b",4,3],["b",4,4],["r",4,10],["b",4,11],["r",5,3],["r",5,4],["b",5,6],["r",5,7],["r",5,8],["r",5,9],["r",5,11],["b",6,0],["b",6,1],["r",6,4],["b",6,7],["r",6,8],["r",6,9],["b",7,0],["b",7,2],["b",7,4],["b",7,5],["b",7,6],["b",7,7],["b",7,8],["r",7,12],["b",8,4],["r",8,8],["r",8,9],["r",9,0],["b",9,5],["b",9,7],["r",9,10],["r",10,0],["b",10,1],["r",10,4],["r",10,5],["r",10,6],["r",10,8],["b",10,10],["b",10,11],["r",10,12],["b",11,0],["r",11,3],["r",11,4],["r",11,5],["b",11,6],["b",11,8],["b",11,9],["b",11,10],["r",12,0],["r",12,2],["r",12,4],["b",12,5],["b",12,6],["r",12,10]],"start":[4,8],"goal":[6,6]},"heuristic":"euclidean","block":"Red","path":[[4,8],[4,7],[5,6],[6,6]],"pops":4,"pushes":11},{"name":"random-47","input":{"n":14,"board":[["r",0,4],["b",0,12],["b",1,10],["b",2,1],["b",2,2],["r",2,7],["r",3,0],["b",3,4],["r",4,6],["b",4,8],["r",5,4],["b",5,7],["r",5,8],["r",5,10],["r",6,9],["r",6,12],["b",7,5],["b",8,2],["b",8,3],["r",8,6],["r",8,10],["b",9,1],["b",9,7],["b",9,13],["r",11,2],["r",11,8],["r",12,7],["r",12,13]],"start":[0,8],"goal":[5,5]},"heuristic":"manhattan","block":"Red","path":[[0,8],[1,7],[2,6],[3,5],[4,5],[5,5]],"pops":6,"pushes":14},{"name":"random-47","input":{"n":14,"board":[["r",0,4],["b",0,12],["b",1,10],["b",2,1],["b",2,2],["r",2,7],["r",3,0],["b",3,4],["r",4,6],["b",4,8],["r",5,4],["b",5,7],["r",5,8],["r",5,10],["r",6,9],["r",6,12],["b",7,5],["b",8,2],["b",8,3],["r",8,6],["r",8,10],["b",9,1],["b",9,7],["b",9,13],["r",11,2],["r",11,8],["r",12,7],["r",12,13]],"start":[0,8],"goal":[5,5]},"heuristic":"euclidean","block":"Red","path":[[0,8],[1,7],[2,6],[3,5],[4,5],[5,5]],"pops":6,"pushes":14},{"name":"random-48","input":{"n":13,"board":[["r",0,0],["b",0,6],["r",0,9],["b",0,10],["r",1,1],["b",1,2],["b",1,3],["b",1,12],["b",2,4],["b",2,8],["b",3,7],["b",3,9],["b",4,0],["r",4,2],["b",4,3],["b",4,8],["b",5,9],["b",5,11],["r",6,8],["r",7,1],["b",7,2],["r",7,3],["r",7,8],["b",7,12],["b",8,2],["b",8,3],["r",9,4],["r",9,5],["r",9,6],["r",9,7],["b",9,10],["r",10,3],["r",10,12],["r",11,2],["b",11,6],["b",11,8],["b",12,7],["b",12,8]],"start":[1,9],"goal":[4,9]},"heuristic":"manhattan","block":null,"path":[[1,9],[2,9],[2,10],[3,10],[4,9]],"pops":9,"pushes":20},{"name":"random-48","input":{"n":13,"board":[["r",0,0],["b",0,6],["r",0,9],["b",0,10],["r",1,1],["b",1,2],["b",1,3],["b",1,12],["b",2,4],["b",2,8],["b",3,7],["b",3,9],["b",4,0],["r",4,2],["b",4,3],["b",4,8],["b",5,9],["b",5,11],["r",6,8],["r",7,1],["b",7,2],["r",7,3],["r",7,8],["b",7,12],["b",8,2],["b",8,3],["r",9,4],["r",9,5],["r",9,6],["r",9,7],["b",9,10],["r",10,3],["r",10,12],["r",11,2],["b",11,6],["b",11,8],["b",12,7],["b",12,8]],"start":[1,9],"goal":[4,9]},"heuristic":"euclidean","block":null,"path":[[1,9],[2,9],[2,10],[3,10],[4,9]],"pops":8,"pushes":17},{"name":"random-49","input":{"n":4,"board":[["r",0,0],["b",0,1],["b",0,3],["r",3,0]],"start":[3,3],"goal":[0,2]},"heuristic":"manhattan","block":"Blue","path":[[3,3],[2,3],[2,2],[1,2],[0,2]],"pops":7,"pushes":10},{"name":"random-49","input":{"n":4,"board":[["r",0,0],["b",0,1],["b",0,3],["r",3,0]],"start":[3,3],"goal":[0,2]},"heuristic":"euclidean","block":"Blue","path":[[3,3],[2,3],[1,3],[1,2],[0,2]],"pops":7,"pushes":10},{"name":"random-50","input":{"n":3,"board":[["b",1,2],["b",2,1],["b",2,2]],"start":[1,0],"goal":[0,0]},"heuristic":"manhattan","block":null,"path":[[1,0],[0,0]],"pops":2,"pushes":5},{"name":"random-50","input":{"n":3,"board":[["b",1,2],["b",2,1],["b",2,2]],"start":[1,0],"goal":[0,0]},"heuristic":"euclidean","block":null,"path":[[1,0],[0,0]],"pops":2,"pushes":5},{"name":"random-51","input":{"n":3,"board":[],"start":[0,1],"goal":[1,1]},"heuristic":"manhattan","block":null,"path":[[0,1],[1,1]],"pops":2,"pushes":5},{"name":"random-51","input":{"n":3,"board":[],"start":[0,1],"goal":[1,1]},"heuristic":"euclidean","block":null,"path":[[0,1],[1,1]],"pops":2,"pushes":5},{"name":"random-52","input":{"n":13,"board":[["b",0,3],["r",0,12],["r",1,1],["r",2,0],["r",4,1],["r",4,7],["b",4,8],["r",4,10],["r",6,5],["b",7,2],["b",9,0],["b",9,6],["r",9,9],["b",9,11],["b",10,11],["b",11,4]],"start":[0,8],"goal":[8,10]},"heuristic":"manhattan","block":"Red","path":[[0,8],[1,8],[1,9],[2,9],[3,9],[4,9],[5,9],[5,10],[6,10],[7,10],[8,10]],"pops":26,"pushes":44},{"name":"random-52","input":{"n":13,"board":[["b",0,3],["r",0,12],["r",1,1],["r",2,0],["r",4,1],["r",4,7],["b",4,8],["r",4,10],["r",6,5],["b",7,2],["b",9,0],["b",9,6],["r",9,9],["b",9,11],["b",10,11],["b",11,4]],"start":[0,8],"goal":[8,10]},"heuristic":"euclidean","block":"Red","path":[[0,8],[1,8],[2,8],[3,8],[4,8],[5,8],[6,8],[6,9],[7,9],[7,10],[8,10]],"pops":35,"pushes":56},{"name":"random-53","input":{"n":4,"board":[],"start":[2,0],"goal":[3,2]},"heuristic":"manhattan","block":null,"path":[[2,0],[2,1],[3,1],[3,2]],"pops":6,"pushes":11},{"name":"random-53","input":{"n":4,"board":[],"start":[2,0],"goal":[3,2]},"heuristic":"euclidean","block":null,"path":[[2,0],[2,1],[3,1],[3,2]],"pops":6,"pushes":11},{"name":"random-54","input":{"n":6,"board":[["b",0,2],["b",0,4],["b",0,5],["r",1,1],["r",1,2],["b",2,0],["r",2,3],["r",2,4],["b",2,5],["b",3,2],["b",3,3],["r",3,4],["r",3,5],["r",4,0],["r",4,2],["r",4,3],["r",5,2],["b",5,3]],"start":[4,4],"goal":[3,1]},"heuristic":"manhattan","block":"Blue","path":[[4,4],[4,3],[4,2],[4,1],[3,1]],"pops":6,"pushes":14},{"name":"random-54","input":{"n":6,"board":[["b",0,2],["b",0,4],["b",0,5],["r",1,1],["r",1,2],["b",2,0],["r",2,3],["r",2,4],["b",2,5],["b",3,2],["b",3,3],["r",3,4],["r",3,5],["r",4,0],["r",4,2],["r",4,3],["r",5,2],["b",5,3]],"start":[4,4],"goal":[3,1]},"heuristic":"euclidean","block":"Blue","path":[[4,4],[4,3],[4,2],[4,1],[3,1]],"pops":6,"pushes":14},{"name":"random-55","input":{"n":13,"board":[["r",0,0],["r",0,2],["b",0,4],["b",0,5],["b",0,7],["r",0,11],["b",1,0],["r",1,1],["r",1,2],["b",1,4],["r",1,5],["r",1,7],["b",1,9],["r",1,10],["b",1,11],["b",2,2],["r",2,3],["b",2,4],["b",2,7],["b",2,8],["b",2,9],["r",2,10],["r",3,0],["r",3,1],["b",3,3],["b",3,4],["r",3,11],["b",4,0],["r",4,2],["r",4,4],["b",4,5],["b",4,6],["b",4,9],["r",4,10],["b",4,11],["b",5,1],["b",5,2],["b",5,3],["b",5,4],["r",5,6],["b",5,7],["b",5,8],["r",5,11],["b",6,0],["r",6,3],["r",6,4],["r",6,5],["r",6,6],["b",6,7],["r",6,8],["r",6,10],["b",6,12],["b",7,0],["b",7,1],["r",7,2],["r",7,3],["r",7,4],["r",7,5],["r",7,6],["r",7,10],["r",7,11],["r",7,12],["b",8,1],["r",8,2],["b",8,5],["r",8,6],["b",8,8],["r",8,9],["r",8,12],["r",9,0],["r",9,5],["r",9,7],["b",9,10],["b",9,11],["b",10,1],["r",10,2],["r",10,5],["b",10,8],["b",10,10],["b",10,12],["r",11,2],["b",11,5],["b",11,6],["b",11,8],["r",11,9],["r",12,1],["b",12,3],["r",12,4],["r",12,6],["r",12,7],["r",12,11]],"start":[5,10],"goal":[6,2]},"heuristic":"manhattan","block":"Red","path":[[5,10],[5,9],[5,8],[5,7],[4,7],[4,6],[5,5],[5,4],[5,3],[6,2]],"pops":20,"pushes":31},{"name":"random-55","input":{"n":13,"board":[["r",0,0],["r",0,2],["b",0,4],["b",0,5],["b",0,7],["r",0,11],["b",1,0],["r",1,1],["r",1,2],["b",1,4],["r",1,5],["r",1,7],["b",1,9],["r",1,10],["b",1,11],["b",2,2],["r",2,3],["b",2,4],["b",2,7],["b",2,8],["b",2,9],["r",2,10],["r",3,0],["r",3,1],["b",3,3],["b",3,4],["r",3,11],["b",4,0],["r",4,2],["r",4,4],["b",4,5],["b",4,6],["b",4,9],["r",4,10],["b",4,11],["b",5,1],["b",5,2],["b",5,3],["b",5,4],["r",5,6],["b",5,7],["b",5,8],["r",5,11],["b",6,0],["r",6,3],["r",6,4],["r",6,5],["r",6,6],["b",6,7],["r",6,8],["r",6,10],["b",6,12],["b",7,0],["b",7,1],["r",7,2],["r",7,3],["r",7,4],["r",7,5],["r",7,6],["r",7,10],["r",7,11],["r",7,12],["b",8,1],["r",8,2],["b",8,5],["r",8,6],["b",8,8],["r",8,9],["r",8,12],["r",9,0],["r",9,5],["r",9,7],["b",9,10],["b",9,11],["b",10,1],["r",10,2],["r",10,5],["b",10,8],["b",10,10],["b",10,12],["r",11,2],["b",11,5],["b",11,6],["b",11,8],["r",11,9],["r",12,1],["b",12,3],["r",12,4],["r",12,6],["r",12,7],["r",12,11]],"start":[5,10],"goal":[6,2]},"heuristic":"euclidean","block":"Red","path":[[5,10],[5,9],[5,8],[5,7],[4,7],[4,6],[5,5],[5,4],[5,3],[6,2]],"pops":20,"pushes":31},{"name":"random-56","input":{"n":6,"board":[["r",0,3],["b",1,0],["b",1,1],["b",1,4],["b",2,4],["b",3,1],["r",3,2],["b",4,5]],"start":[1,5],"goal":[3,3]},"heuristic":"manhattan","block":"Red","path":[[1,5],[2,4],[3,3]],"pops":3,"pushes":8},{"name":"random-56","input":{"n":6,"board":[["r",0,3],["b",1,0],["b",1,1],["b",1,4],["b",2,4],["b",3,1],["r",3,2],["b",4,5]],"start":[1,5],"goal":[3,3]},"heuristic":"euclidean","block":"Red","path":[[1,5],[2,4],[3,3]],"pops":3,"pushes":8},{"name":"random-57","input":{"n":4,"board":[["b",0,0],["r",0,1],["b",0,3],["r",1,1],["b",2,0],["r",2,2],["r",3,0],["r",3,3]],"start":[1,2],"goal":[0,2]},"heuristic":"manhattan","block":"Blue","path":[[1,2],[0,2]],"pops":2,"pushes":6},{"name":"random-57","input":{"n":4,"board":[["b",0,0],["r",0,1],["b",0,3],["r",1,1],["b",2,0],["r",2,2],["r",3,0],["r",3,3]],"start":[1,2],"goal":[0,2]},"heuristic":"euclidean","block":"Blue","path":[[1,2],[0,2]],"pops":2,"pushes":6},{"name":"random-58","input":{"n":6,"board":[["b",1,2],["b",1,3],["b",2,5],["r",4,2]],"start":[4,3],"goal":[0,5]},"heuristic":"manhattan","block":"Red","path":[[4,3],[3,4],[2,5],[1,5],[0,5]],"pops":5,"pushes":12},{"name":"random-58","input":{"n":6,"board":[["b",1,2],["b",1,3],["b",2,5],["r",4,2]],"start":[4,3],"goal":[0,5]},"heuristic":"euclidean","block":"Red","path":[[4,3],[3,4],[2,5],[1,5],[0,5]],"pops":5,"pushes":12},{"name":"random-59","input":{"n":14,"board":[["b",0,1],["r",0,2],["b",1,0],["b",2,1],["r",3,7],["b",5,3],["b",5,12],["b",6,9],["r",7,9],["b",7,12],["b",8,7],["b",9,10],["r",9,11],["r",10,11],["b",11,7],["b",13,5]],"start":[1,8],"goal":[7,5]},"heuristic":"manhattan","block":"Blue","path":[[1,8],[2,7],[3,6],[4,5],[5,5],[6,5],[7,5]],"pops":7,"pushes":22},{"name":"random-59","input":{"n":14,"board":[["b",0,1],["r",0,2],["b",1,0],["b",2,1],["r",3,7],["b",5,3],["b",5,12],["b",6,9],["r",7,9],["b",7,12],["b",8,7],["b",9,10],["r",9,11],["r",10,11],["b",11,7],["b",13,5]],"start":[1,8],"goal":[7,5]},"heuristic":"euclidean","block":"Blue","path":[[1,8],[2,7],[3,6],[4,5],[5,5],[6,5],[7,5]],"pops":7,"pushes":22},{"name":"random-60","input":{"n":9,"board":[["b",0,1],["b",0,4],["r",0,5],["r",0,6],["b",0,8],["r",1,0],["r",1,1],["b",1,2],["b",1,5],["r",1,6],["r",1,7],["r",1,8],["b",2,1],["r",2,8],["b",3,0],["r",3,1],["b",3,2],["b",3,4],["r",3,6],["r",3,7],["b",3,8],["b",4,1],["r",4,2],["b",4,3],["r",4,4],["b",4,5],["r",4,6],["b",4,7],["b",5,0],["b",5,2],["b",5,5],["b",5,7],["r",6,2],["b",6,5],["b",6,6],["b",6,8],["b",7,1],["r",7,2],["r",7,3],["b",7,5],["r",7,6],["b",8,0],["b",8,4],["b",8,8]],"start":[8,1],"goal":[8,7]},"heuristic":"manhattan","block":null,"path":[],"pops":8,"pushes":8},{"name":"random-60","input":{"n":9,"board":[["b",0,1],["b",0,4],["r",0,5],["r",0,6],["b",0,8],["r",1,0],["r",1,1],["b",1,2],["b",1,5],["r",1,6],["r",1,7],["r",1,8],["b",2,1],["r",2,8],["b",3,0],["r",3,1],["b",3,2],["b",3,4],["r",3,6],["r",3,7],["b",3,8],["b",4,1],["r",4,2],["b",4,3],["r",4,4],["b",4,5],["r",4,6],["b",4,7],["b",5,0],["b",5,2],["b",5,5],["b",5,7],["r",6,2],["b",6,5],["b",6,6],["b",6,8],["b",7,1],["r",7,2],["r",7,3],["b",7,5],["r",7,6],["b",8,0],["b",8,4],["b",8,8]],"start":[8,1],"goal":[8,7]},"heuristic":"euclidean","block":null,"path":[],"pops":8,"pushes":8},{"name":"random-61","input":{"n":2,"board":[["b",1,0]],"start":[0,0],"goal":[0,1]},"heuristic":"manhattan","block":null,"path":[[0,0],[0,1]],"pops":2,"pushes":2},{"name":"random-61","input":{"n":2,"board":[["b",1,0]],"start":[0,0],"goal":[0,1]},"heuristic":"euclidean","block":null,"path":[[0,0],[0,1]],"pops":2,"pushes":2},{"name":"random-62","input":{"n":4,"board":[["b",1,3],["b",3,0],["b",3,2]],"start":[0,1],"goal":[3,1]},"heuristic":"manhattan","block":"Red","path":[[0,1],[1,1],[2,1],[3,1]],"pops":4,"pushes":11},{"name":"random-62","input":{"n":4,"board":[["b",1,3],["b",3,0],["b",3,2]],"start":[0,1],"goal":[3,1]},"heuristic":"euclidean","block":"Red","path":[[0,1],[1,1],[2,1],[3,1]],"pops":4,"pushes":11},{"name":"random-63","input":{"n":13,"board":[["r",0,1],["r",0,4],["r",0,5],["b",0,6],["r",1,0],["b",1,8],["b",1,9],["b",1,11],["r",2,2],["b",2,3],["r",2,5],["r",2,8],["b",2,11],["r",2,12],["b",3,0],["b",3,1],["r",3,2],["b",3,3],["r",3,6],["r",3,7],["r",3,11],["b",3,12],["r",4,2],["r",4,3],["r",4,4],["b",4,6],["b",4,7],["b",4,9],["b",4,11],["r",5,2],["b",5,3],["b",5,5],["r",5,10],["b",5,12],["b",6,3],["r",6,10],["b",6,12],["r",7,3],["r",7,5],["r",7,8],["b",7,10],["r",8,2],["b",8,5],["r",8,11],["r",9,0],["r",9,2],["r",9,9],["r",9,10],["r",9,12],["b",10,1],["b",10,2],["r",10,11],["b",11,0],["r",11,2],["b",11,7],["b",11,8],["r",11,10],["b",12,0],["r",12,1],["b",12,2],["b",12,4],["r",12,5],["r",12,6],["r",12,7],["b",12,8],["r",12,11],["b",12,12]],"start":[7,7],"goal":[10,10]},"heuristic":"manhattan","block":"Blue","path":[[7,7],[8,7],[8,8],[8,9],[9,9],[9,10],[10,10]],"pops":15,"pushes":28},{"name":"random-63","input":{"n":13,"board":[["r",0,1],["r",0,4],["r",0,5],["b",0,6],["r",1,0],["b",1,8],["b",1,9],["b",1,11],["r",2,2],["b",2,3],["r",2,5],["r",2,8],["b",2,11],["r",2,12],["b",3,0],["b",3,1],["r",3,2],["b",3,3],["r",3,6],["r",3,7],["r",3,11],["b",3,12],["r",4,2],["r",4,3],["r",4,4],["b",4,6],["b",4,7],["b",4,9],["b",4,11],["r",5,2],["b",5,3],["b",5,5],["r",5,10],["b",5,12],["b",6,3],["r",6,10],["b",6,12],["r",7,3],["r",7,5],["r",7,8],["b",7,10],["r",8,2],["b",8,5],["r",8,11],["r",9,0],["r",9,2],["r",9,9],["r",9,10],["r",9,12],["b",10,1],["b",10,2],["r",10,11],["b",11,0],["r",11,2],["b",11,7],["b",11,8],["r",11,10],["b",12,0],["r",12,1],["b",12,2],["b",12,4],["r",12,5],["r",12,6],["r",12,7],["b",12,8],["r",12,11],["b",12,12]],"start":[7,7],"goal":[10,10]},"heuristic":"euclidean","block":"Blue","path":[[7,7],[8,7],[8,8],[8,9],[9,9],[9,10],[10,10]],"pops":19,"pushes":34},{"name":"random-64","input":{"n":10,"board":[["r",0,1],["r",0,2],["r",1,7],["r",1,9],["r",3,2],["r",5,4],["r",5,7],["r",5,9],["b",6,0],["b",6,3],["r",7,0],["r",7,2],["b",7,5],["b",7,6],["b",7,8],["r",8,1],["r",9,3],["b",9,9]],"start":[7,1],"goal":[9,1]},"heuristic":"manhattan","block":"Blue","path":[[7,1],[8,1],[9,1]],"pops":3,"pushes":10},{"name":"random-64","input":{"n":10,"board":[["r",0,1],["r",0,2],["r",1,7],["r",1,9],["r",3,2],["r",5,4],["r",5,7],["r",5,9],["b",6,0],["b",6,3],["r",7,0],["r",7,2],["b",7,5],["b",7,6],["b",7,8],["r",8,1],["r",9,3],["b",9,9]],"start":[7,1],"goal":[9,1]},"heuristic":"euclidean","block":"Blue","path":[[7,1],[8,1],[9,1]],"pops":3,"pushes":10},{"name":"random-65","input":{"n":9,"board":[["r",0,2],["r",0,3],["b",0,6],["b",0,8],["r",1,6],["r",2,1],["b",2,2],["b",2,3],["r",2,4],["r",2,5],["r",2,6],["b",2,7],["b",2,8],["r",3,0],["b",3,2],["r",3,3],["r",3,5],["b",3,8],["b",4,0],["b",4,2],["r",4,3],["b",4,4],["b",4,6],["b",4,8],["b",5,0],["r",5,1],["r",5,5],["b",5,8],["r",6,1],["b",6,3],["b",6,4],["r",6,5],["b",6,6],["r",6,7],["r",6,8],["r",7,0],["b",7,1],["b",7,2],["b",7,3],["b",7,7],["r",7,8],["b",8,1],["r",8,6],["r",8,7],["r",8,8]],"start":[1,8],"goal":[0,1]},"heuristic":"manhattan","block":null,"path":[],"pops":3,"pushes":3},{"name":"random-65","input":{"n":9,"board":[["r",0,2],["r",0,3],["b",0,6],["b",0,8],["r",1,6],["r",2,1],["b",2,2],["b",2,3],["r",2,4],["r",2,5],["r",2,6],["b",2,7],["b",2,8],["r",3,0],["b",3,2],["r",3,3],["r",3,5],["b",3,8],["b",4,0],["b",4,2],["r",4,3],["b",4,4],["b",4,6],["b",4,8],["b",5,0],["r",5,1],["r",5,5],["b",5,8],["r",6,1],["b",6,3],["b",6,4],["r",6,5],["b",6,6],["r",6,7],["r",6,8],["r",7,0],["b",7,1],["b",7,2],["b",7,3],["b",7,7],["r",7,8],["b",8,1],["r",8,6],["r",8,7],["r",8,8]],"start":[1,8],"goal":[0,1]},"heuristic":"euclidean","block":null,"path":[],"pops":3,"pushes":3},{"name":"random-66","input":{"n":4,"board":[["b",1,3],["b",2,3]],"start":[3,2],"goal":[0,2]},"heuristic":"manhattan","block":null,"path":[[3,2],[2,2],[1,2],[0,2]],"pops":4,"pushes":9},{"name":"random-66","input":{"n":4,"board":[["b",1,3],["b",2,3]],"start":[3,2],"goal":[0,2]},"heuristic":"euclidean","block":null,"path":[[3,2],[2,2],[1,2],[0,2]],"pops":4,"pushes":9},{"name":"random-67","input":{"n":14,"board":[["b",0,0],["b",0,6],["r",0,8],["r",0,12],["b",0,13],["b",1,0],["r",1,3],["b",1,5],["b",1,6],["r",1,7],["b",1,9],["r",2,0],["b",2,1],["b",2,7],["b",2,11],["b",2,12],["b",3,6],["b",3,9],["r",3,13],["r",4,5],["r",4,12],["r",4,13],["r",5,2],["r",5,7],["r",5,8],["b",5,11],["b",5,13],["r",6,7],["r",7,2],["b",7,5],["b",7,6],["b",7,12],["r",7,13],["r",8,2],["b",8,5],["r",8,7],["b",8,10],["r",9,9],["b",9,11],["r",10,0],["r",10,1],["b",10,2],["r",10,7],["r",10,8],["r",10,9],["b",10,11],["b",10,12],["b",11,1],["b",11,3],["b",11,5],["b",11,6],["r",11,7],["b",11,10],["r",11,11],["b",12,1],["b",12,4],["b",12,6],["r",12,9],["r",12,11],["r",13,1],["b",13,7],["r",13,10],["b",13,11],["b",13,13]],"start":[9,7],"goal":[6,3]},"heuristic":"manhattan","block":"Red","path":[[9,7],[9,6],[9,5],[8,5],[8,4],[7,4],[6,4],[6,3]],"pops":17,"pushes":29},{"name":"random-67","input":{"n":14,"board":[["b",0,0],["b",0,6],["r",0,8],["r",0,12],["b",0,13],["b",1,0],["r",1,3],["b",1,5],["b",1,6],["r",1,7],["b",1,9],["r",2,0],["b",2,1],["b",2,7],["b",2,11],["b",2,12],["b",3,6],["b",3,9],["r",3,13],["r",4,5],["r",4,12],["r",4,13],["r",5,2],["r",5,7],["r",5,8],["b",5,11],["b",5,13],["r",6,7],["r",7,2],["b",7,5],["b",7,6],["b",7,12],["r",7,13],["r",8,2],["b",8,5],["r",8,7],["b",8,10],["r",9,9],["b",9,11],["r",10,0],["r",10,1],["b",10,2],["r",10,7],["r",10,8],["r",10,9],["b",10,11],["b",10,12],["b",11,1],["b",11,3],["b",11,5],["b",11,6],["r",11,7],["b",11,10],["r",11,11],["b",12,1],["b",12,4],["b",12,6],["r",12,9],["r",12,11],["r",13,1],["b",13,7],["r",13,10],["b",13,11],["b",13,13]],"start":[9,7],"goal":[6,3]},"heuristic":"euclidean","block":"Red","path":[[9,7],[9,6],[9,5],[8,5],[8,4],[7,4],[6,4],[6,3]],"pops":21,"pushes":35},{"name":"random-68","input":{"n":7,"board":[["b",0,4],["b",0,6],["r",1,1],["b",1,3],["b",1,4],["r",2,0],["b",2,2],["b",2,3],["r",2,4],["r",2,5],["b",2,6],["b",3,2],["r",3,3],["b",3,4],["r",4,0],["r",4,4],["r",4,5],["b",5,0],["r",5,1],["r",5,2],["r",5,4],["r",5,5],["b",6,0],["b",6,1],["b",6,2]],"start":[0,0],"goal":[3,1]},"heuristic":"manhattan","block":null,"path":[[0,0],[0,1],[0,2],[1,2],[2,1],[3,1]],"pops":7,"pushes":9},{"name":"random-68","input":{"n":7,"board":[["b",0,4],["b",0,6],["r",1,1],["b",1,3],["b",1,4],["r",2,0],["b",2,2],["b",2,3],["r",2,4],["r",2,5],["b",2,6],["b",3,2],["r",3,3],["b",3,4],["r",4,0],["r",4,4],["r",4,5],["b",5,0],["r",5,1],["r",5,2],["r",5,4],["r",5,5],["b",6,0],["b",6,1],["b",6,2]],"start":[0,0],"goal":[3,1]},"heuristic":"euclidean","block":null,"path":[[0,0],[0,1],[0,2],[1,2],[2,1],[3,1]],"pops":7,"pushes":9},{"name":"random-69","input":{"n":12,"board":[["r",3,3],["r",3,5],["b",4,3],["r",5,0],["b",5,7],["r",6,9],["b",9,1],["b",9,4],["r",11,1],["r",11,5]],"start":[4,6],"goal":[2,9]},"heuristic":"manhattan","block":null,"path":[[4,6],[3,7],[2,8],[2,9]],"pops":4,"pushes":13},{"name":"random-69","input":{"n":12,"board":[["r",3,3],["r",3,5],["b",4,3],["r",5,0],["b",5,7],["r",6,9],["b",9,1],["b",9,4],["r",11,1],["r",11,5]],"start":[4,6],"goal":[2,9]},"heuristic":"euclidean","block":null,"path":[[4,6],[3,7],[2,8],[2,9]],"pops":4,"pushes":13},{"name":"random-70","input":{"n":2,"board":[["b",0,1]],"start":[1,0],"goal":[1,1]},"heuristic":"manhattan","block":"Blue","path":[[1,0],[1,1]],"pops":2,"pushes":3},{"name":"random-70","input":{"n":2,"board":[["b",0,1]],"start":[1,0],"goal":[1,1]},"heuristic":"euclidean","block":"Blue","path":[[1,0],[1,1]],"pops":2,"pushes":3},{"name":"random-71","input":{"n":12,"board":[["b",0,4],["b",1,6],["b",1,7],["r",1,10],["r",1,11],["b",2,1],["r",2,4],["b",3,2],["r",3,6],["r",3,10],["b",4,2],["b",4,6],["b",4,7],["r",4,11],["r",5,0],["r",5,1],["r",5,5],["r",5,7],["r",6,0],["r",6,2],["r",6,3],["r",6,6],["r",6,11],["r",7,4],["b",7,11],["r",8,4],["r",8,5],["b",8,10],["b",9,4],["r",9,9],["b",10,0],["b",11,4],["r",11,6],["r",11,7],["b",11,8],["b",11,11]],"start":[7,2],"goal":[5,8]},"heuristic":"manhattan","block":"Blue","path":[[7,2],[6,3],[5,4],[5,5],[5,6],[5,7],[5,8]],"pops":7,"pushes":20},{"name":"random-71","input":{"n":12,"board":[["b",0,4],["b",1,6],["b",1,7],["r",1,10],["r",1,11],["b",2,1],["r",2,4],["b",3,2],["r",3,6],["r",3,10],["b",4,2],["b",4,6],["b",4,7],["r",4,11],["r",5,0],["r",5,1],["r",5,5],["r",5,7],["r",6,0],["r",6,2],["r",6,3],["r",6,6],["r",6,11],["r",7,4],["b",7,11],["r",8,4],["r",8,5],["b",8,10],["b",9,4],["r",9,9],["b",10,0],["b",11,4],["r",11,6],["r",11,7],["b",11,8],["b",11,11]],"start":[7,2],"goal":[5,8]},"heuristic":"euclidean","block":"Blue","path":[[7,2],[6,3],[5,4],[5,5],[5,6],[5,7],[5,8]],"pops":7,"pushes":20},{"name":"random-72","input":{"n":10,"board":[["r",0,0],["b",0,1],["r",0,2],["b",0,5],["r",0,7],["b",0,9],["r",1,4],["b",1,5],["r",1,8],["r",1,9],["b",2,3],["b",2,4],["r",2,5],["b",2,9],["b",3,0],["r",3,1],["b",3,2],["b",3,5],["r",3,7],["r",3,8],["r",3,9],["b",4,6],["r",4,7],["b",5,2],["r",5,9],["b",6,1],["b",6,2],["b",6,3],["r",6,4],["r",6,5],["r",6,6],["b",7,1],["b",7,7],["b",8,0],["r",8,1],["b",8,4],["r",8,7],["b",8,8],["b",9,0],["r",9,4],["r",9,5],["r",9,6],["r",9,7],["r",9,8]],"start":[1,7],"goal":[1,3]},"heuristic":"manhattan","block":null,"path":[],"pops":47,"pushes":47},{"name":"random-72","input":{"n":10,"board":[["r",0,0],["b",0,1],["r",0,2],["b",0,5],["r",0,7],["b",0,9],["r",1,4],["b",1,5],["r",1,8],["r",1,9],["b",2,3],["b",2,4],["r",2,5],["b",2,9],["b",3,0],["r",3,1],["b",3,2],["b",3,5],["r",3,7],["r",3,8],["r",3,9],["b",4,6],["r",4,7],["b",5,2],["r",5,9],["b",6,1],["b",6,2],["b",6,3],["r",6,4],["r",6,5],["r",6,6],["b",7,1],["b",7,7],["b",8,0],["r",8,1],["b",8,4],["r",8,7],["b",8,8],["b",9,0],["r",9,4],["r",9,5],["r",9,6],["r",9,7],["r",9,8]],"start":[1,7],"goal":[1,3]},"heuristic":"euclidean","block":null,"path":[],"pops":47,"pushes":47},{"name":"random-73","input":{"n":14,"board":[["b",0,1],["b",0,10],["b",0,11],["b",1,0],["r",1,7],["r",1,10],["b",1,13],["r",2,2],["b",3,1],["r",3,7],["r",3,9],["r",3,13],["b",4,2],["r",4,6],["b",4,9],["b",5,1],["b",5,6],["r",5,11],["r",6,0],["r",6,2],["b",6,5],["b",6,8],["r",6,13],["r",7,4],["b",7,11],["r",8,1],["b",8,2],["b",9,7],["b",9,8],["r",10,5],["r",10,8],["r",11,0],["r",11,12],["b",12,4],["r",12,5],["r",12,8],["r",13,0],["r",13,1],["b",13,9]],"start":[1,6],"goal":[3,11]},"heuristic":"manhattan","block":"Red","path":[[1,6],[2,6],[2,7],[2,8],[2,9],[2,10],[3,10],[3,11]],"pops":11,"pushes":26},{"name":"random-73","input":{"n":14,"board":[["b",0,1],["b",0,10],["b",0,11],["b",1,0],["r",1,7],["r",1,10],["b",1,13],["r",2,2],["b",3,1],["r",3,7],["r",3,9],["r",3,13],["b",4,2],["r",4,6],["b",4,9],["b",5,1],["b",5,6],["r",5,11],["r",6,0],["r",6,2],["b",6,5],["b",6,8],["r",6,13],["r",7,4],["b",7,11],["r",8,1],["b",8,2],["b",9,7],["b",9,8],["r",10,5],["r",10,8],["r",11,0],["r",11,12],["b",12,4],["r",12,5],["r",12,8],["r",13,0],["r",13,1],["b",13,9]],"start":[1,6],"goal":[3,11]},"heuristic":"euclidean","block":"Red","path":[[1,6],[2,6],[2,7],[2,8],[2,9],[2,10],[3,10],[3,11]],"pops":17,"pushes":30},{"name":"random-74","input":{"n":5,"board":[["r",0,0],["b",0,1],["r",0,4],["r",1,2],["b",1,3],["b",1,4],["b",2,1],["b",2,3],["b",3,0],["r",3,2],["b",3,4],["b",4,0],["b",4,4]],"start":[1,0],"goal":[3,3]},"heuristic":"manhattan","block":"Blue","path":[[1,0],[1,1],[1,2],[2,2],[3,2],[3,3]],"pops":7,"pushes":13},{"name":"random-74","input":{"n":5,"board":[["r",0,0],["b",0,1],["r",0,4],["r",1,2],["b",1,3],["b",1,4],["b",2,1],["b",2,3],["b",3,0],["r",3,2],["b",3,4],["b",4,0],["b",4,4]],"start":[1,0],"goal":[3,3]},"heuristic":"euclidean","block":"Blue","path":[[1,0],[1,1],[1,2],[2,2],[3,2],[3,3]],"pops":7,"pushes":13},{"name":"random-75","input":{"n":2,"board":[["b",1,1]],"start":[1,0],"goal":[0,1]},"heuristic":"manhattan","block":"Blue","path":[[1,0],[0,1]],"pops":2,"pushes":3},{"name":"random-75","input":{"n":2,"board":[["b",1,1]],"start":[1,0],"goal":[0,1]},"heuristic":"euclidean","block":"Blue","path":[[1,0],[0,1]],"pops":2,"pushes":3},{"name":"random-76","input":{"n":6,"board":[["r",1,1],["b",1,4],["b",2,1],["r",2,3],["r",2,5],["r",3,3],["b",3,4],["r",3,5],["b",4,1],["r",5,0],["r",5,3],["r",5,4]],"start":[0,2],"goal":[4,3]},"heuristic":"manhattan","block":"Blue","path":[[0,2],[1,2],[2,2],[2,3],[3,3],[4,3]],"pops":10,"pushes":17},{"name":"random-76","input":{"n":6,"board":[["r",1,1],["b",1,4],["b",2,1],["r",2,3],["r",2,5],["r",3,3],["b",3,4],["r",3,5],["b",4,1],["r",5,0],["r",5,3],["r",5,4]],"start":[0,2],"goal":[4,3]},"heuristic":"euclidean","block":"Blue","path":[[0,2],[1,2],[2,2],[3,2],[4,2],[4,3]],"pops":11,"pushes":19},{"name":"random-77","input":{"n":8,"board":[["b",0,0],["b",0,1],["b",0,3],["r",0,4],["r",0,6],["r",1,0],["r",1,3],["r",1,7],["r",2,1],["r",2,3],["r",2,5],["b",2,6],["b",2,7],["r",3,2],["r",4,1],["r",4,2],["r",4,4],["b",4,6],["r",4,7],["b",5,0],["r",5,2],["b",6,2],["b",6,5],["b",6,7],["r",7,1],["b",7,3],["r",7,4],["b",7,6],["b",7,7]],"start":[5,1],"goal":[5,5]},"heuristic":"manhattan","block":null,"path":[],"pops":4,"pushes":4},{"name":"random-77","input":{"n":8,"board":[["b",0,0],["b",0,1],["b",0,3],["r",0,4],["r",0,6],["r",1,0],["r",1,3],["r",1,7],["r",2,1],["r",2,3],["r",2,5],["b",2,6],["b",2,7],["r",3,2],["r",4,1],["r",4,2],["r",4,4],["b",4,6],["r",4,7],["b",5,0],["r",5,2],["b",6,2],["b",6,5],["b",6,7],["r",7,1],["b",7,3],["r",7,4],["b",7,6],["b",7,7]],"start":[5,1],"goal":[5,5]},"heuristic":"euclidean","block":null,"path":[],"pops":4,"pushes":4},{"name":"random-78","input":{"n":8,"board":[["b",0,3],["b",0,4],["b",0,5],["b",0,7],["r",1,3],["b",1,4],["b",2,2],["r",2,5],["b",3,0],["r",3,3],["b",3,4],["r",3,7],["r",4,0],["r",4,1],["b",4,2],["r",4,4],["b",4,6],["b",5,3],["r",5,4],["b",5,6],["b",6,3],["r",6,5],["b",6,7],["b",7,0],["b",7,3]],"start":[0,6],"goal":[6,0]},"heuristic":"manhattan","block":"Red","path":[[0,6],[1,5],[2,4],[3,4],[4,3],[5,2],[6,1],[6,0]],"pops":8,"pushes":20},{"name":"random-78","input":{"n":8,"board":[["b",0,3],["b",0,4],["b",0,5],["b",0,7],["r",1,3],["b",1,4],["b",2,2],["r",2,5],["b",3,0],["r",3,3],["b",3,4],["r",3,7],["r",4,0],["r",4,1],["b",4,2],["r",4,4],["b",4,6],["b",5,3],["r",5,4],["b",5,6],["b",6,3],["r",6,5],["b",6,7],["b",7,0],["b",7,3]],"start":[0,6],"goal":[6,0]},"heuristic":"euclidean","block":"Red","path":[[0,6],[1,5],[2,4],[3,4],[4,3],[5,2],[6,1],[6,0]],"pops":8,"pushes":20},{"name":"random-79","input":{"n":11,"board":[["b",0,0],["b",0,1],["b",0,2],["r",0,3],["r",0,4],["r",0,5],["b",0,6],["b",0,7],["b",0,8],["b",0,9],["r",0,10],["b",1,2],["b",1,4],["r",1,6],["r",1,7],["b",1,8],["b",2,1],["r",2,2],["b",2,3],["r",2,5],["b",2,6],["r",2,7],["b",2,8],["b",2,10],["b",3,0],["b",3,2],["r",3,3],["r",3,4],["r",3,5],["r",3,6],["b",3,7],["r",3,8],["r",3,10],["b",4,0],["r",4,2],["b",4,3],["b",4,5],["b",4,7],["r",5,1],["b",5,2],["r",5,7],["b",5,8],["b",5,9],["b",5,10],["r",6,0],["b",6,1],["b",6,2],["b",6,3],["r",6,4],["r",6,7],["b",7,1],["r",7,4],["b",7,6],["b",7,8],["b",7,9],["r",8,0],["b",8,2],["b",8,4],["b",8,5],["r",8,7],["b",8,8],["b",9,0],["r",9,2],["b",9,3],["r",9,4],["r",9,7],["b",9,9],["b",9,10],["r",10,2],["r",10,5],["r",10,6],["b",10,8],["b",10,10]],"start":[4,6],"goal":[8,10]},"heuristic":"manhattan","block":null,"path":[],"pops":9,"pushes":9},{"name":"random-79","input":{"n":11,"board":[["b",0,0],["b",0,1],["b",0,2],["r",0,3],["r",0,4],["r",0,5],["b",0,6],["b",0,7],["b",0,8],["b",0,9],["r",0,10],["b",1,2],["b",1,4],["r",1,6],["r",1,7],["b",1,8],["b",2,1],["r",2,2],["b",2,3],["r",2,5],["b",2,6],["r",2,7],["b",2,8],["b",2,10],["b",3,0],["b",3,2],["r",3,3],["r",3,4],["r",3,5],["r",3,6],["b",3,7],["r",3,8],["r",3,10],["b",4,0],["r",4,2],["b",4,3],["b",4,5],["b",4,7],["r",5,1],["b",5,2],["r",5,7],["b",5,8],["b",5,9],["b",5,10],["r",6,0],["b",6,1],["b",6,2],["b",6,3],["r",6,4],["r",6,7],["b",7,1],["r",7,4],["b",7,6],["b",7,8],["b",7,9],["r",8,0],["b",8,2],["b",8,4],["b",8,5],["r",8,7],["b",8,8],["b",9,0],["r",9,2],["b",9,3],["r",9,4],["r",9,7],["b",9,9],["b",9,10],["r",10,2],["r",10,5],["r",10,6],["b",10,8],["b",10,10]],"start":[4,6],"goal":[8,10]},"heuristic":"euclidean","block":null,"path":[],"pops":9,"pushes":9}]}
\ No newline at end of file
diff --git a/web/src/lib/__fixtures__/parity-part-b.json b/web/src/lib/__fixtures__/parity-part-b.json
new file mode 100644
index 0000000..209d7cc
--- /dev/null
+++ b/web/src/lib/__fixtures__/parity-part-b.json
@@ -0,0 +1 @@
+{"meta":{"generatedBy":"scripts/generate_parity_fixtures.py","python":"3.12.7","implementation":"CPython"},"scoreMatrices":{"2":[[1.0,1.0],[1.0,1.0]],"3":[[2.0,2.0,2.0],[2.0,1.0,2.0],[2.0,2.0,2.0]],"4":[[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0],[2.0,2.0,2.0,2.0]],"5":[[3.0,3.0,3.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0],[3.0,3.0,1.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0]],"6":[[3.0,3.0,3.0,3.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0,3.0],[3.0,3.0,2.0,2.0,3.0,3.0],[3.0,3.0,2.0,2.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0,3.0],[3.0,3.0,3.0,3.0,3.0,3.0]],"7":[[4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,3.0,3.0,3.0,4.0,4.0],[4.0,4.0,3.0,1.0,3.0,4.0,4.0],[4.0,4.0,3.0,3.0,3.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0]],"8":[[4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,3.0,3.0,3.0,3.0,4.0,4.0],[4.0,4.0,3.0,2.0,2.0,3.0,4.0,4.0],[4.0,4.0,3.0,2.0,2.0,3.0,4.0,4.0],[4.0,4.0,3.0,3.0,3.0,3.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0],[4.0,4.0,4.0,4.0,4.0,4.0,4.0,4.0]],"9":[[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,4.0,4.0,4.0,4.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,3.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,1.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,3.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,4.0,4.0,4.0,4.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0]],"10":[[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,4.0,4.0,4.0,4.0,4.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,3.0,3.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,2.0,2.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,2.0,2.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,3.0,3.0,3.0,3.0,4.0,5.0,5.0],[5.0,5.0,4.0,4.0,4.0,4.0,4.0,4.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0],[5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0]],"11":[[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,4.0,4.0,4.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,3.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,1.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,3.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,4.0,4.0,4.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0]],"12":[[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,4.0,4.0,4.0,4.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,3.0,3.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,2.0,2.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,2.0,2.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,3.0,3.0,3.0,3.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,4.0,4.0,4.0,4.0,4.0,4.0,5.0,6.0,6.0],[6.0,6.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,5.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0],[6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0,6.0]]},"refereeGames":[{"n":3,"actions":[["PLACE",1,0],["PLACE",2,0],["PLACE",0,1],["PLACE",1,1],["PLACE",1,2],["PLACE",0,2]],"steps":[{"captures":[],"board":"000100000","result":null},{"captures":[],"board":"000100200","result":null},{"captures":[],"board":"010100200","result":null},{"captures":[],"board":"010120200","result":null},{"captures":[],"board":"010121200","result":null},{"captures":[[0,1],[1,2]],"board":"002120200","result":"winner: blue"}]},{"n":4,"actions":[["PLACE",0,1],["PLACE",0,2],["PLACE",0,0],["PLACE",3,1],["PLACE",2,1],["PLACE",1,1],["PLACE",2,0],["PLACE",3,0],["PLACE",1,0],["PLACE",3,3],["PLACE",2,0],["PLACE",0,3],["PLACE",1,3],["PLACE",2,2],["PLACE",1,2],["PLACE",3,2]],"steps":[{"captures":[],"board":"0100000000000000","result":null},{"captures":[],"board":"0120000000000000","result":null},{"captures":[],"board":"1120000000000000","result":null},{"captures":[],"board":"1120000000000200","result":null},{"captures":[],"board":"1120000001000200","result":null},{"captures":[],"board":"1120020001000200","result":null},{"captures":[],"board":"1120020011000200","result":null},{"captures":[[2,0],[2,1]],"board":"1120020000002200","result":null},{"captures":[],"board":"1120120000002200","result":null},{"captures":[],"board":"1120120000002202","result":null},{"captures":[],"board":"1120120010002202","result":null},{"captures":[],"board":"1122120010002202","result":null},{"captures":[],"board":"1122120110002202","result":null},{"captures":[],"board":"1122120110202202","result":null},{"captures":[[0,2],[0,3],[1,1],[2,2]],"board":"1100101110002202","result":null},{"captures":[],"board":"1100101110002222","result":"winner: blue"}]},{"n":5,"actions":[["PLACE",0,2],["PLACE",1,1],["PLACE",1,4],["PLACE",2,1],["PLACE",0,3],["PLACE",1,0],["PLACE",2,3],["PLACE",4,3],["PLACE",0,4],["PLACE",2,0],["PLACE",1,2],["PLACE",4,4],["PLACE",3,2],["PLACE",1,3],["PLACE",2,2],["PLACE",3,0],["PLACE",2,4],["PLACE",0,1],["PLACE",4,1]],"steps":[{"captures":[],"board":"0010000000000000000000000","result":null},{"captures":[],"board":"0010002000000000000000000","result":null},{"captures":[],"board":"0010002001000000000000000","result":null},{"captures":[],"board":"0010002001020000000000000","result":null},{"captures":[],"board":"0011002001020000000000000","result":null},{"captures":[],"board":"0011022001020000000000000","result":null},{"captures":[],"board":"0011022001020100000000000","result":null},{"captures":[],"board":"0011022001020100000000020","result":null},{"captures":[],"board":"0011122001020100000000020","result":null},{"captures":[],"board":"0011122001220100000000020","result":null},{"captures":[],"board":"0011122101220100000000020","result":null},{"captures":[],"board":"0011122101220100000000022","result":null},{"captures":[],"board":"0011122101220100010000022","result":null},{"captures":[],"board":"0011122121220100010000022","result":null},{"captures":[[1,3],[2,1]],"board":"0011122101201100010000022","result":null},{"captures":[],"board":"0011122101201102010000022","result":null},{"captures":[],"board":"0011122101201112010000022","result":null},{"captures":[],"board":"0211122101201112010000022","result":null},{"captures":[],"board":"0211122101201112010001022","result":"winner: red"}]},{"n":6,"actions":[["PLACE",1,4],["STEAL"],["PLACE",4,0],["PLACE",5,0],["PLACE",3,1],["PLACE",5,1],["PLACE",3,2],["PLACE",4,2],["PLACE",3,3],["PLACE",2,3],["PLACE",3,2],["PLACE",4,4],["PLACE",5,3],["PLACE",3,5],["PLACE",4,5],["PLACE",4,3]],"steps":[{"captures":[],"board":"000000000010000000000000000000000000","result":null},{"captures":[],"board":"000000000000000000000000020000000000","result":null},{"captures":[],"board":"000000000000000000000000120000000000","result":null},{"captures":[],"board":"000000000000000000000000120000200000","result":null},{"captures":[],"board":"000000000000000000010000120000200000","result":null},{"captures":[],"board":"000000000000000000010000120000220000","result":null},{"captures":[],"board":"000000000000000000011000120000220000","result":null},{"captures":[],"board":"000000000000000000011000122000220000","result":null},{"captures":[],"board":"000000000000000000011100122000220000","result":null},{"captures":[[3,2],[3,3]],"board":"000000000000000200010000122000220000","result":null},{"captures":[],"board":"000000000000000200011000122000220000","result":null},{"captures":[],"board":"000000000000000200011000122020220000","result":null},{"captures":[],"board":"000000000000000200011000122020220100","result":null},{"captures":[],"board":"000000000000000200011002122020220100","result":null},{"captures":[],"board":"000000000000000200011002122021220100","result":null},{"captures":[],"board":"000000000000000200011002122221220100","result":"winner: blue"}]},{"n":7,"actions":[["PLACE",3,6],["PLACE",4,4],["PLACE",4,3],["PLACE",3,4],["PLACE",3,3],["PLACE",5,3],["PLACE",4,5],["PLACE",6,1],["PLACE",3,5],["PLACE",6,3],["PLACE",4,4],["PLACE",1,1],["PLACE",2,5],["PLACE",2,3],["PLACE",6,4],["PLACE",1,5],["PLACE",0,2],["PLACE",1,0],["PLACE",1,6],["PLACE",6,0],["PLACE",5,4],["PLACE",3,4],["PLACE",5,5],["PLACE",3,2],["PLACE",2,0],["PLACE",5,1],["PLACE",2,4],["PLACE",5,0],["PLACE",5,6],["PLACE",3,4],["PLACE",1,5],["PLACE",0,6],["PLACE",0,1],["PLACE",4,6],["PLACE",6,2],["PLACE",3,1],["PLACE",6,5],["PLACE",2,1],["PLACE",1,4],["PLACE",2,6],["PLACE",4,2],["PLACE",6,3],["PLACE",1,3],["PLACE",5,2],["PLACE",4,3],["PLACE",1,1],["PLACE",5,3],["PLACE",6,6],["PLACE",3,0],["PLACE",4,1],["PLACE",5,2],["PLACE",2,5],["PLACE",0,5]],"steps":[{"captures":[],"board":"0000000000000000000000000001000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000001000020000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000001000120000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000201000120000000000000000","result":null},{"captures":[],"board":"0000000000000000000000001201000120000000000000000","result":null},{"captures":[],"board":"0000000000000000000000001201000120000020000000000","result":null},{"captures":[],"board":"0000000000000000000000001201000121000020000000000","result":null},{"captures":[],"board":"0000000000000000000000001201000121000020000200000","result":null},{"captures":[[3,4],[4,4]],"board":"0000000000000000000000001011000101000020000200000","result":null},{"captures":[],"board":"0000000000000000000000001011000101000020000202000","result":null},{"captures":[],"board":"0000000000000000000000001011000111000020000202000","result":null},{"captures":[],"board":"0000000020000000000000001011000111000020000202000","result":null},{"captures":[],"board":"0000000020000000000100001011000111000020000202000","result":null},{"captures":[],"board":"0000000020000000020100001011000111000020000202000","result":null},{"captures":[],"board":"0000000020000000020100001011000111000020000202100","result":null},{"captures":[],"board":"0000000020002000020100001011000111000020000202100","result":null},{"captures":[],"board":"0010000020002000020100001011000111000020000202100","result":null},{"captures":[],"board":"0010000220002000020100001011000111000020000202100","result":null},{"captures":[],"board":"0010000220002100020100001011000111000020000202100","result":null},{"captures":[],"board":"0010000220002100020100001011000111000020002202100","result":null},{"captures":[],"board":"0010000220002100020100001011000111000021002202100","result":null},{"captures":[[4,3],[4,4]],"board":"0010000220002100020100001211000001000021002202100","result":null},{"captures":[],"board":"0010000220002100020100001211000001000021102202100","result":null},{"captures":[],"board":"0010000220002100020100021211000001000021102202100","result":null},{"captures":[],"board":"0010000220002110020100021211000001000021102202100","result":null},{"captures":[],"board":"0010000220002110020100021211000001002021102202100","result":null},{"captures":[[1,5],[2,3],[3,4]],"board":"0010000220000110001100021011000001002021102202100","result":null},{"captures":[],"board":"0010000220000110001100021011000001022021102202100","result":null},{"captures":[],"board":"0010000220000110001100021011000001022021112202100","result":null},{"captures":[],"board":"0010000220000110001100021211000001022021112202100","result":null},{"captures":[],"board":"0010000220001110001100021211000001022021112202100","result":null},{"captures":[],"board":"0010002220001110001100021211000001022021112202100","result":null},{"captures":[[1,0],[1,1]],"board":"0110002000001110001100021211000001022021112202100","result":null},{"captures":[],"board":"0110002000001110001100021211000001222021112202100","result":null},{"captures":[[5,3],[6,3]],"board":"0110002000001110001100021211000001222001112210100","result":null},{"captures":[],"board":"0110002000001110001100221211000001222001112210100","result":null},{"captures":[],"board":"0110002000001110001100221211000001222001112210110","result":null},{"captures":[],"board":"0110002000001112001100221211000001222001112210110","result":null},{"captures":[],"board":"0110002000011112001100221211000001222001112210110","result":null},{"captures":[[2,5],[3,5]],"board":"0110002000011112001020221201000001222001112210110","result":null},{"captures":[],"board":"0110002000011112001020221201001001222001112210110","result":null},{"captures":[],"board":"0110002000011112001020221201001001222001112212110","result":null},{"captures":[],"board":"0110002000111112001020221201001001222001112212110","result":null},{"captures":[],"board":"0110002000111112001020221201001001222201112212110","result":null},{"captures":[],"board":"0110002000111112001020221201001101222201112212110","result":null},{"captures":[],"board":"0110002020111112001020221201001101222201112212110","result":null},{"captures":[[5,2],[6,3]],"board":"0110002020111112001020221201001101222011112210110","result":null},{"captures":[],"board":"0110002020111112001020221201001101222011112210112","result":null},{"captures":[],"board":"0110002020111112001021221201001101222011112210112","result":null},{"captures":[],"board":"0110002020111112001021221201021101222011112210112","result":null},{"captures":[],"board":"0110002020111112001021221201021101222111112210112","result":null},{"captures":[[1,5],[1,6]],"board":"0110002020110012001221221201021101222111112210112","result":null},{"captures":[],"board":"0110012020110012001221221201021101222111112210112","result":"winner: red"}]},{"n":8,"actions":[["PLACE",3,6],["STEAL"],["PLACE",5,3],["PLACE",3,4],["PLACE",2,5],["PLACE",0,6],["PLACE",2,6],["PLACE",3,3],["PLACE",3,5],["PLACE",5,4],["PLACE",2,4],["PLACE",1,4],["PLACE",2,3],["PLACE",7,7],["PLACE",7,3],["PLACE",1,4],["PLACE",7,4],["PLACE",6,5],["PLACE",0,5],["PLACE",0,7],["PLACE",3,1],["PLACE",4,6],["PLACE",5,5],["PLACE",4,5],["PLACE",2,2],["PLACE",6,7],["PLACE",2,7],["PLACE",3,2],["PLACE",6,2],["PLACE",2,0],["PLACE",3,7],["PLACE",0,4],["PLACE",1,2],["PLACE",0,2],["PLACE",4,7],["PLACE",0,3],["PLACE",4,3],["PLACE",4,1],["PLACE",1,6],["PLACE",7,5],["PLACE",7,2],["PLACE",1,7],["PLACE",6,4],["PLACE",5,2],["PLACE",7,6],["PLACE",5,4],["PLACE",1,0],["PLACE",5,1],["PLACE",6,1],["PLACE",6,0],["PLACE",3,3],["PLACE",7,0],["PLACE",7,1],["PLACE",6,5],["PLACE",4,0],["PLACE",1,5],["PLACE",0,5],["PLACE",6,4],["PLACE",0,0],["PLACE",5,5],["PLACE",5,7],["PLACE",2,5],["PLACE",6,6],["PLACE",4,2],["PLACE",1,6],["PLACE",6,3],["PLACE",1,3],["PLACE",1,4],["PLACE",1,5]],"steps":[{"captures":[],"board":"0000000000000000000000000000001000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000002000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000100000002000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000200000000000000100000002000000000000","result":null},{"captures":[],"board":"0000000000000000000001000000200000000000000100000002000000000000","result":null},{"captures":[],"board":"0000002000000000000001000000200000000000000100000002000000000000","result":null},{"captures":[],"board":"0000002000000000000001100000200000000000000100000002000000000000","result":null},{"captures":[],"board":"0000002000000000000001100002200000000000000100000002000000000000","result":null},{"captures":[],"board":"0000002000000000000001100002210000000000000100000002000000000000","result":null},{"captures":[],"board":"0000002000000000000001100002210000000000000120000002000000000000","result":null},{"captures":[],"board":"0000002000000000000011100002210000000000000120000002000000000000","result":null},{"captures":[],"board":"0000002000002000000011100002210000000000000120000002000000000000","result":null},{"captures":[[1,4],[3,3]],"board":"0000002000000000000111100000210000000000000120000002000000000000","result":null},{"captures":[],"board":"0000002000000000000111100000210000000000000120000002000000000002","result":null},{"captures":[],"board":"0000002000000000000111100000210000000000000120000002000000010002","result":null},{"captures":[],"board":"0000002000002000000111100000210000000000000120000002000000010002","result":null},{"captures":[],"board":"0000002000002000000111100000210000000000000120000002000000011002","result":null},{"captures":[],"board":"0000002000002000000111100000210000000000000120000002020000011002","result":null},{"captures":[],"board":"0000012000002000000111100000210000000000000120000002020000011002","result":null},{"captures":[],"board":"0000012200002000000111100000210000000000000120000002020000011002","result":null},{"captures":[],"board":"0000012200002000000111100100210000000000000120000002020000011002","result":null},{"captures":[],"board":"0000012200002000000111100100210000000020000120000002020000011002","result":null},{"captures":[],"board":"0000012200002000000111100100210000000020000121000002020000011002","result":null},{"captures":[],"board":"0000012200002000000111100100210000000220000121000002020000011002","result":null},{"captures":[],"board":"0000012200002000001111100100210000000220000121000002020000011002","result":null},{"captures":[],"board":"0000012200002000001111100100210000000220000121000002020200011002","result":null},{"captures":[],"board":"0000012200002000001111110100210000000220000121000002020200011002","result":null},{"captures":[],"board":"0000012200002000001111110120210000000220000121000002020200011002","result":null},{"captures":[],"board":"0000012200002000001111110120210000000220000121000012020200011002","result":null},{"captures":[],"board":"0000012200002000201111110120210000000220000121000012020200011002","result":null},{"captures":[],"board":"0000012200002000201111110120210100000220000121000012020200011002","result":null},{"captures":[],"board":"0000212200002000201111110120210100000220000121000012020200011002","result":null},{"captures":[],"board":"0000212200102000201111110120210100000220000121000012020200011002","result":null},{"captures":[],"board":"0020212200102000201111110120210100000220000121000012020200011002","result":null},{"captures":[],"board":"0020212200102000201111110120210100000221000121000012020200011002","result":null},{"captures":[],"board":"0022212200102000201111110120210100000221000121000012020200011002","result":null},{"captures":[],"board":"0022212200102000201111110120210100010221000121000012020200011002","result":null},{"captures":[],"board":"0022212200102000201111110120210102010221000121000012020200011002","result":null},{"captures":[],"board":"0022212200102010201111110120210102010221000121000012020200011002","result":null},{"captures":[],"board":"0022212200102010201111110120210102010221000121000012020200011202","result":null},{"captures":[],"board":"0022212200102010201111110120210102010221000121000012020200111202","result":null},{"captures":[],"board":"0022212200102012201111110120210102010221000121000012020200111202","result":null},{"captures":[[5,4],[6,3],[6,5]],"board":"0022212200102012201111110120210102010221000101000010100200111202","result":null},{"captures":[],"board":"0022212200102012201111110120210102010221002101000010100200111202","result":null},{"captures":[],"board":"0022212200102012201111110120210102010221002101000010100200111212","result":null},{"captures":[],"board":"0022212200102012201111110120210102010221002121000010100200111212","result":null},{"captures":[],"board":"0022212210102012201111110120210102010221002121000010100200111212","result":null},{"captures":[],"board":"0022212210102012201111110120210102010221022121000010100200111212","result":null},{"captures":[],"board":"0022212210102012201111110120210102010221022121000110100200111212","result":null},{"captures":[],"board":"0022212210102012201111110120210102010221022121002110100200111212","result":null},{"captures":[],"board":"0022212210102012201111110121210102010221022121002110100200111212","result":null},{"captures":[],"board":"0022212210102012201111110121210102010221022121002110100220111212","result":null},{"captures":[],"board":"0022212210102012201111110121210102010221022121002110100221111212","result":null},{"captures":[[5,5],[6,4]],"board":"0022212210102012201111110121210102010221022120002110020221111212","result":null},{"captures":[],"board":"0022212210102012201111110121210112010221022120002110020221111212","result":null},{"captures":[[0,5],[1,6],[2,4],[2,5]],"board":"0022202210102202201100110121210112010221022120002110020221111212","result":null},{"captures":[],"board":"0022212210102202201100110121210112010221022120002110020221111212","result":null},{"captures":[],"board":"0022212210102202201100110121210112010221022120002110220221111212","result":null},{"captures":[],"board":"1022212210102202201100110121210112010221022120002110220221111212","result":null},{"captures":[],"board":"1022212210102202201100110121210112010221022122002110220221111212","result":null},{"captures":[],"board":"1022212210102202201100110121210112010221022122012110220221111212","result":null},{"captures":[],"board":"1022212210102202201102110121210112010221022122012110220221111212","result":null},{"captures":[[6,5],[6,7],[7,5]],"board":"1022212210102202201102110121210112010221022122012110201021111012","result":null},{"captures":[[3,3],[4,3]],"board":"1022212210102202201102110120210112200221022122012110201021111012","result":null},{"captures":[[0,6],[1,5],[1,7],[2,5]],"board":"1022210210102010201100110120210112200221022122012110201021111012","result":null},{"captures":[[5,3],[6,2]],"board":"1022210210102010201100110120210112200221022022012102201021111012","result":null},{"captures":[[0,4],[1,4]],"board":"1022010210110010201100110120210112200221022022012102201021111012","result":null},{"captures":[],"board":"1022010210112010201100110120210112200221022022012102201021111012","result":null},{"captures":[],"board":"1022010210112110201100110120210112200221022022012102201021111012","result":"winner: red"}]},{"n":3,"actions":[["PLACE",0,0],["PLACE",1,0],["PLACE",0,1],["PLACE",2,0],["PLACE",1,1],["PLACE",2,1],["PLACE",1,2],["PLACE",2,2]],"steps":[{"captures":[],"board":"100000000","result":null},{"captures":[],"board":"100200000","result":null},{"captures":[],"board":"110200000","result":null},{"captures":[],"board":"110200200","result":null},{"captures":[],"board":"110210200","result":null},{"captures":[],"board":"110210220","result":null},{"captures":[],"board":"110211220","result":null},{"captures":[],"board":"110211222","result":"winner: blue"}]},{"n":4,"actions":[["PLACE",0,3],["PLACE",0,2],["PLACE",1,2],["PLACE",2,1],["PLACE",2,3],["PLACE",3,1],["PLACE",1,1],["PLACE",0,1],["PLACE",0,0],["PLACE",3,0],["PLACE",2,1],["PLACE",3,3],["PLACE",2,2],["PLACE",1,0],["PLACE",3,2]],"steps":[{"captures":[],"board":"0001000000000000","result":null},{"captures":[],"board":"0021000000000000","result":null},{"captures":[],"board":"0021001000000000","result":null},{"captures":[],"board":"0021001002000000","result":null},{"captures":[],"board":"0021001002010000","result":null},{"captures":[],"board":"0021001002010200","result":null},{"captures":[[0,2],[2,1]],"board":"0001011000010200","result":null},{"captures":[],"board":"0201011000010200","result":null},{"captures":[],"board":"1201011000010200","result":null},{"captures":[],"board":"1201011000012200","result":null},{"captures":[],"board":"1201011001012200","result":null},{"captures":[],"board":"1201011001012202","result":null},{"captures":[],"board":"1201011001112202","result":null},{"captures":[[0,0],[1,1]],"board":"0201201001112202","result":null},{"captures":[],"board":"0201201001112212","result":"winner: red"}]},{"n":5,"actions":[["PLACE",3,0],["STEAL"],["PLACE",1,0],["PLACE",2,0],["PLACE",1,1],["PLACE",0,2],["PLACE",0,1],["PLACE",2,1],["PLACE",1,3],["PLACE",2,4],["PLACE",2,3],["PLACE",4,3],["PLACE",3,1],["PLACE",2,2],["PLACE",3,4],["PLACE",1,4],["PLACE",3,0],["PLACE",4,4],["PLACE",3,2],["PLACE",1,3],["PLACE",0,0],["PLACE",0,4],["PLACE",4,1],["PLACE",2,3],["PLACE",4,2],["PLACE",3,3],["PLACE",1,2],["PLACE",3,4],["PLACE",4,0],["PLACE",2,1],["PLACE",2,0]],"steps":[{"captures":[],"board":"0000000000000001000000000","result":null},{"captures":[],"board":"0002000000000000000000000","result":null},{"captures":[],"board":"0002010000000000000000000","result":null},{"captures":[],"board":"0002010000200000000000000","result":null},{"captures":[],"board":"0002011000200000000000000","result":null},{"captures":[],"board":"0022011000200000000000000","result":null},{"captures":[],"board":"0122011000200000000000000","result":null},{"captures":[],"board":"0122011000220000000000000","result":null},{"captures":[],"board":"0122011010220000000000000","result":null},{"captures":[],"board":"0122011010220020000000000","result":null},{"captures":[],"board":"0122011010220120000000000","result":null},{"captures":[],"board":"0122011010220120000000020","result":null},{"captures":[],"board":"0122011010220120100000020","result":null},{"captures":[],"board":"0122011010222120100000020","result":null},{"captures":[],"board":"0122011010222120100100020","result":null},{"captures":[[1,3],[2,3]],"board":"0122011002222020100100020","result":null},{"captures":[[2,0],[2,1]],"board":"0122011002002021100100020","result":null},{"captures":[],"board":"0122011002002021100100022","result":null},{"captures":[],"board":"0122011002002021110100022","result":null},{"captures":[],"board":"0122011022002021110100022","result":null},{"captures":[],"board":"1122011022002021110100022","result":null},{"captures":[],"board":"1122211022002021110100022","result":null},{"captures":[],"board":"1122211022002021110101022","result":null},{"captures":[],"board":"1122211022002221110101022","result":null},{"captures":[],"board":"1122211022002221110101122","result":null},{"captures":[[3,4],[4,2]],"board":"1122211022002221112001022","result":null},{"captures":[],"board":"1122211122002221112001022","result":null},{"captures":[],"board":"1122211122002221112201022","result":null},{"captures":[],"board":"1122211122002221112211022","result":null},{"captures":[[1,1],[1,2],[3,1]],"board":"1122210022022221012211022","result":null},{"captures":[],"board":"1122210022122221012211022","result":"winner: red"}]},{"n":6,"actions":[["PLACE",0,5],["PLACE",1,4],["PLACE",1,2],["PLACE",1,5],["PLACE",0,4],["PLACE",1,1],["PLACE",2,5],["PLACE",3,5],["PLACE",5,4],["PLACE",1,0],["PLACE",4,5],["PLACE",5,5],["PLACE",0,3],["PLACE",5,0],["PLACE",4,3],["PLACE",4,4],["PLACE",3,3],["PLACE",4,5],["PLACE",3,4],["PLACE",3,2],["PLACE",0,2],["PLACE",1,3],["PLACE",5,4],["PLACE",4,0],["PLACE",5,3],["PLACE",2,1],["PLACE",2,0],["PLACE",5,1],["PLACE",5,2],["PLACE",0,0],["PLACE",3,0],["PLACE",4,2],["PLACE",4,1],["PLACE",2,1],["PLACE",1,1],["PLACE",5,1],["PLACE",1,0],["PLACE",3,2],["PLACE",2,2],["PLACE",0,1],["PLACE",2,3]],"steps":[{"captures":[],"board":"000001000000000000000000000000000000","result":null},{"captures":[],"board":"000001000020000000000000000000000000","result":null},{"captures":[],"board":"000001001020000000000000000000000000","result":null},{"captures":[],"board":"000001001022000000000000000000000000","result":null},{"captures":[],"board":"000011001022000000000000000000000000","result":null},{"captures":[],"board":"000011021022000000000000000000000000","result":null},{"captures":[],"board":"000011021022000001000000000000000000","result":null},{"captures":[],"board":"000011021022000001000002000000000000","result":null},{"captures":[],"board":"000011021022000001000002000000000010","result":null},{"captures":[],"board":"000011221022000001000002000000000010","result":null},{"captures":[],"board":"000011221022000001000002000001000010","result":null},{"captures":[],"board":"000011221022000001000002000001000012","result":null},{"captures":[],"board":"000111221022000001000002000001000012","result":null},{"captures":[],"board":"000111221022000001000002000001200012","result":null},{"captures":[],"board":"000111221022000001000002000101200012","result":null},{"captures":[[4,5],[5,4]],"board":"000111221022000001000002000120200002","result":null},{"captures":[],"board":"000111221022000001000102000120200002","result":null},{"captures":[],"board":"000111221022000001000102000122200002","result":null},{"captures":[],"board":"000111221022000001000112000122200002","result":null},{"captures":[],"board":"000111221022000001002112000122200002","result":null},{"captures":[],"board":"001111221022000001002112000122200002","result":null},{"captures":[],"board":"001111221222000001002112000122200002","result":null},{"captures":[],"board":"001111221222000001002112000122200012","result":null},{"captures":[],"board":"001111221222000001002112200122200012","result":null},{"captures":[],"board":"001111221222000001002112200122200112","result":null},{"captures":[],"board":"001111221222020001002112200122200112","result":null},{"captures":[[1,1],[2,1]],"board":"001111201222100001002112200122200112","result":null},{"captures":[],"board":"001111201222100001002112200122220112","result":null},{"captures":[],"board":"001111201222100001002112200122221112","result":null},{"captures":[],"board":"201111201222100001002112200122221112","result":null},{"captures":[],"board":"201111201222100001102112200122221112","result":null},{"captures":[],"board":"201111201222100001102112202122221112","result":null},{"captures":[[3,2],[4,2],[5,1]],"board":"201111201222100001100112210122201112","result":null},{"captures":[],"board":"201111201222120001100112210122201112","result":null},{"captures":[[1,0],[2,1]],"board":"201111011222100001100112210122201112","result":null},{"captures":[],"board":"201111011222100001100112210122221112","result":null},{"captures":[],"board":"201111111222100001100112210122221112","result":null},{"captures":[],"board":"201111111222100001102112210122221112","result":null},{"captures":[],"board":"201111111222101001102112210122221112","result":null},{"captures":[],"board":"221111111222101001102112210122221112","result":null},{"captures":[[1,3],[1,4],[3,2]],"board":"221111111002101101100112210122221112","result":"winner: red"}]},{"n":7,"actions":[["PLACE",3,5],["PLACE",4,5],["PLACE",5,5],["PLACE",2,2],["PLACE",2,3],["PLACE",2,1],["PLACE",1,6],["PLACE",3,2],["PLACE",1,4],["PLACE",4,2],["PLACE",3,6],["PLACE",2,0],["PLACE",4,3],["PLACE",5,1],["PLACE",2,6],["PLACE",1,3],["PLACE",3,1],["PLACE",1,0],["PLACE",0,0],["PLACE",3,3],["PLACE",5,6],["PLACE",5,0],["PLACE",5,4],["PLACE",1,2],["PLACE",0,6],["PLACE",4,0],["PLACE",4,6],["PLACE",1,1],["PLACE",4,1],["PLACE",4,4],["PLACE",6,6]],"steps":[{"captures":[],"board":"0000000000000000000000000010000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000010000002000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000010000002000000100000000","result":null},{"captures":[],"board":"0000000000000000200000000010000002000000100000000","result":null},{"captures":[],"board":"0000000000000000210000000010000002000000100000000","result":null},{"captures":[],"board":"0000000000000002210000000010000002000000100000000","result":null},{"captures":[],"board":"0000000000000102210000000010000002000000100000000","result":null},{"captures":[],"board":"0000000000000102210000020010000002000000100000000","result":null},{"captures":[],"board":"0000000000010102210000020010000002000000100000000","result":null},{"captures":[],"board":"0000000000010102210000020010002002000000100000000","result":null},{"captures":[],"board":"0000000000010102210000020011002002000000100000000","result":null},{"captures":[],"board":"0000000000010122210000020011002002000000100000000","result":null},{"captures":[],"board":"0000000000010122210000020011002102000000100000000","result":null},{"captures":[],"board":"0000000000010122210000020011002102002000100000000","result":null},{"captures":[],"board":"0000000000010122210010020011002102002000100000000","result":null},{"captures":[],"board":"0000000000210122210010020011002102002000100000000","result":null},{"captures":[[2,2],[3,2]],"board":"0000000000210122010010100011002102002000100000000","result":null},{"captures":[],"board":"0000000200210122010010100011002102002000100000000","result":null},{"captures":[],"board":"1000000200210122010010100011002102002000100000000","result":null},{"captures":[],"board":"1000000200210122010010102011002102002000100000000","result":null},{"captures":[],"board":"1000000200210122010010102011002102002000110000000","result":null},{"captures":[],"board":"1000000200210122010010102011002102022000110000000","result":null},{"captures":[],"board":"1000000200210122010010102011002102022001110000000","result":null},{"captures":[],"board":"1000000202210122010010102011002102022001110000000","result":null},{"captures":[],"board":"1000001202210122010010102011002102022001110000000","result":null},{"captures":[],"board":"1000001202210122010010102011202102022001110000000","result":null},{"captures":[],"board":"1000001202210122010010102011202102122001110000000","result":null},{"captures":[],"board":"1000001222210122010010102011202102122001110000000","result":null},{"captures":[],"board":"1000001222210122010010102011212102122001110000000","result":null},{"captures":[[3,5],[5,4]],"board":"1000001222210122010010102001212122122000110000000","result":null},{"captures":[],"board":"1000001222210122010010102001212122122000110000001","result":"winner: red"}]},{"n":8,"actions":[["PLACE",3,3],["PLACE",3,2],["PLACE",3,1],["PLACE",2,3],["PLACE",0,6],["PLACE",4,1],["PLACE",4,2],["PLACE",6,2],["PLACE",6,1],["PLACE",6,6],["PLACE",3,4],["PLACE",2,2],["PLACE",4,0],["PLACE",5,2],["PLACE",3,0],["PLACE",4,4],["PLACE",6,0],["PLACE",1,2],["PLACE",1,4],["PLACE",4,6],["PLACE",3,6],["PLACE",7,0],["PLACE",5,0],["PLACE",4,1],["PLACE",5,7],["PLACE",7,3],["PLACE",0,3],["PLACE",1,1],["PLACE",5,1],["PLACE",0,7],["PLACE",2,0],["PLACE",7,4],["PLACE",2,7],["PLACE",0,1],["PLACE",6,5],["PLACE",2,1],["PLACE",0,2],["PLACE",4,5],["PLACE",0,4],["PLACE",3,2],["PLACE",1,5],["PLACE",4,7],["PLACE",7,6],["PLACE",7,2],["PLACE",1,3],["PLACE",2,6],["PLACE",4,1],["PLACE",7,5],["PLACE",5,6],["PLACE",2,4],["PLACE",4,7],["PLACE",6,5],["PLACE",1,7],["PLACE",6,3],["PLACE",7,6],["PLACE",5,3],["PLACE",4,3],["PLACE",6,6],["PLACE",5,4],["PLACE",6,7],["PLACE",1,4],["PLACE",5,5],["PLACE",3,7],["PLACE",2,5],["PLACE",1,5],["PLACE",3,5],["PLACE",7,6],["PLACE",4,4],["PLACE",3,3],["PLACE",3,4],["PLACE",2,3],["PLACE",2,2],["PLACE",3,2],["PLACE",7,7],["PLACE",7,1]],"steps":[{"captures":[],"board":"0000000000000000000000000001000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000021000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000121000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000200000121000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000001000000000000200000121000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000001000000000000200000121000002000000000000000000000000000000","result":null},{"captures":[[3,2],[4,1]],"board":"0000001000000000000200000101000000100000000000000000000000000000","result":null},{"captures":[],"board":"0000001000000000000200000101000000100000000000000020000000000000","result":null},{"captures":[],"board":"0000001000000000000200000101000000100000000000000120000000000000","result":null},{"captures":[],"board":"0000001000000000000200000101000000100000000000000120002000000000","result":null},{"captures":[],"board":"0000001000000000000200000101100000100000000000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200000101100000100000000000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200000101100010100000000000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200000101100010100000002000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200001101100010100000002000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200001101100010102000002000000120002000000000","result":null},{"captures":[],"board":"0000001000000000002200001101100010102000002000001120002000000000","result":null},{"captures":[],"board":"0000001000200000002200001101100010102000002000001120002000000000","result":null},{"captures":[],"board":"0000001000201000002200001101100010102000002000001120002000000000","result":null},{"captures":[],"board":"0000001000201000002200001101100010102020002000001120002000000000","result":null},{"captures":[],"board":"0000001000201000002200001101101010102020002000001120002000000000","result":null},{"captures":[],"board":"0000001000201000002200001101101010102020002000001120002020000000","result":null},{"captures":[],"board":"0000001000201000002200001101101010102020102000001120002020000000","result":null},{"captures":[],"board":"0000001000201000002200001101101012102020102000001120002020000000","result":null},{"captures":[],"board":"0000001000201000002200001101101012102020102000011120002020000000","result":null},{"captures":[],"board":"0000001000201000002200001101101012102020102000011120002020020000","result":null},{"captures":[],"board":"0001001000201000002200001101101012102020102000011120002020020000","result":null},{"captures":[],"board":"0001001002201000002200001101101012102020102000011120002020020000","result":null},{"captures":[[4,1],[5,2]],"board":"0001001002201000002200001101101010102020110000011120002020020000","result":null},{"captures":[],"board":"0001001202201000002200001101101010102020110000011120002020020000","result":null},{"captures":[],"board":"0001001202201000102200001101101010102020110000011120002020020000","result":null},{"captures":[],"board":"0001001202201000102200001101101010102020110000011120002020022000","result":null},{"captures":[],"board":"0001001202201000102200011101101010102020110000011120002020022000","result":null},{"captures":[],"board":"0201001202201000102200011101101010102020110000011120002020022000","result":null},{"captures":[],"board":"0201001202201000102200011101101010102020110000011120012020022000","result":null},{"captures":[],"board":"0201001202201000122200011101101010102020110000011120012020022000","result":null},{"captures":[],"board":"0211001202201000122200011101101010102020110000011120012020022000","result":null},{"captures":[],"board":"0211001202201000122200011101101010102220110000011120012020022000","result":null},{"captures":[],"board":"0211101202201000122200011101101010102220110000011120012020022000","result":null},{"captures":[],"board":"0211101202201000122200011121101010102220110000011120012020022000","result":null},{"captures":[],"board":"0211101202201100122200011121101010102220110000011120012020022000","result":null},{"captures":[],"board":"0211101202201100122200011121101010102222110000011120012020022000","result":null},{"captures":[],"board":"0211101202201100122200011121101010102222110000011120012020022010","result":null},{"captures":[],"board":"0211101202201100122200011121101010102222110000011120012020222010","result":null},{"captures":[],"board":"0211101202211100122200011121101010102222110000011120012020222010","result":null},{"captures":[],"board":"0211101202211100122200211121101010102222110000011120012020222010","result":null},{"captures":[],"board":"0211101202211100122200211121101011102222110000011120012020222010","result":null},{"captures":[[6,5],[7,6]],"board":"0211101202211100122200211121101011102222110000011120002020222200","result":null},{"captures":[[4,7],[6,6]],"board":"0211101202211100122200211121101011102220110000111120000020222200","result":null},{"captures":[[1,4],[3,3]],"board":"0211101202210100122220211120101011102220110000111120000020222200","result":null},{"captures":[],"board":"0211101202210100122220211120101011102221110000111120000020222200","result":null},{"captures":[],"board":"0211101202210100122220211120101011102221110000111120020020222200","result":null},{"captures":[],"board":"0211101202210101122220211120101011102221110000111120020020222200","result":null},{"captures":[],"board":"0211101202210101122220211120101011102221110000111122020020222200","result":null},{"captures":[],"board":"0211101202210101122220211120101011102221110000111122020020222210","result":null},{"captures":[],"board":"0211101202210101122220211120101011102221110200111122020020222210","result":null},{"captures":[],"board":"0211101202210101122220211120101011112221110200111122020020222210","result":null},{"captures":[],"board":"0211101202210101122220211120101011112221110200111122022020222210","result":null},{"captures":[[4,4],[5,3]],"board":"0211101202210101122220211120101011110221110010111122022020222210","result":null},{"captures":[[5,7],[7,6]],"board":"0211101202210101122220211120101011110221110010101122022220222200","result":null},{"captures":[],"board":"0211101202211101122220211120101011110221110010101122022220222200","result":null},{"captures":[],"board":"0211101202211101122220211120101011110221110012101122022220222200","result":null},{"captures":[],"board":"0211101202211101122220211120101111110221110012101122022220222200","result":null},{"captures":[[1,5],[3,4]],"board":"0211101202211001122222211120001111110221110012101122022220222200","result":null},{"captures":[],"board":"0211101202211101122222211120001111110221110012101122022220222200","result":null},{"captures":[],"board":"0211101202211101122222211120021111110221110012101122022220222200","result":null},{"captures":[],"board":"0211101202211101122222211120021111110221110012101122022220222210","result":null},{"captures":[],"board":"0211101202211101122222211120021111112221110012101122022220222210","result":null},{"captures":[[2,3],[2,4]],"board":"0211101202211101122002211121021111112221110012101122022220222210","result":null},{"captures":[],"board":"0211101202211101122002211121221111112221110012101122022220222210","result":null},{"captures":[[2,2],[3,2]],"board":"0211101202211101120102211101221111112221110012101122022220222210","result":null},{"captures":[],"board":"0211101202211101122102211101221111112221110012101122022220222210","result":null},{"captures":[],"board":"0211101202211101122102211111221111112221110012101122022220222210","result":null},{"captures":[],"board":"0211101202211101122102211111221111112221110012101122022220222212","result":null},{"captures":[[6,2],[7,0]],"board":"0211101202211101122102211111221111112221110012101102022201222212","result":"winner: red"}]},{"n":3,"actions":[["PLACE",0,0],["PLACE",0,1],["PLACE",1,0],["PLACE",1,1],["PLACE",2,1],["PLACE",2,0],["PLACE",1,2],["PLACE",1,0],["PLACE",0,2],["PLACE",2,1],["PLACE",2,2]],"steps":[{"captures":[],"board":"100000000","result":null},{"captures":[],"board":"120000000","result":null},{"captures":[],"board":"120100000","result":null},{"captures":[],"board":"120120000","result":null},{"captures":[],"board":"120120010","result":null},{"captures":[[1,0],[2,1]],"board":"120020200","result":null},{"captures":[],"board":"120021200","result":null},{"captures":[],"board":"120221200","result":null},{"captures":[],"board":"121221200","result":null},{"captures":[],"board":"121221220","result":null},{"captures":[],"board":"121221221","result":"winner: red"}]},{"n":4,"actions":[["PLACE",3,2],["STEAL"],["PLACE",1,3],["PLACE",1,2],["PLACE",2,1],["PLACE",3,0],["PLACE",2,2],["PLACE",2,0],["PLACE",3,1],["PLACE",1,1],["PLACE",1,0],["PLACE",3,3],["PLACE",1,2],["PLACE",1,1],["PLACE",0,0],["PLACE",2,3],["PLACE",0,2]],"steps":[{"captures":[],"board":"0000000000000010","result":null},{"captures":[],"board":"0000000000020000","result":null},{"captures":[],"board":"0000000100020000","result":null},{"captures":[],"board":"0000002100020000","result":null},{"captures":[],"board":"0000002101020000","result":null},{"captures":[],"board":"0000002101022000","result":null},{"captures":[[1,2],[2,3]],"board":"0000000101102000","result":null},{"captures":[],"board":"0000000121102000","result":null},{"captures":[],"board":"0000000121102100","result":null},{"captures":[],"board":"0000020121102100","result":null},{"captures":[[1,1],[2,0]],"board":"0000100101102100","result":null},{"captures":[],"board":"0000100101102102","result":null},{"captures":[],"board":"0000101101102102","result":null},{"captures":[],"board":"0000121101102102","result":null},{"captures":[],"board":"1000121101102102","result":null},{"captures":[],"board":"1000121101122102","result":null},{"captures":[],"board":"1010121101122102","result":"winner: red"}]},{"n":5,"actions":[["PLACE",0,0],["PLACE",1,0],["PLACE",0,1],["PLACE",0,2],["PLACE",0,4],["PLACE",3,0],["PLACE",0,3],["PLACE",1,4],["PLACE",4,2],["PLACE",4,3],["PLACE",2,1],["PLACE",1,1],["PLACE",2,3],["PLACE",2,0],["PLACE",4,0],["PLACE",3,2],["PLACE",4,1],["PLACE",1,3],["PLACE",3,3],["PLACE",3,2],["PLACE",2,4],["PLACE",2,2],["PLACE",4,4],["PLACE",2,3],["PLACE",0,4],["PLACE",1,2]],"steps":[{"captures":[],"board":"1000000000000000000000000","result":null},{"captures":[],"board":"1000020000000000000000000","result":null},{"captures":[],"board":"1100020000000000000000000","result":null},{"captures":[],"board":"1120020000000000000000000","result":null},{"captures":[],"board":"1120120000000000000000000","result":null},{"captures":[],"board":"1120120000000002000000000","result":null},{"captures":[],"board":"1121120000000002000000000","result":null},{"captures":[],"board":"1121120002000002000000000","result":null},{"captures":[],"board":"1121120002000002000000100","result":null},{"captures":[],"board":"1121120002000002000000120","result":null},{"captures":[],"board":"1121120002010002000000120","result":null},{"captures":[],"board":"1121122002010002000000120","result":null},{"captures":[],"board":"1121122002010102000000120","result":null},{"captures":[],"board":"1121122002210102000000120","result":null},{"captures":[],"board":"1121122002210102000010120","result":null},{"captures":[],"board":"1121122002210102020010120","result":null},{"captures":[],"board":"1121122002210102020011120","result":null},{"captures":[[0,4],[2,3]],"board":"1121022022210002020011120","result":null},{"captures":[[3,2],[4,3]],"board":"1121022022210002001011100","result":null},{"captures":[],"board":"1121022022210002021011100","result":null},{"captures":[],"board":"1121022022210012021011100","result":null},{"captures":[],"board":"1121022022212012021011100","result":null},{"captures":[],"board":"1121022022212012021011101","result":null},{"captures":[],"board":"1121022022212212021011101","result":null},{"captures":[],"board":"1121122022212212021011101","result":null},{"captures":[],"board":"1121122222212212021011101","result":"winner: blue"}]},{"n":6,"actions":[["PLACE",5,2],["PLACE",4,3],["PLACE",5,1],["PLACE",4,1],["PLACE",2,3],["PLACE",4,0],["PLACE",1,0],["PLACE",3,4],["PLACE",4,2],["PLACE",2,0],["PLACE",4,4],["PLACE",2,2],["PLACE",4,5],["PLACE",2,1],["PLACE",1,3],["PLACE",2,4],["PLACE",5,5],["PLACE",3,2],["PLACE",1,4],["PLACE",0,2],["PLACE",1,5],["PLACE",3,3],["PLACE",2,3],["PLACE",0,4],["PLACE",3,0],["PLACE",0,1],["PLACE",0,3],["PLACE",5,0],["PLACE",3,1],["PLACE",1,1],["PLACE",2,2],["PLACE",3,5],["PLACE",0,0],["PLACE",2,1],["PLACE",0,5],["PLACE",2,5],["PLACE",5,3],["PLACE",3,2]],"steps":[{"captures":[],"board":"000000000000000000000000000000001000","result":null},{"captures":[],"board":"000000000000000000000000000200001000","result":null},{"captures":[],"board":"000000000000000000000000000200011000","result":null},{"captures":[],"board":"000000000000000000000000020200011000","result":null},{"captures":[],"board":"000000000000000100000000020200011000","result":null},{"captures":[],"board":"000000000000000100000000220200011000","result":null},{"captures":[],"board":"000000100000000100000000220200011000","result":null},{"captures":[],"board":"000000100000000100000020220200011000","result":null},{"captures":[],"board":"000000100000000100000020221200011000","result":null},{"captures":[],"board":"000000100000200100000020221200011000","result":null},{"captures":[],"board":"000000100000200100000020221210011000","result":null},{"captures":[],"board":"000000100000202100000020221210011000","result":null},{"captures":[],"board":"000000100000202100000020221211011000","result":null},{"captures":[],"board":"000000100000222100000020221211011000","result":null},{"captures":[],"board":"000000100100222100000020221211011000","result":null},{"captures":[],"board":"000000100100222120000020221211011000","result":null},{"captures":[],"board":"000000100100222120000020221211011001","result":null},{"captures":[],"board":"000000100100222120002020221211011001","result":null},{"captures":[],"board":"000000100110222120002020221211011001","result":null},{"captures":[],"board":"002000100110222120002020221211011001","result":null},{"captures":[],"board":"002000100111222120002020221211011001","result":null},{"captures":[[2,3],[4,2]],"board":"002000100111222020002220220211011001","result":null},{"captures":[],"board":"002000100111222120002220220211011001","result":null},{"captures":[],"board":"002020100111222120002220220211011001","result":null},{"captures":[],"board":"002020100111222120102220220211011001","result":null},{"captures":[],"board":"022020100111222120102220220211011001","result":null},{"captures":[],"board":"022120100111222120102220220211011001","result":null},{"captures":[],"board":"022120100111222120102220220211211001","result":null},{"captures":[[2,1],[2,2],[3,2],[4,0]],"board":"022120100111200120110220020211211001","result":null},{"captures":[],"board":"022120120111200120110220020211211001","result":null},{"captures":[],"board":"022120120111201120110220020211211001","result":null},{"captures":[],"board":"022120120111201120110222020211211001","result":null},{"captures":[],"board":"122120120111201120110222020211211001","result":null},{"captures":[],"board":"122120120111221120110222020211211001","result":null},{"captures":[],"board":"122121120111221120110222020211211001","result":null},{"captures":[],"board":"122121120111221122110222020211211001","result":null},{"captures":[],"board":"122121120111221122110222020211211101","result":null},{"captures":[[2,2],[3,1]],"board":"122121120111220122102222020211211101","result":"winner: blue"}]},{"n":7,"actions":[["PLACE",4,4],["STEAL"],["PLACE",4,5],["PLACE",4,6],["PLACE",1,5],["PLACE",0,4],["PLACE",2,4],["PLACE",2,2],["PLACE",6,6],["PLACE",0,3],["PLACE",5,5],["PLACE",0,5],["PLACE",4,3],["PLACE",3,4],["PLACE",0,6],["PLACE",3,6],["PLACE",6,4],["PLACE",2,6],["PLACE",1,3],["PLACE",2,3],["PLACE",6,3],["PLACE",1,4],["PLACE",5,0],["PLACE",1,3],["PLACE",6,5],["PLACE",4,2],["PLACE",5,4],["PLACE",3,3],["PLACE",3,2],["PLACE",3,3],["PLACE",5,2],["PLACE",4,0],["PLACE",6,1],["PLACE",5,1],["PLACE",1,2],["PLACE",1,6],["PLACE",0,6],["PLACE",2,4],["PLACE",0,2],["PLACE",0,0],["PLACE",4,1],["PLACE",5,3],["PLACE",5,6],["PLACE",1,1],["PLACE",1,5],["PLACE",1,6],["PLACE",4,2],["PLACE",6,0],["PLACE",4,0],["PLACE",5,4],["PLACE",1,0],["PLACE",3,1],["PLACE",0,1],["PLACE",5,5],["PLACE",3,5],["PLACE",0,5],["PLACE",4,3],["PLACE",0,6],["PLACE",1,1],["PLACE",2,1],["PLACE",2,5],["PLACE",4,5],["PLACE",4,4],["PLACE",1,2],["PLACE",3,4],["PLACE",2,0]],"steps":[{"captures":[],"board":"0000000000000000000000000000000010000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000020000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000021000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000021200000000000000","result":null},{"captures":[],"board":"0000000000001000000000000000000021200000000000000","result":null},{"captures":[],"board":"0000200000001000000000000000000021200000000000000","result":null},{"captures":[],"board":"0000200000001000001000000000000021200000000000000","result":null},{"captures":[],"board":"0000200000001000201000000000000021200000000000000","result":null},{"captures":[],"board":"0000200000001000201000000000000021200000000000001","result":null},{"captures":[],"board":"0002200000001000201000000000000021200000000000001","result":null},{"captures":[],"board":"0002200000001000201000000000000021200000100000001","result":null},{"captures":[],"board":"0002220000001000201000000000000021200000100000001","result":null},{"captures":[],"board":"0002220000001000201000000000000121200000100000001","result":null},{"captures":[],"board":"0002220000001000201000000200000121200000100000001","result":null},{"captures":[],"board":"0002221000001000201000000200000121200000100000001","result":null},{"captures":[],"board":"0002221000001000201000000202000121200000100000001","result":null},{"captures":[],"board":"0002221000001000201000000202000121200000100000101","result":null},{"captures":[],"board":"0002221000001000201020000202000121200000100000101","result":null},{"captures":[],"board":"0002221000101000201020000202000121200000100000101","result":null},{"captures":[],"board":"0002221000101000221020000202000121200000100000101","result":null},{"captures":[],"board":"0002221000101000221020000202000121200000100001101","result":null},{"captures":[[1,3],[2,4]],"board":"0002221000021000220020000202000121200000100001101","result":null},{"captures":[],"board":"0002221000021000220020000202000121210000100001101","result":null},{"captures":[],"board":"0002221000221000220020000202000121210000100001101","result":null},{"captures":[],"board":"0002221000221000220020000202000121210000100001111","result":null},{"captures":[],"board":"0002221000221000220020000202002121210000100001111","result":null},{"captures":[],"board":"0002221000221000220020000202002121210001100001111","result":null},{"captures":[],"board":"0002221000221000220020002202002121210001100001111","result":null},{"captures":[[3,3],[4,2]],"board":"0002221000221000220020010202000121210001100001111","result":null},{"captures":[],"board":"0002221000221000220020012202000121210001100001111","result":null},{"captures":[],"board":"0002221000221000220020012202000121210101100001111","result":null},{"captures":[],"board":"0002221000221000220020012202200121210101100001111","result":null},{"captures":[],"board":"0002221000221000220020012202200121210101100101111","result":null},{"captures":[],"board":"0002221000221000220020012202200121212101100101111","result":null},{"captures":[],"board":"0002221001221000220020012202200121212101100101111","result":null},{"captures":[[0,6],[1,5]],"board":"0002220001220200220020012202200121212101100101111","result":null},{"captures":[],"board":"0002221001220200220020012202200121212101100101111","result":null},{"captures":[],"board":"0002221001220200222020012202200121212101100101111","result":null},{"captures":[],"board":"0012221001220200222020012202200121212101100101111","result":null},{"captures":[],"board":"2012221001220200222020012202200121212101100101111","result":null},{"captures":[[4,0],[5,1]],"board":"2012221001220200222020012202010121210101100101111","result":null},{"captures":[[4,3],[5,4]],"board":"2012221001220200222020012202010021210120100101111","result":null},{"captures":[],"board":"2012221001220200222020012202010021210120110101111","result":null},{"captures":[[0,2],[1,2]],"board":"2002221020220200222020012202010021210120110101111","result":null},{"captures":[[0,5],[1,6]],"board":"2002201020221000222020012202010021210120110101111","result":null},{"captures":[],"board":"2002201020221200222020012202010021210120110101111","result":null},{"captures":[],"board":"2002201020221200222020012202011021210120110101111","result":null},{"captures":[],"board":"2002201020221200222020012202011021210120112101111","result":null},{"captures":[],"board":"2002201020221200222020012202111021210120112101111","result":null},{"captures":[[4,5],[5,5]],"board":"2002201020221200222020012202111020210122012101111","result":null},{"captures":[],"board":"2002201120221200222020012202111020210122012101111","result":null},{"captures":[],"board":"2002201120221200222020212202111020210122012101111","result":null},{"captures":[[0,0],[1,1]],"board":"0102201100221200222020212202111020210122012101111","result":null},{"captures":[],"board":"0102201100221200222020212202111020210122212101111","result":null},{"captures":[],"board":"0102201100221200222020212212111020210122212101111","result":null},{"captures":[[0,6],[1,5]],"board":"0102220100220200222020212212111020210122212101111","result":null},{"captures":[[3,4],[4,4]],"board":"0102220100220200222020212012111100210122212101111","result":null},{"captures":[],"board":"0102222100220200222020212012111100210122212101111","result":null},{"captures":[],"board":"0102222110220200222020212012111100210122212101111","result":null},{"captures":[],"board":"0102222110220202222020212012111100210122212101111","result":null},{"captures":[],"board":"0102222110220202222120212012111100210122212101111","result":null},{"captures":[],"board":"0102222110220202222120212012111102210122212101111","result":null},{"captures":[[5,3],[5,4]],"board":"0102222110220202222120212012111112210100212101111","result":null},{"captures":[],"board":"0102222112220202222120212012111112210100212101111","result":null},{"captures":[],"board":"0102222112220202222120212112111112210100212101111","result":null},{"captures":[],"board":"0102222112220222222120212112111112210100212101111","result":"winner: blue"}]},{"n":8,"actions":[["PLACE",7,2],["PLACE",6,2],["PLACE",5,2],["PLACE",6,1],["PLACE",1,1],["PLACE",7,0],["PLACE",7,7],["PLACE",6,3],["PLACE",0,2],["PLACE",2,1],["PLACE",2,2],["PLACE",5,0],["PLACE",7,1],["PLACE",6,4],["PLACE",5,1],["PLACE",4,3],["PLACE",6,0],["PLACE",3,1],["PLACE",7,6],["PLACE",4,1],["PLACE",0,3],["PLACE",5,5],["PLACE",6,7],["PLACE",3,6],["PLACE",6,6],["PLACE",1,2],["PLACE",5,7],["PLACE",4,5],["PLACE",7,3],["PLACE",6,5],["PLACE",3,0],["PLACE",1,0],["PLACE",0,0],["PLACE",1,3],["PLACE",2,0],["PLACE",4,6],["PLACE",2,3],["PLACE",6,2],["PLACE",7,4],["PLACE",2,4],["PLACE",7,5],["PLACE",6,1],["PLACE",1,7],["PLACE",0,1],["PLACE",7,1],["PLACE",1,4],["PLACE",2,7],["PLACE",0,7],["PLACE",1,1],["PLACE",4,4],["PLACE",2,6],["PLACE",6,0],["PLACE",5,2],["PLACE",2,5],["PLACE",4,7],["PLACE",0,5],["PLACE",1,5],["PLACE",1,0],["PLACE",2,4],["PLACE",5,3],["PLACE",3,4],["PLACE",3,7],["PLACE",0,1],["PLACE",1,4],["PLACE",2,1],["PLACE",3,3],["PLACE",4,0],["PLACE",6,1],["PLACE",6,2],["PLACE",0,4],["PLACE",5,1],["PLACE",5,6],["PLACE",0,6],["PLACE",2,2],["PLACE",1,2],["PLACE",5,3],["PLACE",1,6],["PLACE",1,3],["PLACE",4,2],["PLACE",5,4],["PLACE",3,2],["PLACE",3,5],["PLACE",2,2]],"steps":[{"captures":[],"board":"0000000000000000000000000000000000000000000000000000000000100000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000020000000100000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000001000000020000000100000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000001000000220000000100000","result":null},{"captures":[],"board":"0000000001000000000000000000000000000000001000000220000000100000","result":null},{"captures":[],"board":"0000000001000000000000000000000000000000001000000220000020100000","result":null},{"captures":[],"board":"0000000001000000000000000000000000000000001000000220000020100001","result":null},{"captures":[],"board":"0000000001000000000000000000000000000000001000000222000020100001","result":null},{"captures":[],"board":"0010000001000000000000000000000000000000001000000222000020100001","result":null},{"captures":[],"board":"0010000001000000020000000000000000000000001000000222000020100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000000000001000000222000020100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000000000201000000222000020100001","result":null},{"captures":[[6,1],[6,2]],"board":"0010000001000000021000000000000000000000201000000002000021100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000000000201000000002200021100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000000000211000000002200021100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000020000211000000002200021100001","result":null},{"captures":[],"board":"0010000001000000021000000000000000020000211000001002200021100001","result":null},{"captures":[],"board":"0010000001000000021000000200000000020000211000001002200021100001","result":null},{"captures":[],"board":"0010000001000000021000000200000000020000211000001002200021100011","result":null},{"captures":[],"board":"0010000001000000021000000200000002020000211000001002200021100011","result":null},{"captures":[],"board":"0011000001000000021000000200000002020000211000001002200021100011","result":null},{"captures":[],"board":"0011000001000000021000000200000002020000211002001002200021100011","result":null},{"captures":[],"board":"0011000001000000021000000200000002020000211002001002200121100011","result":null},{"captures":[],"board":"0011000001000000021000000200002002020000211002001002200121100011","result":null},{"captures":[],"board":"0011000001000000021000000200002002020000211002001002201121100011","result":null},{"captures":[[1,1],[2,2]],"board":"0011000000200000020000000200002002020000211002001002201121100011","result":null},{"captures":[],"board":"0011000000200000020000000200002002020000211002011002201121100011","result":null},{"captures":[],"board":"0011000000200000020000000200002002020200211002011002201121100011","result":null},{"captures":[],"board":"0011000000200000020000000200002002020200211002011002201121110011","result":null},{"captures":[],"board":"0011000000200000020000000200002002020200211002011002221121110011","result":null},{"captures":[],"board":"0011000000200000020000001200002002020200211002011002221121110011","result":null},{"captures":[],"board":"0011000020200000020000001200002002020200211002011002221121110011","result":null},{"captures":[],"board":"1011000020200000020000001200002002020200211002011002221121110011","result":null},{"captures":[],"board":"1011000020220000020000001200002002020200211002011002221121110011","result":null},{"captures":[],"board":"1011000020220000120000001200002002020200211002011002221121110011","result":null},{"captures":[],"board":"1011000020220000120000001200002002020220211002011002221121110011","result":null},{"captures":[],"board":"1011000020220000120100001200002002020220211002011002221121110011","result":null},{"captures":[],"board":"1011000020220000120100001200002002020220211002011022221121110011","result":null},{"captures":[],"board":"1011000020220000120100001200002002020220211002011022221121111011","result":null},{"captures":[],"board":"1011000020220000120120001200002002020220211002011022221121111011","result":null},{"captures":[],"board":"1011000020220000120120001200002002020220211002011022221121111111","result":null},{"captures":[[5,1],[5,2],[6,0],[7,1]],"board":"1011000020220000120120001200002002020220200002010222221120111111","result":null},{"captures":[],"board":"1011000020220001120120001200002002020220200002010222221120111111","result":null},{"captures":[],"board":"1211000020220001120120001200002002020220200002010222221120111111","result":null},{"captures":[],"board":"1211000020220001120120001200002002020220200002010222221121111111","result":null},{"captures":[],"board":"1211000020222001120120001200002002020220200002010222221121111111","result":null},{"captures":[],"board":"1211000020222001120120011200002002020220200002010222221121111111","result":null},{"captures":[],"board":"1211000220222001120120011200002002020220200002010222221121111111","result":null},{"captures":[[0,1],[1,0],[1,2],[2,1]],"board":"1011000201022001100120011200002002020220200002010222221121111111","result":null},{"captures":[],"board":"1011000201022001100120011200002002022220200002010222221121111111","result":null},{"captures":[],"board":"1011000201022001100120111200002002022220200002010222221121111111","result":null},{"captures":[],"board":"1011000201022001100120111200002002022220200002012222221121111111","result":null},{"captures":[[6,1],[6,2]],"board":"1011000201022001100120111200002002022220201002012002221121111111","result":null},{"captures":[],"board":"1011000201022001100122111200002002022220201002012002221121111111","result":null},{"captures":[],"board":"1011000201022001100122111200002002022221201002012002221121111111","result":null},{"captures":[],"board":"1011020201022001100122111200002002022221201002012002221121111111","result":null},{"captures":[[1,4],[2,4]],"board":"1011020201020101100102111200002002022221201002012002221121111111","result":null},{"captures":[],"board":"1011020221020101100102111200002002022221201002012002221121111111","result":null},{"captures":[],"board":"1011020221020101100112111200002002022221201002012002221121111111","result":null},{"captures":[],"board":"1011020221020101100112111200002002022221201202012002221121111111","result":null},{"captures":[],"board":"1011020221020101100112111200102002022221201202012002221121111111","result":null},{"captures":[],"board":"1011020221020101100112111200102202022221201202012002221121111111","result":null},{"captures":[],"board":"1111020221020101100112111200102202022221201202012002221121111111","result":null},{"captures":[[1,5],[2,4]],"board":"1111020221022001100102111200102202022221201202012002221121111111","result":null},{"captures":[],"board":"1111020221022001110102111200102202022221201202012002221121111111","result":null},{"captures":[],"board":"1111020221022001110102111202102202022221201202012002221121111111","result":null},{"captures":[],"board":"1111020221022001110102111202102212022221201202012002221121111111","result":null},{"captures":[],"board":"1111020221022001110102111202102212022221201202012202221121111111","result":null},{"captures":[[5,3],[6,1]],"board":"1111020221022001110102111202102212022221201002012012221121111111","result":null},{"captures":[],"board":"1111220221022001110102111202102212022221201002012012221121111111","result":null},{"captures":[[4,1],[5,0]],"board":"1111220221022001110102111202102210022221011002012012221121111111","result":null},{"captures":[],"board":"1111220221022001110102111202102210022221011002212012221121111111","result":null},{"captures":[],"board":"1111221221022001110102111202102210022221011002212012221121111111","result":null},{"captures":[],"board":"1111221221022001112102111202102210022221011002212012221121111111","result":null},{"captures":[[1,3],[2,2]],"board":"1111221221102001110102111202102210022221011002212012221121111111","result":null},{"captures":[],"board":"1111221221102001110102111202102210022221011202212012221121111111","result":null},{"captures":[],"board":"1111221221102011110102111202102210022221011202212012221121111111","result":null},{"captures":[],"board":"1111221221122011110102111202102210022221011202212012221121111111","result":null},{"captures":[[3,3],[4,3]],"board":"1111221221122011110102111200102210102221011202212012221121111111","result":null},{"captures":[],"board":"1111221221122011110102111200102210102221011222212012221121111111","result":null},{"captures":[],"board":"1111221221122011110102111210102210102221011222212012221121111111","result":null},{"captures":[[2,6],[3,4]],"board":"1111221221122011110102011210022210102221011222212012221121111111","result":null},{"captures":[],"board":"1111221221122011111102011210022210102221011222212012221121111111","result":"winner: red"}]},{"n":3,"actions":[["PLACE",2,1],["STEAL"],["PLACE",2,2],["PLACE",2,1],["PLACE",1,1],["PLACE",2,0],["PLACE",2,1],["PLACE",0,2],["PLACE",0,1]],"steps":[{"captures":[],"board":"000000010","result":null},{"captures":[],"board":"000002000","result":null},{"captures":[],"board":"000002001","result":null},{"captures":[],"board":"000002021","result":null},{"captures":[[1,2],[2,1]],"board":"000010001","result":null},{"captures":[],"board":"000010201","result":null},{"captures":[],"board":"000010211","result":null},{"captures":[],"board":"002010211","result":null},{"captures":[],"board":"012010211","result":"winner: red"}]},{"n":4,"actions":[["PLACE",0,3],["PLACE",1,2],["PLACE",1,1],["PLACE",0,1],["PLACE",1,0],["PLACE",3,3],["PLACE",2,0],["PLACE",0,2],["PLACE",0,0],["PLACE",1,3],["PLACE",0,3],["PLACE",2,2],["PLACE",3,0]],"steps":[{"captures":[],"board":"0001000000000000","result":null},{"captures":[],"board":"0001002000000000","result":null},{"captures":[],"board":"0001012000000000","result":null},{"captures":[],"board":"0201012000000000","result":null},{"captures":[],"board":"0201112000000000","result":null},{"captures":[],"board":"0201112000000002","result":null},{"captures":[],"board":"0201112010000002","result":null},{"captures":[[0,3],[1,1]],"board":"0220102010000002","result":null},{"captures":[],"board":"1220102010000002","result":null},{"captures":[],"board":"1220102210000002","result":null},{"captures":[],"board":"1221102210000002","result":null},{"captures":[],"board":"1221102210200002","result":null},{"captures":[],"board":"1221102210201002","result":"winner: red"}]},{"n":5,"actions":[["PLACE",2,3],["STEAL"],["PLACE",2,3],["PLACE",1,2],["PLACE",2,2],["PLACE",3,3],["PLACE",3,4],["PLACE",4,3],["PLACE",4,4],["PLACE",1,4],["PLACE",2,1],["PLACE",4,1],["PLACE",2,0],["PLACE",0,3],["PLACE",0,2],["PLACE",0,4],["PLACE",4,0],["PLACE",0,1],["PLACE",2,4],["PLACE",4,2],["PLACE",3,1],["PLACE",3,0],["PLACE",3,1],["PLACE",0,0],["PLACE",1,3],["PLACE",1,2],["PLACE",1,0],["PLACE",4,0],["PLACE",1,1]],"steps":[{"captures":[],"board":"0000000000000100000000000","result":null},{"captures":[],"board":"0000000000000000020000000","result":null},{"captures":[],"board":"0000000000000100020000000","result":null},{"captures":[],"board":"0000000200000100020000000","result":null},{"captures":[],"board":"0000000200001100020000000","result":null},{"captures":[],"board":"0000000200001100022000000","result":null},{"captures":[],"board":"0000000200001100022100000","result":null},{"captures":[],"board":"0000000200001100022100020","result":null},{"captures":[],"board":"0000000200001100022100021","result":null},{"captures":[],"board":"0000000202001100022100021","result":null},{"captures":[],"board":"0000000202011100022100021","result":null},{"captures":[],"board":"0000000202011100022102021","result":null},{"captures":[],"board":"0000000202111100022102021","result":null},{"captures":[],"board":"0002000202111100022102021","result":null},{"captures":[],"board":"0012000202111100022102021","result":null},{"captures":[],"board":"0012200202111100022102021","result":null},{"captures":[],"board":"0012200202111100022112021","result":null},{"captures":[],"board":"0212200202111100022112021","result":null},{"captures":[[1,4],[3,3]],"board":"0212200200111110020112021","result":null},{"captures":[],"board":"0212200200111110020112221","result":null},{"captures":[],"board":"0212200200111110120112221","result":null},{"captures":[[3,1],[4,0]],"board":"0212200200111112020102221","result":null},{"captures":[],"board":"0212200200111112120102221","result":null},{"captures":[],"board":"2212200200111112120102221","result":null},{"captures":[[0,3],[1,2]],"board":"2210200010111112120102221","result":null},{"captures":[],"board":"2210200210111112120102221","result":null},{"captures":[],"board":"2210210210111112120102221","result":null},{"captures":[],"board":"2210210210111112120122221","result":null},{"captures":[[0,1],[1,2]],"board":"2010211010111112120122221","result":"winner: red"}]},{"n":6,"actions":[["PLACE",2,1],["PLACE",2,0],["PLACE",1,0],["PLACE",0,1],["PLACE",1,2],["PLACE",0,0],["PLACE",1,3],["PLACE",0,4],["PLACE",1,4],["PLACE",2,3],["PLACE",1,5],["PLACE",5,1],["PLACE",4,2],["PLACE",3,3],["PLACE",0,5],["PLACE",1,1],["PLACE",5,2],["PLACE",2,2],["PLACE",2,5],["PLACE",1,3],["PLACE",3,5],["PLACE",1,0],["PLACE",0,3],["PLACE",3,2],["PLACE",5,3],["PLACE",4,4],["PLACE",0,2],["PLACE",2,4],["PLACE",4,5],["PLACE",1,4],["PLACE",5,5]],"steps":[{"captures":[],"board":"000000000000010000000000000000000000","result":null},{"captures":[],"board":"000000000000210000000000000000000000","result":null},{"captures":[],"board":"000000100000210000000000000000000000","result":null},{"captures":[],"board":"020000100000210000000000000000000000","result":null},{"captures":[],"board":"020000101000210000000000000000000000","result":null},{"captures":[],"board":"220000101000210000000000000000000000","result":null},{"captures":[],"board":"220000101100210000000000000000000000","result":null},{"captures":[],"board":"220020101100210000000000000000000000","result":null},{"captures":[],"board":"220020101110210000000000000000000000","result":null},{"captures":[[1,3],[1,4]],"board":"220020101000210200000000000000000000","result":null},{"captures":[],"board":"220020101001210200000000000000000000","result":null},{"captures":[],"board":"220020101001210200000000000000020000","result":null},{"captures":[],"board":"220020101001210200000000001000020000","result":null},{"captures":[],"board":"220020101001210200000200001000020000","result":null},{"captures":[],"board":"220021101001210200000200001000020000","result":null},{"captures":[[1,0],[2,1]],"board":"220021021001200200000200001000020000","result":null},{"captures":[],"board":"220021021001200200000200001000021000","result":null},{"captures":[],"board":"220021021001202200000200001000021000","result":null},{"captures":[],"board":"220021021001202201000200001000021000","result":null},{"captures":[],"board":"220021021201202201000200001000021000","result":null},{"captures":[],"board":"220021021201202201000201001000021000","result":null},{"captures":[],"board":"220021221201202201000201001000021000","result":null},{"captures":[],"board":"220121221201202201000201001000021000","result":null},{"captures":[],"board":"220121221201202201002201001000021000","result":null},{"captures":[],"board":"220121221201202201002201001000021100","result":null},{"captures":[],"board":"220121221201202201002201001020021100","result":null},{"captures":[],"board":"221121221201202201002201001020021100","result":null},{"captures":[],"board":"221121221201202221002201001020021100","result":null},{"captures":[],"board":"221121221201202221002201001021021100","result":null},{"captures":[],"board":"221121221221202221002201001021021100","result":null},{"captures":[],"board":"221121221221202221002201001021021101","result":"winner: red"}]},{"n":7,"actions":[["PLACE",3,2],["PLACE",3,1],["PLACE",2,2],["PLACE",4,0],["PLACE",2,3],["PLACE",1,2],["PLACE",6,6],["PLACE",2,4],["PLACE",1,3],["PLACE",4,1],["PLACE",1,5],["PLACE",5,6],["PLACE",0,4],["PLACE",1,1],["PLACE",4,5],["PLACE",3,4],["PLACE",3,0],["PLACE",5,1],["PLACE",2,0],["PLACE",5,4],["PLACE",5,3],["PLACE",4,3],["PLACE",5,5],["PLACE",2,5],["PLACE",0,5],["PLACE",6,2],["PLACE",6,4],["PLACE",6,5],["PLACE",6,6],["PLACE",0,1],["PLACE",1,6],["PLACE",0,0],["PLACE",6,3],["PLACE",3,3],["PLACE",5,4],["PLACE",6,2],["PLACE",6,0],["PLACE",0,3],["PLACE",2,6],["PLACE",6,4],["PLACE",5,5],["PLACE",4,4],["PLACE",4,6],["PLACE",3,5],["PLACE",1,0],["PLACE",0,6],["PLACE",4,2],["PLACE",4,1],["PLACE",5,6],["PLACE",0,2],["PLACE",3,3],["PLACE",5,2],["PLACE",2,1],["PLACE",6,5],["PLACE",1,5],["PLACE",4,2],["PLACE",1,4],["PLACE",5,3],["PLACE",3,1],["PLACE",1,2],["PLACE",3,6],["PLACE",5,0],["PLACE",6,1],["PLACE",5,4],["PLACE",6,3],["PLACE",6,4],["PLACE",5,4],["PLACE",5,3],["PLACE",6,4],["PLACE",1,6]],"steps":[{"captures":[],"board":"0000000000000000000000010000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000210000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000100000210000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000100000210000200000000000000000000","result":null},{"captures":[],"board":"0000000000000000110000210000200000000000000000000","result":null},{"captures":[],"board":"0000000002000000110000210000200000000000000000000","result":null},{"captures":[],"board":"0000000002000000110000210000200000000000000000001","result":null},{"captures":[],"board":"0000000002000000112000210000200000000000000000001","result":null},{"captures":[],"board":"0000000002100000112000210000200000000000000000001","result":null},{"captures":[],"board":"0000000002100000112000210000220000000000000000001","result":null},{"captures":[],"board":"0000000002101000112000210000220000000000000000001","result":null},{"captures":[],"board":"0000000002101000112000210000220000000000020000001","result":null},{"captures":[],"board":"0000100002101000112000210000220000000000020000001","result":null},{"captures":[],"board":"0000100022101000112000210000220000000000020000001","result":null},{"captures":[],"board":"0000100022101000112000210000220001000000020000001","result":null},{"captures":[],"board":"0000100022101000112000210200220001000000020000001","result":null},{"captures":[],"board":"0000100022101000112001210200220001000000020000001","result":null},{"captures":[],"board":"0000100022101000112001210200220001002000020000001","result":null},{"captures":[],"board":"0000100022101010112001210200220001002000020000001","result":null},{"captures":[],"board":"0000100022101010112001210200220001002002020000001","result":null},{"captures":[],"board":"0000100022101010112001210200220001002012020000001","result":null},{"captures":[],"board":"0000100022101010112001210200220201002012020000001","result":null},{"captures":[],"board":"0000100022101010112001210200220201002012120000001","result":null},{"captures":[],"board":"0000100022101010112201210200220201002012120000001","result":null},{"captures":[],"board":"0000110022101010112201210200220201002012120000001","result":null},{"captures":[],"board":"0000110022101010112201210200220201002012120020001","result":null},{"captures":[],"board":"0000110022101010112201210200220201002012120020101","result":null},{"captures":[[5,5],[6,4],[6,6]],"board":"0000110022101010112201210200220201002012020020020","result":null},{"captures":[],"board":"0000110022101010112201210200220201002012020020021","result":null},{"captures":[],"board":"0200110022101010112201210200220201002012020020021","result":null},{"captures":[],"board":"0200110022101110112201210200220201002012020020021","result":null},{"captures":[],"board":"2200110022101110112201210200220201002012020020021","result":null},{"captures":[[5,4],[6,2]],"board":"2200110022101110112201210200220201002010020001021","result":null},{"captures":[],"board":"2200110022101110112201212200220201002010020001021","result":null},{"captures":[],"board":"2200110022101110112201212200220201002011020001021","result":null},{"captures":[],"board":"2200110022101110112201212200220201002011020021021","result":null},{"captures":[],"board":"2200110022101110112201212200220201002011021021021","result":null},{"captures":[],"board":"2202110022101110112201212200220201002011021021021","result":null},{"captures":[],"board":"2202110022101110112211212200220201002011021021021","result":null},{"captures":[],"board":"2202110022101110112211212200220201002011021021221","result":null},{"captures":[[5,6],[6,5]],"board":"2202110022101110112211212200220201002011101021201","result":null},{"captures":[],"board":"2202110022101110112211212200220221002011101021201","result":null},{"captures":[],"board":"2202110022101110112211212200220221102011101021201","result":null},{"captures":[],"board":"2202110022101110112211212220220221102011101021201","result":null},{"captures":[],"board":"2202110122101110112211212220220221102011101021201","result":null},{"captures":[[1,5],[1,6]],"board":"2202112122100010112211212220220221102011101021201","result":null},{"captures":[[3,3],[4,1]],"board":"2202112122100010112211210220201221102011101021201","result":null},{"captures":[],"board":"2202112122100010112211210220221221102011101021201","result":null},{"captures":[],"board":"2202112122100010112211210220221221102011111021201","result":null},{"captures":[],"board":"2222112122100010112211210220221221102011111021201","result":null},{"captures":[],"board":"2222112122100010112211211220221221102011111021201","result":null},{"captures":[[4,2],[5,3]],"board":"2222112122100010112211211220220221102201111021201","result":null},{"captures":[[1,2],[3,1]],"board":"2222112120100011112211011220220221102201111021201","result":null},{"captures":[],"board":"2222112120100011112211011220220221102201111021221","result":null},{"captures":[],"board":"2222112120101011112211011220220221102201111021221","result":null},{"captures":[],"board":"2222112120101011112211011220222221102201111021221","result":null},{"captures":[],"board":"2222112120111011112211011220222221102201111021221","result":null},{"captures":[[5,4],[6,3]],"board":"2222112120111011112211011220222221102220111020221","result":null},{"captures":[],"board":"2222112120111011112211111220222221102220111020221","result":null},{"captures":[],"board":"2222112122111011112211111220222221102220111020221","result":null},{"captures":[],"board":"2222112122111011112211111221222221102220111020221","result":null},{"captures":[],"board":"2222112122111011112211111221222221122220111020221","result":null},{"captures":[],"board":"2222112122111011112211111221222221122220111120221","result":null},{"captures":[],"board":"2222112122111011112211111221222221122222111120221","result":null},{"captures":[[5,4],[6,4]],"board":"2222112122111011112211111221222221122220111121021","result":null},{"captures":[],"board":"2222112122111011112211111221222221122220111121221","result":null},{"captures":[[5,3],[6,4]],"board":"2222112122111011112211111221222221122201111121021","result":null},{"captures":[],"board":"2222112122111011112211111221222221122221111121021","result":null},{"captures":[],"board":"2222112122111011112211111221222221122221111121121","result":null},{"captures":[[1,5],[2,6]],"board":"2222112122110211112201111221222221122221111121121","result":"winner: blue"}]},{"n":8,"actions":[["PLACE",5,5],["STEAL"],["PLACE",6,5],["PLACE",4,6],["PLACE",5,6],["PLACE",4,0],["PLACE",1,6],["PLACE",4,1],["PLACE",6,7],["PLACE",7,4],["PLACE",4,7],["PLACE",5,0],["PLACE",3,1],["PLACE",6,4],["PLACE",2,6],["PLACE",6,3],["PLACE",3,6],["PLACE",0,7],["PLACE",2,7],["PLACE",6,6],["PLACE",7,6],["PLACE",0,6],["PLACE",2,5],["PLACE",5,7],["PLACE",4,3],["PLACE",3,2],["PLACE",5,6],["PLACE",4,4],["PLACE",1,5],["PLACE",5,7],["PLACE",7,7],["PLACE",3,0],["PLACE",0,3],["PLACE",1,7],["PLACE",7,3],["PLACE",6,6],["PLACE",6,7],["PLACE",3,7],["PLACE",6,2],["PLACE",1,2],["PLACE",7,2],["PLACE",6,5],["PLACE",3,4],["PLACE",5,2],["PLACE",6,1],["PLACE",7,5],["PLACE",0,4],["PLACE",7,1],["PLACE",7,2],["PLACE",5,3],["PLACE",7,0],["PLACE",5,4],["PLACE",4,6],["PLACE",1,1],["PLACE",0,1],["PLACE",3,3],["PLACE",2,1],["PLACE",2,0],["PLACE",3,4],["PLACE",4,3]],"steps":[{"captures":[],"board":"0000000000000000000000000000000000000000000001000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000002000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000002000000010000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000020000002000000010000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000020000002100000010000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000020000020000002100000010000000000","result":null},{"captures":[],"board":"0000000000000010000000000000000020000020000002100000010000000000","result":null},{"captures":[],"board":"0000000000000010000000000000000022000020000002100000010000000000","result":null},{"captures":[],"board":"0000000000000010000000000000000022000020000002100000010100000000","result":null},{"captures":[],"board":"0000000000000010000000000000000022000020000002100000010100002000","result":null},{"captures":[],"board":"0000000000000010000000000000000022000021000002100000010100002000","result":null},{"captures":[],"board":"0000000000000010000000000000000022000021200002100000010100002000","result":null},{"captures":[],"board":"0000000000000010000000000100000022000021200002100000010100002000","result":null},{"captures":[],"board":"0000000000000010000000000100000022000021200002100000210100002000","result":null},{"captures":[],"board":"0000000000000010000000100100000022000021200002100000210100002000","result":null},{"captures":[],"board":"0000000000000010000000100100000022000021200002100002210100002000","result":null},{"captures":[],"board":"0000000000000010000000100100001022000021200002100002210100002000","result":null},{"captures":[],"board":"0000000200000010000000100100001022000021200002100002210100002000","result":null},{"captures":[],"board":"0000000200000010000000110100001022000021200002100002210100002000","result":null},{"captures":[[5,6],[6,5]],"board":"0000000200000010000000110100001022000021200002000002202100002000","result":null},{"captures":[],"board":"0000000200000010000000110100001022000021200002000002202100002010","result":null},{"captures":[],"board":"0000002200000010000000110100001022000021200002000002202100002010","result":null},{"captures":[],"board":"0000002200000010000001110100001022000021200002000002202100002010","result":null},{"captures":[],"board":"0000002200000010000001110100001022000021200002020002202100002010","result":null},{"captures":[],"board":"0000002200000010000001110100001022010021200002020002202100002010","result":null},{"captures":[],"board":"0000002200000010000001110120001022010021200002020002202100002010","result":null},{"captures":[[4,6],[5,7],[6,6]],"board":"0000002200000010000001110120001022010001200002100002200100002010","result":null},{"captures":[],"board":"0000002200000010000001110120001022012001200002100002200100002010","result":null},{"captures":[],"board":"0000002200000110000001110120001022012001200002100002200100002010","result":null},{"captures":[],"board":"0000002200000110000001110120001022012001200002120002200100002010","result":null},{"captures":[],"board":"0000002200000110000001110120001022012001200002120002200100002011","result":null},{"captures":[],"board":"0000002200000110000001112120001022012001200002120002200100002011","result":null},{"captures":[],"board":"0001002200000110000001112120001022012001200002120002200100002011","result":null},{"captures":[],"board":"0001002200000112000001112120001022012001200002120002200100002011","result":null},{"captures":[],"board":"0001002200000112000001112120001022012001200002120002200100012011","result":null},{"captures":[[5,6],[6,7]],"board":"0001002200000112000001112120001022012001200002020002202000012011","result":null},{"captures":[],"board":"0001002200000112000001112120001022012001200002020002202100012011","result":null},{"captures":[],"board":"0001002200000112000001112120001222012001200002020002202100012011","result":null},{"captures":[],"board":"0001002200000112000001112120001222012001200002020012202100012011","result":null},{"captures":[],"board":"0001002200200112000001112120001222012001200002020012202100012011","result":null},{"captures":[],"board":"0001002200200112000001112120001222012001200002020012202100112011","result":null},{"captures":[],"board":"0001002200200112000001112120001222012001200002020012222100112011","result":null},{"captures":[],"board":"0001002200200112000001112120101222012001200002020012222100112011","result":null},{"captures":[],"board":"0001002200200112000001112120101222012001202002020012222100112011","result":null},{"captures":[],"board":"0001002200200112000001112120101222012001202002020112222100112011","result":null},{"captures":[],"board":"0001002200200112000001112120101222012001202002020112222100112211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012001202002020112222100112211","result":null},{"captures":[[6,1],[6,2],[7,2]],"board":"0001102200200112000001112120101222012001202002020002222102012211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012001202002020002222102112211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012001202202020002222102112211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012001202202020002222112112211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012001202222020002222112112211","result":null},{"captures":[],"board":"0001102200200112000001112120101222012011202222020002222112112211","result":null},{"captures":[],"board":"0001102202200112000001112120101222012011202222020002222112112211","result":null},{"captures":[],"board":"0101102202200112000001112120101222012011202222020002222112112211","result":null},{"captures":[[3,4],[4,3]],"board":"0101102202200112000001112122001222002011202222020002222112112211","result":null},{"captures":[],"board":"0101102202200112010001112122001222002011202222020002222112112211","result":null},{"captures":[],"board":"0101102202200112210001112122001222002011202222020002222112112211","result":null},{"captures":[],"board":"0101102202200112210001112122101222002011202222020002222112112211","result":null},{"captures":[],"board":"0101102202200112210001112122101222022011202222020002222112112211","result":"winner: blue"}]},{"n":3,"actions":[["PLACE",0,2],["PLACE",1,1],["PLACE",2,1],["PLACE",0,1],["PLACE",1,0],["PLACE",0,1],["PLACE",2,2],["PLACE",0,0],["PLACE",2,0],["PLACE",1,1],["PLACE",0,2],["PLACE",1,2]],"steps":[{"captures":[],"board":"001000000","result":null},{"captures":[],"board":"001020000","result":null},{"captures":[],"board":"001020010","result":null},{"captures":[],"board":"021020010","result":null},{"captures":[[0,1],[1,1]],"board":"001100010","result":null},{"captures":[],"board":"021100010","result":null},{"captures":[],"board":"021100011","result":null},{"captures":[],"board":"221100011","result":null},{"captures":[],"board":"221100111","result":null},{"captures":[[0,2],[1,0]],"board":"220020111","result":null},{"captures":[],"board":"221020111","result":null},{"captures":[[0,2],[2,1]],"board":"220022101","result":"winner: blue"}]},{"n":4,"actions":[["PLACE",2,2],["PLACE",0,1],["PLACE",1,3],["PLACE",3,0],["PLACE",1,0],["PLACE",0,2],["PLACE",2,0],["PLACE",3,2],["PLACE",2,3],["PLACE",1,1],["PLACE",0,0],["PLACE",1,2],["PLACE",0,3],["PLACE",3,3],["PLACE",3,1]],"steps":[{"captures":[],"board":"0000000000100000","result":null},{"captures":[],"board":"0200000000100000","result":null},{"captures":[],"board":"0200000100100000","result":null},{"captures":[],"board":"0200000100102000","result":null},{"captures":[],"board":"0200100100102000","result":null},{"captures":[],"board":"0220100100102000","result":null},{"captures":[],"board":"0220100110102000","result":null},{"captures":[],"board":"0220100110102020","result":null},{"captures":[],"board":"0220100110112020","result":null},{"captures":[],"board":"0220120110112020","result":null},{"captures":[],"board":"1220120110112020","result":null},{"captures":[],"board":"1220122110112020","result":null},{"captures":[],"board":"1221122110112020","result":null},{"captures":[],"board":"1221122110112022","result":null},{"captures":[],"board":"1221122110112122","result":"winner: red"}]},{"n":5,"actions":[["PLACE",4,2],["PLACE",4,3],["PLACE",3,2],["PLACE",3,3],["PLACE",3,1],["PLACE",2,4],["PLACE",4,1],["PLACE",4,4],["PLACE",3,4],["PLACE",0,4],["PLACE",2,2],["PLACE",4,0],["PLACE",2,3],["PLACE",3,0],["PLACE",1,4],["PLACE",3,3],["PLACE",3,4],["PLACE",0,3],["PLACE",0,2],["PLACE",2,3],["PLACE",0,1],["PLACE",1,0],["PLACE",0,0],["PLACE",2,1],["PLACE",1,2]],"steps":[{"captures":[],"board":"0000000000000000000000100","result":null},{"captures":[],"board":"0000000000000000000000120","result":null},{"captures":[],"board":"0000000000000000010000120","result":null},{"captures":[],"board":"0000000000000000012000120","result":null},{"captures":[],"board":"0000000000000000112000120","result":null},{"captures":[],"board":"0000000000000020112000120","result":null},{"captures":[],"board":"0000000000000020112001120","result":null},{"captures":[],"board":"0000000000000020112001122","result":null},{"captures":[[3,3],[4,3]],"board":"0000000000000020110101102","result":null},{"captures":[],"board":"0000200000000020110101102","result":null},{"captures":[],"board":"0000200000001020110101102","result":null},{"captures":[],"board":"0000200000001020110121102","result":null},{"captures":[],"board":"0000200000001120110121102","result":null},{"captures":[],"board":"0000200000001122110121102","result":null},{"captures":[],"board":"0000200001001122110121102","result":null},{"captures":[[2,3],[3,4]],"board":"0000200001001022112021102","result":null},{"captures":[],"board":"0000200001001022112121102","result":null},{"captures":[],"board":"0002200001001022112121102","result":null},{"captures":[],"board":"0012200001001022112121102","result":null},{"captures":[],"board":"0012200001001222112121102","result":null},{"captures":[],"board":"0112200001001222112121102","result":null},{"captures":[],"board":"0112220001001222112121102","result":null},{"captures":[],"board":"1112220001001222112121102","result":null},{"captures":[],"board":"1112220001021222112121102","result":null},{"captures":[],"board":"1112220101021222112121102","result":"winner: red"}]},{"n":6,"actions":[["PLACE",5,4],["STEAL"],["PLACE",3,5],["PLACE",5,4],["PLACE",3,4],["PLACE",5,5],["PLACE",5,3],["PLACE",4,3],["PLACE",4,4],["PLACE",3,3],["PLACE",3,2],["PLACE",5,1],["PLACE",3,1],["PLACE",0,3],["PLACE",2,4],["PLACE",2,5],["PLACE",2,1],["PLACE",4,3],["PLACE",3,0],["PLACE",1,3],["PLACE",4,2],["PLACE",3,4],["PLACE",0,2],["PLACE",0,1],["PLACE",5,2],["PLACE",1,2],["PLACE",0,5],["PLACE",4,4],["PLACE",5,0],["PLACE",5,1],["PLACE",4,1],["PLACE",2,2],["PLACE",1,0],["PLACE",2,0],["PLACE",1,5],["PLACE",1,4],["PLACE",3,5],["PLACE",2,3],["PLACE",4,3],["PLACE",0,4],["PLACE",2,4],["PLACE",1,4],["PLACE",4,4],["PLACE",2,3],["PLACE",0,0],["PLACE",4,0],["PLACE",3,4]],"steps":[{"captures":[],"board":"000000000000000000000000000000000010","result":null},{"captures":[],"board":"000000000000000000000000000002000000","result":null},{"captures":[],"board":"000000000000000000000001000002000000","result":null},{"captures":[],"board":"000000000000000000000001000002000020","result":null},{"captures":[],"board":"000000000000000000000011000002000020","result":null},{"captures":[],"board":"000000000000000000000011000002000022","result":null},{"captures":[],"board":"000000000000000000000011000002000122","result":null},{"captures":[],"board":"000000000000000000000011000202000122","result":null},{"captures":[[4,3],[5,4]],"board":"000000000000000000000011000012000102","result":null},{"captures":[],"board":"000000000000000000000211000012000102","result":null},{"captures":[],"board":"000000000000000000001211000012000102","result":null},{"captures":[],"board":"000000000000000000001211000012020102","result":null},{"captures":[],"board":"000000000000000000011211000012020102","result":null},{"captures":[],"board":"000200000000000000011211000012020102","result":null},{"captures":[],"board":"000200000000000010011211000012020102","result":null},{"captures":[[2,4],[3,4]],"board":"000200000000000002011201000012020102","result":null},{"captures":[],"board":"000200000000010002011201000012020102","result":null},{"captures":[],"board":"000200000000010002011201000212020102","result":null},{"captures":[],"board":"000200000000010002111201000212020102","result":null},{"captures":[],"board":"000200000200010002111201000212020102","result":null},{"captures":[],"board":"000200000200010002111201001212020102","result":null},{"captures":[[3,5],[4,4]],"board":"000200000200010002111220001202020102","result":null},{"captures":[],"board":"001200000200010002111220001202020102","result":null},{"captures":[],"board":"021200000200010002111220001202020102","result":null},{"captures":[[4,3],[5,1]],"board":"021200000200010002111220001002001102","result":null},{"captures":[],"board":"021200002200010002111220001002001102","result":null},{"captures":[],"board":"021201002200010002111220001002001102","result":null},{"captures":[],"board":"021201002200010002111220001022001102","result":null},{"captures":[],"board":"021201002200010002111220001022101102","result":null},{"captures":[],"board":"021201002200010002111220001022121102","result":null},{"captures":[],"board":"021201002200010002111220011022121102","result":null},{"captures":[],"board":"021201002200012002111220011022121102","result":null},{"captures":[],"board":"021201102200012002111220011022121102","result":null},{"captures":[],"board":"021201102200212002111220011022121102","result":null},{"captures":[],"board":"021201102201212002111220011022121102","result":null},{"captures":[],"board":"021201102221212002111220011022121102","result":null},{"captures":[],"board":"021201102221212002111221011022121102","result":null},{"captures":[],"board":"021201102221212202111221011022121102","result":null},{"captures":[[3,4],[4,4]],"board":"021201102221212202111201011102121102","result":null},{"captures":[],"board":"021221102221212202111201011102121102","result":null},{"captures":[[1,4],[2,3],[2,5],[3,3]],"board":"021221102201212010111001011102121102","result":null},{"captures":[],"board":"021221102221212010111001011102121102","result":null},{"captures":[],"board":"021221102221212010111001011112121102","result":null},{"captures":[],"board":"021221102221212210111001011112121102","result":null},{"captures":[],"board":"121221102221212210111001011112121102","result":null},{"captures":[[4,1],[5,0]],"board":"121221102221212210111001201112021102","result":null},{"captures":[],"board":"121221102221212210111011201112021102","result":"winner: red"}]},{"n":7,"actions":[["PLACE",0,5],["PLACE",0,4],["PLACE",3,2],["PLACE",1,0],["PLACE",0,0],["PLACE",2,3],["PLACE",0,3],["PLACE",3,1],["PLACE",1,4],["PLACE",2,2],["PLACE",4,2],["PLACE",3,0],["PLACE",1,3],["PLACE",4,3],["PLACE",2,2],["PLACE",1,5],["PLACE",4,6],["PLACE",2,3],["PLACE",2,4],["PLACE",0,2],["PLACE",5,2],["PLACE",5,6],["PLACE",2,2],["PLACE",4,0],["PLACE",6,6],["PLACE",3,4],["PLACE",4,1],["PLACE",2,0],["PLACE",1,1],["PLACE",6,2],["PLACE",0,1],["PLACE",6,5],["PLACE",0,2],["PLACE",4,4],["PLACE",1,2],["PLACE",6,0],["PLACE",1,5],["PLACE",6,3],["PLACE",5,4],["PLACE",6,1],["PLACE",2,1],["PLACE",3,2],["PLACE",5,0],["PLACE",3,3],["PLACE",0,6],["PLACE",1,0],["PLACE",5,1],["PLACE",2,2],["PLACE",2,6],["PLACE",4,5],["PLACE",3,5],["PLACE",1,6],["PLACE",6,4],["PLACE",0,4],["PLACE",4,1],["PLACE",4,4],["PLACE",4,5],["PLACE",2,5]],"steps":[{"captures":[],"board":"0000010000000000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000210000000000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000210000000000000000010000000000000000000000000","result":null},{"captures":[],"board":"0000210200000000000000010000000000000000000000000","result":null},{"captures":[],"board":"1000210200000000000000010000000000000000000000000","result":null},{"captures":[],"board":"1000210200000000020000010000000000000000000000000","result":null},{"captures":[],"board":"1001210200000000020000010000000000000000000000000","result":null},{"captures":[],"board":"1001210200000000020000210000000000000000000000000","result":null},{"captures":[],"board":"1001210200010000020000210000000000000000000000000","result":null},{"captures":[],"board":"1001210200010000220000210000000000000000000000000","result":null},{"captures":[],"board":"1001210200010000220000210000001000000000000000000","result":null},{"captures":[],"board":"1001210200010000220002210000001000000000000000000","result":null},{"captures":[[0,4],[2,2],[2,3]],"board":"1001010200110000000002210000001000000000000000000","result":null},{"captures":[],"board":"1001010200110000000002210000001200000000000000000","result":null},{"captures":[],"board":"1001010200110000100002210000001200000000000000000","result":null},{"captures":[],"board":"1001010200112000100002210000001200000000000000000","result":null},{"captures":[],"board":"1001010200112000100002210000001200100000000000000","result":null},{"captures":[[2,2],[3,2]],"board":"1001010200112000020002200000001200100000000000000","result":null},{"captures":[[1,5],[2,3]],"board":"1001010200110000001002200000001200100000000000000","result":null},{"captures":[],"board":"1021010200110000001002200000001200100000000000000","result":null},{"captures":[],"board":"1021010200110000001002200000001200100100000000000","result":null},{"captures":[],"board":"1021010200110000001002200000001200100100020000000","result":null},{"captures":[],"board":"1021010200110000101002200000001200100100020000000","result":null},{"captures":[],"board":"1021010200110000101002200000201200100100020000000","result":null},{"captures":[],"board":"1021010200110000101002200000201200100100020000001","result":null},{"captures":[],"board":"1021010200110000101002200200201200100100020000001","result":null},{"captures":[],"board":"1021010200110000101002200200211200100100020000001","result":null},{"captures":[],"board":"1021010200110020101002200200211200100100020000001","result":null},{"captures":[],"board":"1021010210110020101002200200211200100100020000001","result":null},{"captures":[],"board":"1021010210110020101002200200211200100100020020001","result":null},{"captures":[[0,2],[1,0]],"board":"1101010010110020101002200200211200100100020020001","result":null},{"captures":[],"board":"1101010010110020101002200200211200100100020020021","result":null},{"captures":[],"board":"1111010010110020101002200200211200100100020020021","result":null},{"captures":[],"board":"1111010010110020101002200200211220100100020020021","result":null},{"captures":[],"board":"1111010011110020101002200200211220100100020020021","result":null},{"captures":[],"board":"1111010011110020101002200200211220100100022020021","result":null},{"captures":[],"board":"1111010011111020101002200200211220100100022020021","result":null},{"captures":[],"board":"1111010011111020101002200200211220100100022022021","result":null},{"captures":[],"board":"1111010011111020101002200200211220100101022022021","result":null},{"captures":[],"board":"1111010011111020101002200200211220100101022222021","result":null},{"captures":[],"board":"1111010011111021101002200200211220100101022222021","result":null},{"captures":[[2,2],[4,1]],"board":"1111010011111021001002220200201220100101022222021","result":null},{"captures":[],"board":"1111010011111021001002220200201220110101022222021","result":null},{"captures":[],"board":"1111010011111021001002222200201220110101022222021","result":null},{"captures":[],"board":"1111011011111021001002222200201220110101022222021","result":null},{"captures":[],"board":"1111011211111021001002222200201220110101022222021","result":null},{"captures":[],"board":"1111011211111021001002222200201220111101022222021","result":null},{"captures":[],"board":"1111011211111021201002222200201220111101022222021","result":null},{"captures":[],"board":"1111011211111021201012222200201220111101022222021","result":null},{"captures":[],"board":"1111011211111021201012222200201222111101022222021","result":null},{"captures":[[4,4],[4,5]],"board":"1111011211111021201012222210201200111101022222021","result":null},{"captures":[],"board":"1111011211111221201012222210201200111101022222021","result":null},{"captures":[],"board":"1111011211111221201012222210201200111101022222121","result":null},{"captures":[],"board":"1111211211111221201012222210201200111101022222121","result":null},{"captures":[],"board":"1111211211111221201012222210211200111101022222121","result":null},{"captures":[],"board":"1111211211111221201012222210211220111101022222121","result":null},{"captures":[],"board":"1111211211111221201012222210211221111101022222121","result":null},{"captures":[[1,5],[2,4],[2,6],[3,5]],"board":"1111211211110221200202222200211221111101022222121","result":"winner: blue"}]},{"n":8,"actions":[["PLACE",2,3],["STEAL"],["PLACE",4,1],["PLACE",2,2],["PLACE",3,1],["PLACE",4,0],["PLACE",2,1],["PLACE",3,1],["PLACE",1,3],["PLACE",1,1],["PLACE",3,4],["PLACE",7,4],["PLACE",3,0],["PLACE",4,4],["PLACE",0,1],["PLACE",0,4],["PLACE",4,5],["PLACE",4,1],["PLACE",2,5],["PLACE",3,6],["PLACE",0,5],["PLACE",1,6],["PLACE",7,3],["PLACE",4,6],["PLACE",0,2],["PLACE",2,0],["PLACE",6,4],["PLACE",2,7],["PLACE",2,4],["PLACE",0,3],["PLACE",2,1],["PLACE",6,2],["PLACE",3,5],["PLACE",4,7],["PLACE",1,2],["PLACE",5,4],["PLACE",1,7],["PLACE",0,7],["PLACE",3,0],["PLACE",1,1],["PLACE",2,3],["PLACE",4,4],["PLACE",4,2],["PLACE",6,5],["PLACE",5,0],["PLACE",5,6],["PLACE",2,6],["PLACE",0,0],["PLACE",5,2],["PLACE",2,0],["PLACE",7,1],["PLACE",2,2],["PLACE",0,6],["PLACE",3,6],["PLACE",7,6],["PLACE",4,3],["PLACE",3,3],["PLACE",1,5],["PLACE",4,3],["PLACE",3,1],["PLACE",7,2],["PLACE",5,1],["PLACE",6,3],["PLACE",1,6],["PLACE",7,5],["PLACE",5,0],["PLACE",7,4],["PLACE",2,5],["PLACE",3,2],["PLACE",3,5],["PLACE",6,7],["PLACE",0,3],["PLACE",1,4],["PLACE",0,6],["PLACE",3,4],["PLACE",1,7],["PLACE",2,6],["PLACE",5,3],["PLACE",7,7],["PLACE",6,1],["PLACE",2,5],["PLACE",5,5]],"steps":[{"captures":[],"board":"0000000000000000000100000000000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000020000000000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000020000001000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000002000000020000001000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000002000000120000001000000000000000000000000000000","result":null},{"captures":[[3,1],[4,1]],"board":"0000000000000000002000000020000020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000012000000020000020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000012000000220000020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000010000012000000220000020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000002010000012000000220000020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000002010000012000000220100020000000000000000000000000000000","result":null},{"captures":[],"board":"0000000002010000012000000220100020000000000000000000000000002000","result":null},{"captures":[],"board":"0000000002010000012000001220100020000000000000000000000000002000","result":null},{"captures":[],"board":"0000000002010000012000001220100020002000000000000000000000002000","result":null},{"captures":[],"board":"0100000002010000012000001220100020002000000000000000000000002000","result":null},{"captures":[],"board":"0100200002010000012000001220100020002000000000000000000000002000","result":null},{"captures":[],"board":"0100200002010000012000001220100020002100000000000000000000002000","result":null},{"captures":[],"board":"0100200002010000012000001220100022002100000000000000000000002000","result":null},{"captures":[],"board":"0100200002010000012001001220100022002100000000000000000000002000","result":null},{"captures":[],"board":"0100200002010000012001001220102022002100000000000000000000002000","result":null},{"captures":[],"board":"0100210002010000012001001220102022002100000000000000000000002000","result":null},{"captures":[],"board":"0100210002010020012001001220102022002100000000000000000000002000","result":null},{"captures":[],"board":"0100210002010020012001001220102022002100000000000000000000012000","result":null},{"captures":[],"board":"0100210002010020012001001220102022002120000000000000000000012000","result":null},{"captures":[],"board":"0110210002010020012001001220102022002120000000000000000000012000","result":null},{"captures":[[2,1],[3,0]],"board":"0110210002010020202001000220102022002120000000000000000000012000","result":null},{"captures":[],"board":"0110210002010020202001000220102022002120000000000000100000012000","result":null},{"captures":[],"board":"0110210002010020202001020220102022002120000000000000100000012000","result":null},{"captures":[],"board":"0110210002010020202011020220102022002120000000000000100000012000","result":null},{"captures":[],"board":"0112210002010020202011020220102022002120000000000000100000012000","result":null},{"captures":[],"board":"0112210002010020212011020220102022002120000000000000100000012000","result":null},{"captures":[],"board":"0112210002010020212011020220102022002120000000000020100000012000","result":null},{"captures":[[3,6],[4,4]],"board":"0112210002010020212011020220110022000120000000000020100000012000","result":null},{"captures":[],"board":"0112210002010020212011020220110022000122000000000020100000012000","result":null},{"captures":[[0,3],[1,1],[2,2]],"board":"0110210000110020210011020220110022000122000000000020100000012000","result":null},{"captures":[],"board":"0110210000110020210011020220110022000122000020000020100000012000","result":null},{"captures":[],"board":"0110210000110021210011020220110022000122000020000020100000012000","result":null},{"captures":[],"board":"0110210200110021210011020220110022000122000020000020100000012000","result":null},{"captures":[[2,0],[3,1]],"board":"0110210200110021010011021020110022000122000020000020100000012000","result":null},{"captures":[],"board":"0110210202110021010011021020110022000122000020000020100000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022000122000020000020100000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022002122000020000020100000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022102122000020000020100000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022102122000020000020120000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022102122100020000020120000012000","result":null},{"captures":[],"board":"0110210202110021010111021020110022102122100020200020120000012000","result":null},{"captures":[[1,6],[2,7]],"board":"0110210202110001010111101020110022102122100020200020120000012000","result":null},{"captures":[],"board":"2110210202110001010111101020110022102122100020200020120000012000","result":null},{"captures":[],"board":"2110210202110001010111101020110022102122101020200020120000012000","result":null},{"captures":[],"board":"2110210202110001210111101020110022102122101020200020120000012000","result":null},{"captures":[],"board":"2110210202110001210111101020110022102122101020200020120001012000","result":null},{"captures":[[1,2],[2,1]],"board":"2110210202010001202111101020110022102122101020200020120001012000","result":null},{"captures":[],"board":"2110211202010001202111101020110022102122101020200020120001012000","result":null},{"captures":[[3,5],[4,5]],"board":"2110211202010001202111101020102022102022101020200020120001012000","result":null},{"captures":[],"board":"2110211202010001202111101020102022102022101020200020120001012010","result":null},{"captures":[],"board":"2110211202010001202111101020102022122022101020200020120001012010","result":null},{"captures":[[3,2],[4,3]],"board":"2110211202010001202111101001102022102022101020200020120001012010","result":null},{"captures":[],"board":"2110211202010201202111101001102022102022101020200020120001012010","result":null},{"captures":[],"board":"2110211202010201202111101001102022112022101020200020120001012010","result":null},{"captures":[],"board":"2110211202010201202111101201102022112022101020200020120001012010","result":null},{"captures":[],"board":"2110211202010201202111101201102022112022101020200020120001112010","result":null},{"captures":[[4,2],[5,0]],"board":"2110211202010201202111101201102022012022021020200020120001112010","result":null},{"captures":[],"board":"2110211202010201202111101201102022012022021020200021120001112010","result":null},{"captures":[[0,6],[1,7],[2,5]],"board":"2110210202010220202110101201102022012022021020200021120001112010","result":null},{"captures":[[6,5],[7,4]],"board":"2110210202010220202110101201102022012022021020200021100001110110","result":null},{"captures":[],"board":"2110210202010220202110101201102022012022221020200021100001110110","result":null},{"captures":[],"board":"2110210202010220202110101201102022012022221020200021100001111110","result":null},{"captures":[],"board":"2110210202010220202112101201102022012022221020200021100001111110","result":null},{"captures":[],"board":"2110210202010220202112101211102022012022221020200021100001111110","result":null},{"captures":[[2,6],[3,4]],"board":"2110210202010220202112001211022022012022221020200021100001111110","result":null},{"captures":[],"board":"2110210202010220202112001211022022012022221020200021100101111110","result":null},{"captures":[],"board":"2112210202010220202112001211022022012022221020200021100101111110","result":null},{"captures":[[0,4],[1,5]],"board":"2112010202011020202112001211022022012022221020200021100101111110","result":null},{"captures":[],"board":"2112012202011020202112001211022022012022221020200021100101111110","result":null},{"captures":[],"board":"2112012202011020202112001211122022012022221020200021100101111110","result":null},{"captures":[],"board":"2112012202011022202112001211122022012022221020200021100101111110","result":null},{"captures":[[2,5],[3,5]],"board":"2112012202011022202110101211102022012022221020200021100101111110","result":null},{"captures":[[5,2],[6,3]],"board":"2112012202011022202110101211102022012022220220200020100101111110","result":null},{"captures":[],"board":"2112012202011022202110101211102022012022220220200020100101111111","result":null},{"captures":[],"board":"2112012202011022202110101211102022012022220220200220100101111111","result":null},{"captures":[],"board":"2112012202011022202111101211102022012022220220200220100101111111","result":null},{"captures":[],"board":"2112012202011022202111101211102022012022220222200220100101111111","result":"winner: blue"}]},{"n":3,"actions":[["PLACE",0,1],["STEAL"],["PLACE",1,1],["PLACE",2,1],["PLACE",0,1],["PLACE",2,0],["PLACE",2,2],["PLACE",0,0],["PLACE",0,2],["PLACE",1,2]],"steps":[{"captures":[],"board":"010000000","result":null},{"captures":[],"board":"000200000","result":null},{"captures":[],"board":"000210000","result":null},{"captures":[],"board":"000210020","result":null},{"captures":[],"board":"010210020","result":null},{"captures":[],"board":"010210220","result":null},{"captures":[],"board":"010210221","result":null},{"captures":[],"board":"210210221","result":null},{"captures":[],"board":"211210221","result":null},{"captures":[[1,1],[2,2]],"board":"211202220","result":"winner: blue"}]},{"n":4,"actions":[["PLACE",0,1],["STEAL"],["PLACE",0,0],["PLACE",0,1],["PLACE",2,0],["PLACE",1,1],["PLACE",3,0],["PLACE",3,1],["PLACE",1,2],["PLACE",2,2],["PLACE",1,3],["PLACE",0,2],["PLACE",0,3],["PLACE",2,1],["PLACE",1,2],["PLACE",2,3]],"steps":[{"captures":[],"board":"0100000000000000","result":null},{"captures":[],"board":"0000200000000000","result":null},{"captures":[],"board":"1000200000000000","result":null},{"captures":[],"board":"1200200000000000","result":null},{"captures":[],"board":"1200200010000000","result":null},{"captures":[],"board":"1200220010000000","result":null},{"captures":[],"board":"1200220010001000","result":null},{"captures":[],"board":"1200220010001200","result":null},{"captures":[],"board":"1200221010001200","result":null},{"captures":[],"board":"1200221010201200","result":null},{"captures":[],"board":"1200221110201200","result":null},{"captures":[],"board":"1220221110201200","result":null},{"captures":[],"board":"1221221110201200","result":null},{"captures":[[1,2],[2,0]],"board":"1221220102201200","result":null},{"captures":[],"board":"1221221102201200","result":null},{"captures":[],"board":"1221221102221200","result":"winner: blue"}]},{"n":5,"actions":[["PLACE",0,4],["PLACE",1,3],["PLACE",2,3],["PLACE",1,2],["PLACE",3,3],["PLACE",2,2],["PLACE",2,4],["PLACE",1,1],["PLACE",2,0],["PLACE",3,4],["PLACE",1,4],["PLACE",3,2],["PLACE",0,2],["PLACE",2,1],["PLACE",4,3]],"steps":[{"captures":[],"board":"0000100000000000000000000","result":null},{"captures":[],"board":"0000100020000000000000000","result":null},{"captures":[],"board":"0000100020000100000000000","result":null},{"captures":[],"board":"0000100220000100000000000","result":null},{"captures":[],"board":"0000100220000100001000000","result":null},{"captures":[],"board":"0000100220002100001000000","result":null},{"captures":[],"board":"0000100220002110001000000","result":null},{"captures":[],"board":"0000102220002110001000000","result":null},{"captures":[],"board":"0000102220102110001000000","result":null},{"captures":[],"board":"0000102220102110001200000","result":null},{"captures":[],"board":"0000102221102110001200000","result":null},{"captures":[],"board":"0000102221102110021200000","result":null},{"captures":[],"board":"0010102221102110021200000","result":null},{"captures":[],"board":"0010102221122110021200000","result":null},{"captures":[],"board":"0010102221122110021200010","result":"winner: red"}]},{"n":6,"actions":[["PLACE",2,2],["PLACE",2,1],["PLACE",1,3],["PLACE",3,0],["PLACE",4,0],["PLACE",1,1],["PLACE",0,3],["PLACE",0,2],["PLACE",1,0],["PLACE",4,1],["PLACE",0,4],["PLACE",2,0],["PLACE",4,2],["PLACE",0,5],["PLACE",1,5],["PLACE",2,3],["PLACE",5,2],["PLACE",3,3],["PLACE",5,0],["PLACE",2,4],["PLACE",3,1]],"steps":[{"captures":[],"board":"000000000000001000000000000000000000","result":null},{"captures":[],"board":"000000000000021000000000000000000000","result":null},{"captures":[],"board":"000000000100021000000000000000000000","result":null},{"captures":[],"board":"000000000100021000200000000000000000","result":null},{"captures":[],"board":"000000000100021000200000100000000000","result":null},{"captures":[],"board":"000000020100021000200000100000000000","result":null},{"captures":[],"board":"000100020100021000200000100000000000","result":null},{"captures":[],"board":"002100020100021000200000100000000000","result":null},{"captures":[],"board":"002100120100021000200000100000000000","result":null},{"captures":[],"board":"002100120100021000200000120000000000","result":null},{"captures":[],"board":"002110120100021000200000120000000000","result":null},{"captures":[],"board":"002110120100221000200000120000000000","result":null},{"captures":[],"board":"002110120100221000200000121000000000","result":null},{"captures":[],"board":"002112120100221000200000121000000000","result":null},{"captures":[],"board":"002112120101221000200000121000000000","result":null},{"captures":[],"board":"002112120101221200200000121000000000","result":null},{"captures":[],"board":"002112120101221200200000121000001000","result":null},{"captures":[],"board":"002112120101221200200200121000001000","result":null},{"captures":[],"board":"002112120101221200200200121000101000","result":null},{"captures":[],"board":"002112120101221220200200121000101000","result":null},{"captures":[[3,0],[4,1]],"board":"002112120101221220010200101000101000","result":"winner: red"}]},{"n":7,"actions":[["PLACE",2,2],["PLACE",1,0],["PLACE",2,0],["PLACE",3,3],["PLACE",3,4],["PLACE",2,1],["PLACE",1,3],["PLACE",6,4],["PLACE",1,5],["PLACE",6,5],["PLACE",0,3],["PLACE",2,3],["PLACE",5,6],["PLACE",2,4],["PLACE",3,5],["PLACE",3,1],["PLACE",6,3],["PLACE",4,0],["PLACE",6,2],["PLACE",5,5],["PLACE",6,1],["PLACE",1,6],["PLACE",0,1],["PLACE",2,6],["PLACE",0,4],["PLACE",4,4],["PLACE",5,4],["PLACE",4,5],["PLACE",1,4],["PLACE",5,2],["PLACE",5,0],["PLACE",6,0],["PLACE",1,1],["PLACE",0,0],["PLACE",4,3],["PLACE",1,2],["PLACE",2,1],["PLACE",3,6],["PLACE",4,1],["PLACE",3,2],["PLACE",2,5],["PLACE",5,3],["PLACE",2,4],["PLACE",5,1],["PLACE",4,1],["PLACE",1,3],["PLACE",0,6],["PLACE",4,3],["PLACE",4,4],["PLACE",4,2],["PLACE",0,2],["PLACE",5,4]],"steps":[{"captures":[],"board":"0000000000000000100000000000000000000000000000000","result":null},{"captures":[],"board":"0000000200000000100000000000000000000000000000000","result":null},{"captures":[],"board":"0000000200000010100000000000000000000000000000000","result":null},{"captures":[],"board":"0000000200000010100000002000000000000000000000000","result":null},{"captures":[],"board":"0000000200000010100000002100000000000000000000000","result":null},{"captures":[],"board":"0000000200000012100000002100000000000000000000000","result":null},{"captures":[],"board":"0000000200100012100000002100000000000000000000000","result":null},{"captures":[],"board":"0000000200100012100000002100000000000000000000200","result":null},{"captures":[],"board":"0000000200101012100000002100000000000000000000200","result":null},{"captures":[],"board":"0000000200101012100000002100000000000000000000220","result":null},{"captures":[],"board":"0001000200101012100000002100000000000000000000220","result":null},{"captures":[],"board":"0001000200101012120000002100000000000000000000220","result":null},{"captures":[],"board":"0001000200101012120000002100000000000000010000220","result":null},{"captures":[],"board":"0001000200101012122000002100000000000000010000220","result":null},{"captures":[],"board":"0001000200101012122000002110000000000000010000220","result":null},{"captures":[],"board":"0001000200101012122000202110000000000000010000220","result":null},{"captures":[],"board":"0001000200101012122000202110000000000000010001220","result":null},{"captures":[],"board":"0001000200101012122000202110200000000000010001220","result":null},{"captures":[],"board":"0001000200101012122000202110200000000000010011220","result":null},{"captures":[],"board":"0001000200101012122000202110200000000000210011220","result":null},{"captures":[],"board":"0001000200101012122000202110200000000000210111220","result":null},{"captures":[],"board":"0001000200101212122000202110200000000000210111220","result":null},{"captures":[],"board":"0101000200101212122000202110200000000000210111220","result":null},{"captures":[],"board":"0101000200101212122020202110200000000000210111220","result":null},{"captures":[],"board":"0101100200101212122020202110200000000000210111220","result":null},{"captures":[],"board":"0101100200101212122020202110200020000000210111220","result":null},{"captures":[],"board":"0101100200101212122020202110200020000001210111220","result":null},{"captures":[[3,5],[5,4]],"board":"0101100200101212122020202100200022000000210111220","result":null},{"captures":[],"board":"0101100200111212122020202100200022000000210111220","result":null},{"captures":[],"board":"0101100200111212122020202100200022000200210111220","result":null},{"captures":[],"board":"0101100200111212122020202100200022010200210111220","result":null},{"captures":[],"board":"0101100200111212122020202100200022010200212111220","result":null},{"captures":[[1,0],[2,1]],"board":"0101100010111210122020202100200022010200212111220","result":null},{"captures":[],"board":"2101100010111210122020202100200022010200212111220","result":null},{"captures":[[3,3],[4,4]],"board":"2101100010111210122020200100200102010200212111220","result":null},{"captures":[[1,3],[2,2]],"board":"2101100012011210022020200100200102010200212111220","result":null},{"captures":[],"board":"2101100012011211022020200100200102010200212111220","result":null},{"captures":[],"board":"2101100012011211022020200102200102010200212111220","result":null},{"captures":[],"board":"2101100012011211022020200102210102010200212111220","result":null},{"captures":[],"board":"2101100012011211022020220102210102010200212111220","result":null},{"captures":[[1,6],[2,4]],"board":"2101100012011011020120220102210102010200212111220","result":null},{"captures":[[4,3],[6,2]],"board":"2101100012011011020120220102210002010220212101220","result":null},{"captures":[],"board":"2101100012011011021120220102210002010220212101220","result":null},{"captures":[[4,1],[5,0],[6,1]],"board":"2101100012011011021120220102200002002220212001220","result":null},{"captures":[],"board":"2101100012011011021120220102210002002220212001220","result":null},{"captures":[],"board":"2101100012211011021120220102210002002220212001220","result":null},{"captures":[],"board":"2101101012211011021120220102210002002220212001220","result":null},{"captures":[],"board":"2101101012211011021120220102210202002220212001220","result":null},{"captures":[],"board":"2101101012211011021120220102210212002220212001220","result":null},{"captures":[],"board":"2101101012211011021120220102212212002220212001220","result":null},{"captures":[],"board":"2111101012211011021120220102212212002220212001220","result":null},{"captures":[[4,4],[6,3]],"board":"2111101012211011021120220102212202002222212000220","result":"winner: blue"}]},{"n":8,"actions":[["PLACE",3,7],["STEAL"],["PLACE",6,3],["PLACE",7,4],["PLACE",7,2],["PLACE",6,4],["PLACE",7,1],["PLACE",5,5],["PLACE",5,4],["PLACE",4,1],["PLACE",4,0],["PLACE",5,6],["PLACE",3,4],["PLACE",7,5],["PLACE",4,7],["PLACE",3,5],["PLACE",5,7],["PLACE",3,1],["PLACE",5,3],["PLACE",6,5],["PLACE",2,6],["PLACE",2,4],["PLACE",3,3],["PLACE",2,2],["PLACE",3,6],["PLACE",3,0],["PLACE",6,7],["PLACE",5,0],["PLACE",6,0],["PLACE",1,5],["PLACE",1,3],["PLACE",0,3],["PLACE",1,4],["PLACE",4,5],["PLACE",6,6],["PLACE",4,4],["PLACE",2,7],["PLACE",0,5],["PLACE",5,2],["PLACE",5,1],["PLACE",3,2],["PLACE",1,7],["PLACE",3,1],["PLACE",7,6],["PLACE",4,2],["PLACE",0,7],["PLACE",1,6],["PLACE",2,0],["PLACE",4,3],["PLACE",1,0],["PLACE",4,1],["PLACE",0,0],["PLACE",0,4],["PLACE",6,2],["PLACE",3,7],["PLACE",2,5],["PLACE",0,6],["PLACE",1,6],["PLACE",1,2],["PLACE",1,1],["PLACE",7,0],["PLACE",2,2],["PLACE",0,2],["PLACE",2,6],["PLACE",2,1],["PLACE",6,3],["PLACE",0,5],["PLACE",2,2],["PLACE",0,3],["PLACE",2,3],["PLACE",6,1]],"steps":[{"captures":[],"board":"0000000000000000000000000000000100000000000000000000000000000000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000000000000020000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000001000000020000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000001000000022000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000001000000122000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000001200000122000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000000000001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000002000001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000000000000000000012000001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000000002000000000012000001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000000012000000000012000001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000000012000000000012200001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000100012000000000012200001200001122000","result":null},{"captures":[],"board":"0000000000000000000000000000100012000000000012200001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000000100012000001000012200001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000000120012000001000012200001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000000120012000001000012210001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000200120012000001000012210001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000200120012000001000112210001200001122200","result":null},{"captures":[],"board":"0000000000000000000000000200120012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000000000100200120012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000000020100200120012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000000020100201120012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000002020100201120012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000002020100201121012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000002020102201121012000001000112210001220001122200","result":null},{"captures":[],"board":"0000000000000000002020102201121012000001000112210001220101122200","result":null},{"captures":[],"board":"0000000000000000002020102201121012000001200112210001220101122200","result":null},{"captures":[],"board":"0000000000000000002020102201121012000001200112211001220101122200","result":null},{"captures":[],"board":"0000000000000200002020102201121012000001200112211001220101122200","result":null},{"captures":[],"board":"0000000000010200002020102201121012000001200112211001220101122200","result":null},{"captures":[],"board":"0002000000010200002020102201121012000001200112211001220101122200","result":null},{"captures":[],"board":"0002000000011200002020102201121012000001200112211001220101122200","result":null},{"captures":[],"board":"0002000000011200002020102201121012000201200112211001220101122200","result":null},{"captures":[],"board":"0002000000011200002020102201121012000201200112211001221101122200","result":null},{"captures":[],"board":"0002000000011200002020102201121012002201200112211001221101122200","result":null},{"captures":[],"board":"0002000000011200002020112201121012002201200112211001221101122200","result":null},{"captures":[],"board":"0002020000011200002020112201121012002201200112211001221101122200","result":null},{"captures":[],"board":"0002020000011200002020112201121012002201201112211001221101122200","result":null},{"captures":[],"board":"0002020000011200002020112201121012002201221112211001221101122200","result":null},{"captures":[[3,1],[4,1]],"board":"0002020000011200002020112011121010002201221112211001221101122200","result":null},{"captures":[],"board":"0002020000011202002020112011121010002201221112211001221101122200","result":null},{"captures":[],"board":"0002020000011202002020112111121010002201221112211001221101122200","result":null},{"captures":[],"board":"0002020000011202002020112111121010002201221112211001221101122220","result":null},{"captures":[],"board":"0002020000011202002020112111121010102201221112211001221101122220","result":null},{"captures":[],"board":"0002020200011202002020112111121010102201221112211001221101122220","result":null},{"captures":[],"board":"0002020200011212002020112111121010102201221112211001221101122220","result":null},{"captures":[],"board":"0002020200011212202020112111121010102201221112211001221101122220","result":null},{"captures":[],"board":"0002020200011212202020112111121010112201221112211001221101122220","result":null},{"captures":[],"board":"0002020220011212202020112111121010112201221112211001221101122220","result":null},{"captures":[[5,0],[5,1]],"board":"0002020220011212202020112111121011112201001112211001221101122220","result":null},{"captures":[],"board":"2002020220011212202020112111121011112201001112211001221101122220","result":null},{"captures":[],"board":"2002120220011212202020112111121011112201001112211001221101122220","result":null},{"captures":[[6,3],[7,2]],"board":"2002120220011212202020112111121011112201001112211020221101022220","result":null},{"captures":[],"board":"2002120220011212202020112111121111112201001112211020221101022220","result":null},{"captures":[[1,6],[2,6],[3,4]],"board":"2002120220011202202022012111021111112201001112211020221101022220","result":null},{"captures":[[0,5],[1,5]],"board":"2002101220011002202022012111021111112201001112211020221101022220","result":null},{"captures":[],"board":"2002101220011022202022012111021111112201001112211020221101022220","result":null},{"captures":[[0,3],[2,2]],"board":"2000101220111022200022012111021111112201001112211020221101022220","result":null},{"captures":[],"board":"2000101222111022200022012111021111112201001112211020221101022220","result":null},{"captures":[],"board":"2000101222111022200022012111021111112201001112211020221111022220","result":null},{"captures":[],"board":"2000101222111022202022012111021111112201001112211020221111022220","result":null},{"captures":[],"board":"2010101222111022202022012111021111112201001112211020221111022220","result":null},{"captures":[],"board":"2010101222111022202022212111021111112201001112211020221111022220","result":null},{"captures":[[1,1],[2,2],[3,0]],"board":"2010101220111022210022210111021111112201001112211020221111022220","result":null},{"captures":[[5,3],[5,4]],"board":"2010101220111022210022210111021111112201001002211022221111022220","result":null},{"captures":[],"board":"2010111220111022210022210111021111112201001002211022221111022220","result":null},{"captures":[],"board":"2010111220111022212022210111021111112201001002211022221111022220","result":null},{"captures":[],"board":"2011111220111022212022210111021111112201001002211022221111022220","result":null},{"captures":[[1,3],[1,4],[3,2],[3,3]],"board":"2011111220100022212222210100021111112201001002211022221111022220","result":null},{"captures":[],"board":"2011111220100022212222210100021111112201001002211122221111022220","result":"winner: red"}]},{"n":3,"actions":[["PLACE",0,0],["PLACE",1,0],["PLACE",1,1],["PLACE",2,2],["PLACE",0,1],["PLACE",1,2],["PLACE",0,2],["PLACE",2,0],["PLACE",2,1]],"steps":[{"captures":[],"board":"100000000","result":null},{"captures":[],"board":"100200000","result":null},{"captures":[],"board":"100210000","result":null},{"captures":[],"board":"100210002","result":null},{"captures":[],"board":"110210002","result":null},{"captures":[],"board":"110212002","result":null},{"captures":[],"board":"111212002","result":null},{"captures":[],"board":"111212202","result":null},{"captures":[[1,2],[2,0]],"board":"111210012","result":"winner: red"}]},{"n":4,"actions":[["PLACE",0,2],["STEAL"],["PLACE",3,2],["PLACE",2,1],["PLACE",3,3],["PLACE",2,2],["PLACE",1,0],["PLACE",1,3]],"steps":[{"captures":[],"board":"0010000000000000","result":null},{"captures":[],"board":"0000000020000000","result":null},{"captures":[],"board":"0000000020000010","result":null},{"captures":[],"board":"0000000022000010","result":null},{"captures":[],"board":"0000000022000011","result":null},{"captures":[],"board":"0000000022200011","result":null},{"captures":[],"board":"0000100022200011","result":null},{"captures":[],"board":"0000100222200011","result":"winner: blue"}]},{"n":5,"actions":[["PLACE",0,1],["STEAL"],["PLACE",0,0],["PLACE",1,1],["PLACE",0,1],["PLACE",0,2],["PLACE",2,0],["PLACE",2,4],["PLACE",1,1],["PLACE",1,0],["PLACE",0,3],["PLACE",1,1],["PLACE",3,4],["PLACE",2,3],["PLACE",4,0],["PLACE",3,2],["PLACE",4,1],["PLACE",4,2],["PLACE",3,3],["PLACE",4,3],["PLACE",4,2],["PLACE",0,1],["PLACE",2,2],["PLACE",1,2],["PLACE",3,3],["PLACE",2,1],["PLACE",3,4],["PLACE",1,3],["PLACE",4,3],["PLACE",3,1],["PLACE",3,2],["PLACE",2,4]],"steps":[{"captures":[],"board":"0100000000000000000000000","result":null},{"captures":[],"board":"0000020000000000000000000","result":null},{"captures":[],"board":"1000020000000000000000000","result":null},{"captures":[],"board":"1000022000000000000000000","result":null},{"captures":[],"board":"1100022000000000000000000","result":null},{"captures":[],"board":"1120022000000000000000000","result":null},{"captures":[[1,0],[1,1]],"board":"1120000000100000000000000","result":null},{"captures":[],"board":"1120000000100020000000000","result":null},{"captures":[],"board":"1120001000100020000000000","result":null},{"captures":[[0,1],[1,1]],"board":"1020020000100020000000000","result":null},{"captures":[],"board":"1021020000100020000000000","result":null},{"captures":[],"board":"1021022000100020000000000","result":null},{"captures":[],"board":"1021022000100020000100000","result":null},{"captures":[],"board":"1021022000100220000100000","result":null},{"captures":[],"board":"1021022000100220000110000","result":null},{"captures":[],"board":"1021022000100220020110000","result":null},{"captures":[],"board":"1021022000100220020111000","result":null},{"captures":[],"board":"1021022000100220020111200","result":null},{"captures":[[3,2],[4,2]],"board":"1021022000100220001111000","result":null},{"captures":[[3,3],[3,4]],"board":"1021022000100220000011020","result":null},{"captures":[],"board":"1021022000100220000011120","result":null},{"captures":[],"board":"1221022000100220000011120","result":null},{"captures":[],"board":"1221022000101220000011120","result":null},{"captures":[],"board":"1221022200101220000011120","result":null},{"captures":[],"board":"1221022200101220001011120","result":null},{"captures":[],"board":"1221022200121220001011120","result":null},{"captures":[[2,4],[4,3]],"board":"1221022200121200001111100","result":null},{"captures":[[0,3],[2,2]],"board":"1220022220120200001111100","result":null},{"captures":[],"board":"1220022220120200001111110","result":null},{"captures":[],"board":"1220022220120200201111110","result":null},{"captures":[],"board":"1220022220120200211111110","result":null},{"captures":[],"board":"1220022220120220211111110","result":"winner: blue"}]},{"n":6,"actions":[["PLACE",2,0],["STEAL"],["PLACE",2,2],["PLACE",0,1],["PLACE",2,1],["PLACE",1,3],["PLACE",3,5],["PLACE",3,1],["PLACE",1,0],["PLACE",1,2],["PLACE",4,2],["PLACE",3,0],["PLACE",4,5],["PLACE",4,3],["PLACE",2,2],["PLACE",2,0],["PLACE",3,4],["PLACE",3,2],["PLACE",1,4],["PLACE",5,5],["PLACE",2,4],["PLACE",4,1],["PLACE",0,0],["PLACE",5,3],["PLACE",1,1],["PLACE",1,5],["PLACE",2,1],["PLACE",3,3],["PLACE",2,0],["PLACE",0,5],["PLACE",0,4],["PLACE",2,3],["PLACE",0,5],["PLACE",1,3],["PLACE",5,2],["PLACE",2,4],["PLACE",4,2],["PLACE",1,4],["PLACE",0,3],["PLACE",4,4],["PLACE",3,4],["PLACE",5,4],["PLACE",3,1],["PLACE",4,1],["PLACE",4,3],["PLACE",4,0],["PLACE",2,5],["PLACE",1,2],["PLACE",1,1],["PLACE",5,1],["PLACE",0,3],["PLACE",5,0],["PLACE",0,1],["PLACE",3,2]],"steps":[{"captures":[],"board":"000000000000100000000000000000000000","result":null},{"captures":[],"board":"002000000000000000000000000000000000","result":null},{"captures":[],"board":"002000000000001000000000000000000000","result":null},{"captures":[],"board":"022000000000001000000000000000000000","result":null},{"captures":[],"board":"022000000000011000000000000000000000","result":null},{"captures":[],"board":"022000000200011000000000000000000000","result":null},{"captures":[],"board":"022000000200011000000001000000000000","result":null},{"captures":[],"board":"022000000200011000020001000000000000","result":null},{"captures":[],"board":"022000100200011000020001000000000000","result":null},{"captures":[[2,1],[2,2]],"board":"022000102200000000020001000000000000","result":null},{"captures":[],"board":"022000102200000000020001001000000000","result":null},{"captures":[],"board":"022000102200000000220001001000000000","result":null},{"captures":[],"board":"022000102200000000220001001001000000","result":null},{"captures":[],"board":"022000102200000000220001001201000000","result":null},{"captures":[],"board":"022000102200001000220001001201000000","result":null},{"captures":[],"board":"022000102200201000220001001201000000","result":null},{"captures":[],"board":"022000102200201000220011001201000000","result":null},{"captures":[],"board":"022000102200201000222011001201000000","result":null},{"captures":[],"board":"022000102210201000222011001201000000","result":null},{"captures":[],"board":"022000102210201000222011001201000002","result":null},{"captures":[],"board":"022000102210201010222011001201000002","result":null},{"captures":[],"board":"022000102210201010222011021201000002","result":null},{"captures":[],"board":"122000102210201010222011021201000002","result":null},{"captures":[],"board":"122000102210201010222011021201000202","result":null},{"captures":[[0,1],[2,0]],"board":"102000112210001010222011021201000202","result":null},{"captures":[],"board":"102000112212001010222011021201000202","result":null},{"captures":[[1,2],[3,1]],"board":"102000110212011010202011021201000202","result":null},{"captures":[[3,4],[4,2]],"board":"102000110212011010202201020201000202","result":null},{"captures":[],"board":"102000110212111010202201020201000202","result":null},{"captures":[],"board":"102002110212111010202201020201000202","result":null},{"captures":[[0,5],[1,3]],"board":"102010110012111010202201020201000202","result":null},{"captures":[[1,4],[2,4]],"board":"102010110002111200202201020201000202","result":null},{"captures":[],"board":"102011110002111200202201020201000202","result":null},{"captures":[],"board":"102011110202111200202201020201000202","result":null},{"captures":[],"board":"102011110202111200202201020201001202","result":null},{"captures":[],"board":"102011110202111220202201020201001202","result":null},{"captures":[],"board":"102011110202111220202201021201001202","result":null},{"captures":[],"board":"102011110222111220202201021201001202","result":null},{"captures":[],"board":"102111110222111220202201021201001202","result":null},{"captures":[],"board":"102111110222111220202201021221001202","result":null},{"captures":[[3,3],[4,3]],"board":"102111110222111220202011021021001202","result":null},{"captures":[],"board":"102111110222111220202011021021001222","result":null},{"captures":[[3,2],[4,1]],"board":"102111110222111220210011001021001222","result":null},{"captures":[],"board":"102111110222111220210011021021001222","result":null},{"captures":[],"board":"102111110222111220210011021121001222","result":null},{"captures":[],"board":"102111110222111220210011221121001222","result":null},{"captures":[],"board":"102111110222111221210011221121001222","result":null},{"captures":[[0,3],[1,1],[2,2]],"board":"102011102222110221210011221121001222","result":null},{"captures":[],"board":"102011112222110221210011221121001222","result":null},{"captures":[],"board":"102011112222110221210011221121021222","result":null},{"captures":[[0,2],[1,2]],"board":"100111110222110221210011221121021222","result":null},{"captures":[],"board":"100111110222110221210011221121221222","result":null},{"captures":[],"board":"110111110222110221210011221121221222","result":null},{"captures":[[3,1],[4,2]],"board":"110111110222110221202011220121221222","result":"winner: blue"}]}],"evalPositions":[{"game":0,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":0,"cut":2,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":0,"cut":3,"features":{"empty":6,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":1.0},"location":{"red":4.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":9.0},{"game":0,"cut":5,"features":{"empty":4,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":3.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":12.0},{"game":0,"cut":6,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":3.0},"location":{"red":2.0,"blue":5.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":2.0}},"eval":-5.5},{"game":1,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":1,"cut":2,"features":{"empty":14,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":7.0},{"game":1,"cut":5,"features":{"empty":11,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":11.5},{"game":1,"cut":8,"features":{"empty":10,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":4.0},"location":{"red":4.0,"blue":8.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":3.0}},"eval":-2.0},{"game":1,"cut":15,"features":{"empty":7,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":6.0,"blue":3.0},"location":{"red":12.0,"blue":6.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":5.0,"blue":2.0}},"eval":39.5},{"game":1,"cut":16,"features":{"empty":6,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":6.0,"blue":4.0},"location":{"red":12.0,"blue":8.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":5.0,"blue":0.0}},"eval":21.0},{"game":2,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":2,"cut":2,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":11.5},{"game":2,"cut":6,"features":{"empty":19,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":3.0},"location":{"red":9.0,"blue":9.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":3.0}},"eval":12.5},{"game":2,"cut":9,"features":{"empty":16,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":5.0,"blue":4.0},"location":{"red":15.0,"blue":12.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":3.0}},"eval":22.0},{"game":2,"cut":18,"features":{"empty":9,"triangle":{"red":8.0,"blue":4.0},"tokens":{"red":9.0,"blue":7.0},"location":{"red":25.0,"blue":21.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":6.0,"blue":0.0}},"eval":22.5},{"game":2,"cut":19,"features":{"empty":8,"triangle":{"red":8.0,"blue":4.0},"tokens":{"red":10.0,"blue":7.0},"location":{"red":28.0,"blue":21.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":8.0,"blue":0.0}},"eval":30.0},{"game":3,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":3,"cut":2,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":3,"cut":5,"features":{"empty":32,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":6.0,"blue":6.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":3,"cut":8,"features":{"empty":29,"triangle":{"red":0.0,"blue":4.0},"tokens":{"red":3.0,"blue":4.0},"location":{"red":8.0,"blue":12.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-25.5},{"game":3,"cut":15,"features":{"empty":24,"triangle":{"red":0.0,"blue":4.0},"tokens":{"red":5.0,"blue":7.0},"location":{"red":14.0,"blue":20.0},"diamond":{"red":5.0,"blue":4.0},"weakness":{"red":0.0,"blue":2.0}},"eval":-26.0},{"game":3,"cut":16,"features":{"empty":23,"triangle":{"red":0.0,"blue":4.0},"tokens":{"red":5.0,"blue":8.0},"location":{"red":14.0,"blue":23.0},"diamond":{"red":5.0,"blue":5.0},"weakness":{"red":0.0,"blue":3.0}},"eval":-33.5},{"game":4,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":40.0},{"game":4,"cut":2,"features":{"empty":47,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":4.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":25.5},{"game":4,"cut":17,"features":{"empty":34,"triangle":{"red":4.0,"blue":0.0},"tokens":{"red":9.0,"blue":6.0},"location":{"red":31.0,"blue":23.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":7.0,"blue":5.0}},"eval":55.0},{"game":4,"cut":26,"features":{"empty":27,"triangle":{"red":6.0,"blue":3.0},"tokens":{"red":11.0,"blue":11.0},"location":{"red":41.0,"blue":41.0},"diamond":{"red":4.0,"blue":8.0},"weakness":{"red":2.0,"blue":8.0}},"eval":56.5},{"game":4,"cut":52,"features":{"empty":14,"triangle":{"red":12.0,"blue":7.0},"tokens":{"red":20.0,"blue":15.0},"location":{"red":74.0,"blue":58.0},"diamond":{"red":6.0,"blue":5.0},"weakness":{"red":11.0,"blue":3.0}},"eval":66.0},{"game":4,"cut":53,"features":{"empty":13,"triangle":{"red":12.0,"blue":7.0},"tokens":{"red":21.0,"blue":15.0},"location":{"red":78.0,"blue":58.0},"diamond":{"red":6.0,"blue":5.0},"weakness":{"red":12.0,"blue":3.0}},"eval":78.5},{"game":5,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":47.5},{"game":5,"cut":2,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":15.5},{"game":5,"cut":23,"features":{"empty":44,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":11.0,"blue":9.0},"location":{"red":38.0,"blue":33.0},"diamond":{"red":6.0,"blue":6.0},"weakness":{"red":8.0,"blue":4.0}},"eval":45.0},{"game":5,"cut":34,"features":{"empty":33,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":16.0,"blue":15.0},"location":{"red":57.0,"blue":55.0},"diamond":{"red":11.0,"blue":9.0},"weakness":{"red":11.0,"blue":9.0}},"eval":23.5},{"game":5,"cut":68,"features":{"empty":21,"triangle":{"red":4.0,"blue":11.0},"tokens":{"red":23.0,"blue":20.0},"location":{"red":89.0,"blue":72.0},"diamond":{"red":7.0,"blue":6.0},"weakness":{"red":12.0,"blue":9.0}},"eval":34.5},{"game":5,"cut":69,"features":{"empty":20,"triangle":{"red":4.0,"blue":11.0},"tokens":{"red":24.0,"blue":20.0},"location":{"red":93.0,"blue":72.0},"diamond":{"red":9.0,"blue":6.0},"weakness":{"red":12.0,"blue":9.0}},"eval":42.0},{"game":6,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":6,"cut":2,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":6,"cut":4,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":2.5},{"game":6,"cut":7,"features":{"empty":2,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":3.0},"location":{"red":7.0,"blue":6.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-1.0},{"game":6,"cut":8,"features":{"empty":1,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":7.0,"blue":8.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-13.5},{"game":7,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":7,"cut":2,"features":{"empty":14,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":7.0},{"game":7,"cut":5,"features":{"empty":11,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":4.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":3.0,"blue":0.0}},"eval":8.5},{"game":7,"cut":7,"features":{"empty":11,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":1.0},"location":{"red":8.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":4.0,"blue":0.0}},"eval":29.5},{"game":7,"cut":14,"features":{"empty":6,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":5.0,"blue":5.0},"location":{"red":10.0,"blue":10.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":4.0,"blue":5.0}},"eval":15.0},{"game":7,"cut":15,"features":{"empty":5,"triangle":{"red":5.0,"blue":0.0},"tokens":{"red":6.0,"blue":5.0},"location":{"red":12.0,"blue":10.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":3.0}},"eval":29.5},{"game":8,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":8,"cut":2,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-2.0},{"game":8,"cut":10,"features":{"empty":16,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":4.0,"blue":5.0},"location":{"red":12.0,"blue":15.0},"diamond":{"red":0.0,"blue":3.0},"weakness":{"red":2.0,"blue":2.0}},"eval":15.0},{"game":8,"cut":15,"features":{"empty":11,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":7.0,"blue":7.0},"location":{"red":21.0,"blue":19.0},"diamond":{"red":4.0,"blue":7.0},"weakness":{"red":2.0,"blue":4.0}},"eval":36.5},{"game":8,"cut":30,"features":{"empty":5,"triangle":{"red":3.0,"blue":11.0},"tokens":{"red":7.0,"blue":13.0},"location":{"red":21.0,"blue":37.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":4.0,"blue":4.0}},"eval":-101.5},{"game":8,"cut":31,"features":{"empty":4,"triangle":{"red":3.0,"blue":11.0},"tokens":{"red":8.0,"blue":13.0},"location":{"red":24.0,"blue":37.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":4.0}},"eval":-85.0},{"game":9,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":9,"cut":2,"features":{"empty":34,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":17.0},{"game":9,"cut":13,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":7.0,"blue":6.0},"location":{"red":21.0,"blue":18.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":2.0,"blue":2.0}},"eval":25.5},{"game":9,"cut":20,"features":{"empty":18,"triangle":{"red":3.0,"blue":3.0},"tokens":{"red":8.0,"blue":10.0},"location":{"red":23.0,"blue":29.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":2.0,"blue":5.0}},"eval":-10.0},{"game":9,"cut":40,"features":{"empty":5,"triangle":{"red":11.0,"blue":3.0},"tokens":{"red":18.0,"blue":13.0},"location":{"red":52.0,"blue":38.0},"diamond":{"red":8.0,"blue":6.0},"weakness":{"red":6.0,"blue":2.0}},"eval":74.5},{"game":9,"cut":41,"features":{"empty":7,"triangle":{"red":11.0,"blue":3.0},"tokens":{"red":19.0,"blue":10.0},"location":{"red":54.0,"blue":30.0},"diamond":{"red":5.0,"blue":0.0},"weakness":{"red":12.0,"blue":0.0}},"eval":91.5},{"game":10,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":40.0},{"game":10,"cut":2,"features":{"empty":47,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":23.5},{"game":10,"cut":10,"features":{"empty":39,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":5.0,"blue":5.0},"location":{"red":19.0,"blue":17.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":4.0,"blue":4.0}},"eval":31.5},{"game":10,"cut":15,"features":{"empty":34,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":8.0,"blue":7.0},"location":{"red":30.0,"blue":25.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":5.0,"blue":6.0}},"eval":47.0},{"game":10,"cut":30,"features":{"empty":23,"triangle":{"red":3.0,"blue":5.0},"tokens":{"red":13.0,"blue":13.0},"location":{"red":50.0,"blue":47.0},"diamond":{"red":4.0,"blue":7.0},"weakness":{"red":6.0,"blue":6.0}},"eval":23.5},{"game":10,"cut":31,"features":{"empty":22,"triangle":{"red":3.0,"blue":5.0},"tokens":{"red":14.0,"blue":13.0},"location":{"red":54.0,"blue":47.0},"diamond":{"red":4.0,"blue":7.0},"weakness":{"red":6.0,"blue":6.0}},"eval":39.0},{"game":11,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":43.5},{"game":11,"cut":2,"features":{"empty":62,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":29.0},{"game":11,"cut":25,"features":{"empty":41,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":13.0,"blue":10.0},"location":{"red":47.0,"blue":35.0},"diamond":{"red":7.0,"blue":5.0},"weakness":{"red":8.0,"blue":9.0}},"eval":72.5},{"game":11,"cut":37,"features":{"empty":31,"triangle":{"red":7.0,"blue":4.0},"tokens":{"red":19.0,"blue":14.0},"location":{"red":71.0,"blue":52.0},"diamond":{"red":4.0,"blue":6.0},"weakness":{"red":11.0,"blue":7.0}},"eval":98.5},{"game":11,"cut":74,"features":{"empty":10,"triangle":{"red":20.0,"blue":20.0},"tokens":{"red":29.0,"blue":25.0},"location":{"red":108.0,"blue":91.0},"diamond":{"red":6.0,"blue":12.0},"weakness":{"red":8.0,"blue":10.0}},"eval":101.0},{"game":11,"cut":75,"features":{"empty":11,"triangle":{"red":20.0,"blue":19.0},"tokens":{"red":30.0,"blue":23.0},"location":{"red":112.0,"blue":83.0},"diamond":{"red":6.0,"blue":10.0},"weakness":{"red":9.0,"blue":6.0}},"eval":129.5},{"game":12,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":12,"cut":2,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":12,"cut":3,"features":{"empty":6,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":1.0},"location":{"red":4.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":15.0},{"game":12,"cut":5,"features":{"empty":4,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":3.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":12,"cut":10,"features":{"empty":1,"triangle":{"red":0.0,"blue":5.0},"tokens":{"red":3.0,"blue":5.0},"location":{"red":6.0,"blue":9.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-36.5},{"game":12,"cut":11,"features":{"empty":0,"triangle":{"red":0.0,"blue":5.0},"tokens":{"red":4.0,"blue":5.0},"location":{"red":8.0,"blue":9.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-25.0},{"game":13,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":13,"cut":2,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-4.5},{"game":13,"cut":5,"features":{"empty":12,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":6.0},{"game":13,"cut":8,"features":{"empty":11,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":0.0}},"eval":8.5},{"game":13,"cut":16,"features":{"empty":5,"triangle":{"red":5.0,"blue":0.0},"tokens":{"red":7.0,"blue":4.0},"location":{"red":14.0,"blue":8.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":53.5},{"game":13,"cut":17,"features":{"empty":4,"triangle":{"red":5.0,"blue":0.0},"tokens":{"red":8.0,"blue":4.0},"location":{"red":16.0,"blue":8.0},"diamond":{"red":4.0,"blue":2.0},"weakness":{"red":2.0,"blue":0.0}},"eval":51.0},{"game":14,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":14,"cut":2,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":11.5},{"game":14,"cut":8,"features":{"empty":17,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":12.0,"blue":12.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":2.0}},"eval":22.5},{"game":14,"cut":13,"features":{"empty":12,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":7.0,"blue":6.0},"location":{"red":21.0,"blue":18.0},"diamond":{"red":2.0,"blue":4.0},"weakness":{"red":4.0,"blue":2.0}},"eval":22.0},{"game":14,"cut":25,"features":{"empty":4,"triangle":{"red":0.0,"blue":8.0},"tokens":{"red":11.0,"blue":10.0},"location":{"red":33.0,"blue":28.0},"diamond":{"red":5.0,"blue":5.0},"weakness":{"red":7.0,"blue":6.0}},"eval":-7.0},{"game":14,"cut":26,"features":{"empty":3,"triangle":{"red":0.0,"blue":10.0},"tokens":{"red":11.0,"blue":11.0},"location":{"red":33.0,"blue":31.0},"diamond":{"red":5.0,"blue":2.0},"weakness":{"red":6.0,"blue":2.0}},"eval":-48.5},{"game":15,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":15,"cut":2,"features":{"empty":34,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":17.0},{"game":15,"cut":12,"features":{"empty":24,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":6.0,"blue":6.0},"location":{"red":17.0,"blue":17.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":2.0,"blue":4.0}},"eval":27.0},{"game":15,"cut":19,"features":{"empty":17,"triangle":{"red":6.0,"blue":0.0},"tokens":{"red":10.0,"blue":9.0},"location":{"red":29.0,"blue":25.0},"diamond":{"red":4.0,"blue":6.0},"weakness":{"red":2.0,"blue":8.0}},"eval":68.5},{"game":15,"cut":37,"features":{"empty":5,"triangle":{"red":6.0,"blue":11.0},"tokens":{"red":17.0,"blue":14.0},"location":{"red":49.0,"blue":41.0},"diamond":{"red":8.0,"blue":2.0},"weakness":{"red":2.0,"blue":3.0}},"eval":6.5},{"game":15,"cut":38,"features":{"empty":6,"triangle":{"red":5.0,"blue":11.0},"tokens":{"red":15.0,"blue":15.0},"location":{"red":44.0,"blue":43.0},"diamond":{"red":5.0,"blue":4.0},"weakness":{"red":2.0,"blue":4.0}},"eval":-11.0},{"game":16,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":38.0},{"game":16,"cut":2,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":10.0},{"game":16,"cut":22,"features":{"empty":30,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":8.0,"blue":11.0},"location":{"red":31.0,"blue":40.0},"diamond":{"red":4.0,"blue":3.0},"weakness":{"red":6.0,"blue":9.0}},"eval":-31.0},{"game":16,"cut":33,"features":{"empty":21,"triangle":{"red":6.0,"blue":7.0},"tokens":{"red":14.0,"blue":14.0},"location":{"red":54.0,"blue":49.0},"diamond":{"red":5.0,"blue":5.0},"weakness":{"red":7.0,"blue":7.0}},"eval":17.5},{"game":16,"cut":65,"features":{"empty":9,"triangle":{"red":17.0,"blue":16.0},"tokens":{"red":20.0,"blue":20.0},"location":{"red":75.0,"blue":74.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":8.0,"blue":4.0}},"eval":-2.5},{"game":16,"cut":66,"features":{"empty":8,"triangle":{"red":17.0,"blue":16.0},"tokens":{"red":20.0,"blue":21.0},"location":{"red":75.0,"blue":78.0},"diamond":{"red":2.0,"blue":4.0},"weakness":{"red":8.0,"blue":4.0}},"eval":-11.0},{"game":17,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":47.5},{"game":17,"cut":2,"features":{"empty":62,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.0},{"game":17,"cut":27,"features":{"empty":41,"triangle":{"red":5.0,"blue":0.0},"tokens":{"red":12.0,"blue":11.0},"location":{"red":47.0,"blue":41.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":4.0,"blue":9.0}},"eval":66.5},{"game":17,"cut":41,"features":{"empty":27,"triangle":{"red":6.0,"blue":6.0},"tokens":{"red":19.0,"blue":18.0},"location":{"red":74.0,"blue":67.0},"diamond":{"red":4.0,"blue":13.0},"weakness":{"red":6.0,"blue":10.0}},"eval":83.5},{"game":17,"cut":82,"features":{"empty":10,"triangle":{"red":20.0,"blue":17.0},"tokens":{"red":31.0,"blue":23.0},"location":{"red":120.0,"blue":84.0},"diamond":{"red":10.0,"blue":0.0},"weakness":{"red":8.0,"blue":6.0}},"eval":104.0},{"game":17,"cut":83,"features":{"empty":9,"triangle":{"red":23.0,"blue":17.0},"tokens":{"red":32.0,"blue":23.0},"location":{"red":123.0,"blue":84.0},"diamond":{"red":7.0,"blue":0.0},"weakness":{"red":5.0,"blue":4.0}},"eval":141.5},{"game":18,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":18,"cut":2,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-8.0},{"game":18,"cut":3,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":18,"cut":4,"features":{"empty":6,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":2.0},"location":{"red":2.0,"blue":4.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-1.0},{"game":18,"cut":8,"features":{"empty":4,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":5.0,"blue":4.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":4.0},{"game":18,"cut":9,"features":{"empty":3,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":2.0},"location":{"red":7.0,"blue":4.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":11.5},{"game":19,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":19,"cut":2,"features":{"empty":14,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":7.0},{"game":19,"cut":4,"features":{"empty":12,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":6.0},{"game":19,"cut":6,"features":{"empty":10,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":3.0},"location":{"red":6.0,"blue":6.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":1.0},{"game":19,"cut":12,"features":{"empty":6,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":4.0,"blue":6.0},"location":{"red":8.0,"blue":12.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":3.0}},"eval":-13.0},{"game":19,"cut":13,"features":{"empty":5,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":5.0,"blue":6.0},"location":{"red":10.0,"blue":12.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":3.0}},"eval":-1.5},{"game":20,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":20,"cut":2,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-2.0},{"game":20,"cut":9,"features":{"empty":17,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":10.0,"blue":12.0},"diamond":{"red":3.0,"blue":3.0},"weakness":{"red":0.0,"blue":0.0}},"eval":4.5},{"game":20,"cut":14,"features":{"empty":12,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":6.0,"blue":7.0},"location":{"red":16.0,"blue":21.0},"diamond":{"red":4.0,"blue":4.0},"weakness":{"red":2.0,"blue":6.0}},"eval":0.0},{"game":20,"cut":28,"features":{"empty":4,"triangle":{"red":5.0,"blue":3.0},"tokens":{"red":11.0,"blue":10.0},"location":{"red":31.0,"blue":30.0},"diamond":{"red":5.0,"blue":3.0},"weakness":{"red":4.0,"blue":0.0}},"eval":-2.0},{"game":20,"cut":29,"features":{"empty":5,"triangle":{"red":8.0,"blue":3.0},"tokens":{"red":12.0,"blue":8.0},"location":{"red":34.0,"blue":24.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":6.0,"blue":0.0}},"eval":51.5},{"game":21,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":21,"cut":2,"features":{"empty":34,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":17.0},{"game":21,"cut":10,"features":{"empty":28,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":5.0},"location":{"red":9.0,"blue":14.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":3.0,"blue":2.0}},"eval":-15.0},{"game":21,"cut":15,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":6.0,"blue":7.0},"location":{"red":18.0,"blue":19.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":3.0,"blue":3.0}},"eval":1.5},{"game":21,"cut":30,"features":{"empty":10,"triangle":{"red":3.0,"blue":13.0},"tokens":{"red":11.0,"blue":15.0},"location":{"red":33.0,"blue":41.0},"diamond":{"red":4.0,"blue":4.0},"weakness":{"red":0.0,"blue":5.0}},"eval":-58.0},{"game":21,"cut":31,"features":{"empty":9,"triangle":{"red":3.0,"blue":13.0},"tokens":{"red":12.0,"blue":15.0},"location":{"red":36.0,"blue":41.0},"diamond":{"red":4.0,"blue":4.0},"weakness":{"red":2.0,"blue":5.0}},"eval":-50.5},{"game":22,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":38.0},{"game":22,"cut":2,"features":{"empty":47,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":21.5},{"game":22,"cut":23,"features":{"empty":26,"triangle":{"red":4.0,"blue":3.0},"tokens":{"red":12.0,"blue":11.0},"location":{"red":45.0,"blue":41.0},"diamond":{"red":8.0,"blue":4.0},"weakness":{"red":5.0,"blue":9.0}},"eval":28.0},{"game":22,"cut":35,"features":{"empty":19,"triangle":{"red":7.0,"blue":8.0},"tokens":{"red":15.0,"blue":15.0},"location":{"red":57.0,"blue":54.0},"diamond":{"red":5.0,"blue":6.0},"weakness":{"red":9.0,"blue":8.0}},"eval":13.5},{"game":22,"cut":69,"features":{"empty":1,"triangle":{"red":21.0,"blue":19.0},"tokens":{"red":26.0,"blue":22.0},"location":{"red":98.0,"blue":83.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":68.5},{"game":22,"cut":70,"features":{"empty":2,"triangle":{"red":20.0,"blue":19.0},"tokens":{"red":24.0,"blue":23.0},"location":{"red":90.0,"blue":87.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":4.0}},"eval":30.0},{"game":23,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":45.5},{"game":23,"cut":2,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":17.5},{"game":23,"cut":20,"features":{"empty":47,"triangle":{"red":3.0,"blue":3.0},"tokens":{"red":7.0,"blue":10.0},"location":{"red":28.0,"blue":39.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":5.0,"blue":6.0}},"eval":-27.5},{"game":23,"cut":30,"features":{"empty":40,"triangle":{"red":6.0,"blue":3.0},"tokens":{"red":12.0,"blue":12.0},"location":{"red":45.0,"blue":44.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":8.0,"blue":5.0}},"eval":18.0},{"game":23,"cut":59,"features":{"empty":18,"triangle":{"red":9.0,"blue":13.0},"tokens":{"red":20.0,"blue":26.0},"location":{"red":77.0,"blue":95.0},"diamond":{"red":5.0,"blue":11.0},"weakness":{"red":7.0,"blue":10.0}},"eval":-54.0},{"game":23,"cut":60,"features":{"empty":17,"triangle":{"red":9.0,"blue":15.0},"tokens":{"red":20.0,"blue":27.0},"location":{"red":77.0,"blue":97.0},"diamond":{"red":5.0,"blue":11.0},"weakness":{"red":7.0,"blue":11.0}},"eval":-69.5},{"game":24,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":24,"cut":2,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":1.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":5.5},{"game":24,"cut":4,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":4.0,"blue":3.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":4.5},{"game":24,"cut":6,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":1.0},"location":{"red":6.0,"blue":2.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":3.0,"blue":0.0}},"eval":9.5},{"game":24,"cut":11,"features":{"empty":2,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":3.0},"location":{"red":8.0,"blue":5.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":2.0,"blue":0.0}},"eval":9.0},{"game":24,"cut":12,"features":{"empty":3,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":4.0},"location":{"red":4.0,"blue":7.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":3.0}},"eval":-17.5},{"game":25,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":25,"cut":2,"features":{"empty":14,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":7.0},{"game":25,"cut":5,"features":{"empty":11,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":6.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":11.5},{"game":25,"cut":7,"features":{"empty":9,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":3.0},"location":{"red":8.0,"blue":6.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":0.0}},"eval":7.5},{"game":25,"cut":14,"features":{"empty":2,"triangle":{"red":3.0,"blue":4.0},"tokens":{"red":7.0,"blue":7.0},"location":{"red":14.0,"blue":14.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":2.0,"blue":3.0}},"eval":9.0},{"game":25,"cut":15,"features":{"empty":1,"triangle":{"red":3.0,"blue":4.0},"tokens":{"red":8.0,"blue":7.0},"location":{"red":16.0,"blue":14.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":2.0,"blue":2.0}},"eval":5.5},{"game":26,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":26,"cut":2,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":11.5},{"game":26,"cut":8,"features":{"empty":17,"triangle":{"red":4.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":12.0,"blue":12.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":3.0}},"eval":37.5},{"game":26,"cut":12,"features":{"empty":15,"triangle":{"red":5.0,"blue":0.0},"tokens":{"red":6.0,"blue":4.0},"location":{"red":16.0,"blue":12.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":3.0,"blue":2.0}},"eval":43.5},{"game":26,"cut":24,"features":{"empty":5,"triangle":{"red":5.0,"blue":3.0},"tokens":{"red":10.0,"blue":10.0},"location":{"red":28.0,"blue":30.0},"diamond":{"red":4.0,"blue":6.0},"weakness":{"red":2.0,"blue":5.0}},"eval":21.5},{"game":26,"cut":25,"features":{"empty":4,"triangle":{"red":5.0,"blue":3.0},"tokens":{"red":11.0,"blue":10.0},"location":{"red":31.0,"blue":30.0},"diamond":{"red":6.0,"blue":6.0},"weakness":{"red":2.0,"blue":5.0}},"eval":27.0},{"game":27,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":27,"cut":2,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":27,"cut":15,"features":{"empty":24,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":7.0,"blue":5.0},"location":{"red":20.0,"blue":14.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":4.0,"blue":2.0}},"eval":31.0},{"game":27,"cut":23,"features":{"empty":20,"triangle":{"red":3.0,"blue":3.0},"tokens":{"red":7.0,"blue":9.0},"location":{"red":20.0,"blue":26.0},"diamond":{"red":3.0,"blue":2.0},"weakness":{"red":4.0,"blue":7.0}},"eval":-13.0},{"game":27,"cut":46,"features":{"empty":7,"triangle":{"red":8.0,"blue":7.0},"tokens":{"red":16.0,"blue":13.0},"location":{"red":47.0,"blue":37.0},"diamond":{"red":9.0,"blue":3.0},"weakness":{"red":7.0,"blue":2.0}},"eval":11.5},{"game":27,"cut":47,"features":{"empty":6,"triangle":{"red":10.0,"blue":7.0},"tokens":{"red":17.0,"blue":13.0},"location":{"red":50.0,"blue":37.0},"diamond":{"red":7.0,"blue":3.0},"weakness":{"red":6.0,"blue":2.0}},"eval":42.0},{"game":28,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":40.0},{"game":28,"cut":2,"features":{"empty":47,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":23.5},{"game":28,"cut":19,"features":{"empty":37,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":8.0,"blue":4.0},"location":{"red":30.0,"blue":15.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":6.0,"blue":3.0}},"eval":71.5},{"game":28,"cut":29,"features":{"empty":27,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":13.0,"blue":9.0},"location":{"red":49.0,"blue":34.0},"diamond":{"red":7.0,"blue":2.0},"weakness":{"red":9.0,"blue":2.0}},"eval":25.5},{"game":28,"cut":57,"features":{"empty":5,"triangle":{"red":17.0,"blue":9.0},"tokens":{"red":25.0,"blue":19.0},"location":{"red":98.0,"blue":68.0},"diamond":{"red":9.0,"blue":8.0},"weakness":{"red":9.0,"blue":6.0}},"eval":121.5},{"game":28,"cut":58,"features":{"empty":8,"triangle":{"red":12.0,"blue":9.0},"tokens":{"red":21.0,"blue":20.0},"location":{"red":83.0,"blue":72.0},"diamond":{"red":6.0,"blue":8.0},"weakness":{"red":5.0,"blue":7.0}},"eval":57.0},{"game":29,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":45.5},{"game":29,"cut":2,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":17.5},{"game":29,"cut":27,"features":{"empty":42,"triangle":{"red":0.0,"blue":5.0},"tokens":{"red":9.0,"blue":13.0},"location":{"red":32.0,"blue":48.0},"diamond":{"red":6.0,"blue":3.0},"weakness":{"red":7.0,"blue":7.0}},"eval":-70.0},{"game":29,"cut":41,"features":{"empty":35,"triangle":{"red":4.0,"blue":0.0},"tokens":{"red":16.0,"blue":13.0},"location":{"red":57.0,"blue":50.0},"diamond":{"red":10.0,"blue":5.0},"weakness":{"red":11.0,"blue":8.0}},"eval":38.5},{"game":29,"cut":81,"features":{"empty":18,"triangle":{"red":15.0,"blue":15.0},"tokens":{"red":23.0,"blue":23.0},"location":{"red":82.0,"blue":87.0},"diamond":{"red":4.0,"blue":10.0},"weakness":{"red":3.0,"blue":14.0}},"eval":56.0},{"game":29,"cut":82,"features":{"empty":17,"triangle":{"red":15.0,"blue":16.0},"tokens":{"red":23.0,"blue":24.0},"location":{"red":82.0,"blue":90.0},"diamond":{"red":4.0,"blue":12.0},"weakness":{"red":3.0,"blue":13.0}},"eval":43.5},{"game":30,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":30,"cut":2,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-8.0},{"game":30,"cut":3,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":1.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":1.5},{"game":30,"cut":5,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":3.0,"blue":4.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":0.5},{"game":30,"cut":9,"features":{"empty":1,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":7.0,"blue":8.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":-6.5},{"game":30,"cut":10,"features":{"empty":2,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":5.0},"location":{"red":4.0,"blue":10.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":3.0}},"eval":-26.0},{"game":31,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":31,"cut":2,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-4.5},{"game":31,"cut":5,"features":{"empty":12,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":4.0,"blue":4.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":14.0},{"game":31,"cut":8,"features":{"empty":9,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":3.0,"blue":4.0},"location":{"red":6.0,"blue":8.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":2.0}},"eval":-10.5},{"game":31,"cut":15,"features":{"empty":4,"triangle":{"red":3.0,"blue":7.0},"tokens":{"red":5.0,"blue":7.0},"location":{"red":10.0,"blue":14.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-26.0},{"game":31,"cut":16,"features":{"empty":3,"triangle":{"red":3.0,"blue":7.0},"tokens":{"red":5.0,"blue":8.0},"location":{"red":10.0,"blue":16.0},"diamond":{"red":0.0,"blue":4.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-30.5},{"game":32,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":32,"cut":2,"features":{"empty":23,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":11.5},{"game":32,"cut":5,"features":{"empty":20,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":2.0},"location":{"red":9.0,"blue":6.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":2.0,"blue":2.0}},"eval":16.0},{"game":32,"cut":7,"features":{"empty":18,"triangle":{"red":3.0,"blue":3.0},"tokens":{"red":4.0,"blue":3.0},"location":{"red":12.0,"blue":7.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":13.0},{"game":32,"cut":14,"features":{"empty":11,"triangle":{"red":4.0,"blue":5.0},"tokens":{"red":7.0,"blue":7.0},"location":{"red":21.0,"blue":19.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":2.0,"blue":0.0}},"eval":8.5},{"game":32,"cut":15,"features":{"empty":10,"triangle":{"red":4.0,"blue":5.0},"tokens":{"red":8.0,"blue":7.0},"location":{"red":24.0,"blue":19.0},"diamond":{"red":2.0,"blue":2.0},"weakness":{"red":2.0,"blue":0.0}},"eval":14.0},{"game":33,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":29.5},{"game":33,"cut":2,"features":{"empty":34,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":15.0},{"game":33,"cut":7,"features":{"empty":29,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":4.0,"blue":3.0},"location":{"red":11.0,"blue":9.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":4.0,"blue":3.0}},"eval":23.5},{"game":33,"cut":10,"features":{"empty":26,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":5.0,"blue":5.0},"location":{"red":14.0,"blue":15.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":4.0,"blue":5.0}},"eval":22.0},{"game":33,"cut":20,"features":{"empty":16,"triangle":{"red":3.0,"blue":7.0},"tokens":{"red":10.0,"blue":10.0},"location":{"red":29.0,"blue":28.0},"diamond":{"red":6.0,"blue":5.0},"weakness":{"red":7.0,"blue":6.0}},"eval":-9.0},{"game":33,"cut":21,"features":{"empty":17,"triangle":{"red":3.0,"blue":6.0},"tokens":{"red":11.0,"blue":8.0},"location":{"red":32.0,"blue":22.0},"diamond":{"red":5.0,"blue":2.0},"weakness":{"red":8.0,"blue":4.0}},"eval":19.5},{"game":34,"cut":1,"features":{"empty":48,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":38.0},{"game":34,"cut":2,"features":{"empty":47,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":3.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":21.5},{"game":34,"cut":17,"features":{"empty":32,"triangle":{"red":0.0,"blue":3.0},"tokens":{"red":9.0,"blue":8.0},"location":{"red":34.0,"blue":27.0},"diamond":{"red":4.0,"blue":4.0},"weakness":{"red":5.0,"blue":2.0}},"eval":20.0},{"game":34,"cut":26,"features":{"empty":23,"triangle":{"red":3.0,"blue":6.0},"tokens":{"red":13.0,"blue":13.0},"location":{"red":50.0,"blue":46.0},"diamond":{"red":7.0,"blue":8.0},"weakness":{"red":6.0,"blue":8.0}},"eval":20.5},{"game":34,"cut":51,"features":{"empty":13,"triangle":{"red":10.0,"blue":8.0},"tokens":{"red":17.0,"blue":19.0},"location":{"red":65.0,"blue":72.0},"diamond":{"red":5.0,"blue":11.0},"weakness":{"red":3.0,"blue":13.0}},"eval":36.5},{"game":34,"cut":52,"features":{"empty":14,"triangle":{"red":10.0,"blue":10.0},"tokens":{"red":15.0,"blue":20.0},"location":{"red":58.0,"blue":76.0},"diamond":{"red":2.0,"blue":8.0},"weakness":{"red":3.0,"blue":13.0}},"eval":-15.0},{"game":35,"cut":1,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":4.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":47.5},{"game":35,"cut":2,"features":{"empty":63,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":15.5},{"game":35,"cut":23,"features":{"empty":42,"triangle":{"red":3.0,"blue":7.0},"tokens":{"red":11.0,"blue":11.0},"location":{"red":38.0,"blue":41.0},"diamond":{"red":5.0,"blue":4.0},"weakness":{"red":5.0,"blue":2.0}},"eval":-10.0},{"game":35,"cut":35,"features":{"empty":30,"triangle":{"red":6.0,"blue":7.0},"tokens":{"red":17.0,"blue":17.0},"location":{"red":62.0,"blue":63.0},"diamond":{"red":7.0,"blue":11.0},"weakness":{"red":10.0,"blue":5.0}},"eval":11.0},{"game":35,"cut":70,"features":{"empty":17,"triangle":{"red":15.0,"blue":16.0},"tokens":{"red":23.0,"blue":24.0},"location":{"red":88.0,"blue":87.0},"diamond":{"red":5.0,"blue":0.0},"weakness":{"red":6.0,"blue":10.0}},"eval":-8.5},{"game":35,"cut":71,"features":{"empty":16,"triangle":{"red":19.0,"blue":16.0},"tokens":{"red":24.0,"blue":24.0},"location":{"red":92.0,"blue":87.0},"diamond":{"red":5.0,"blue":0.0},"weakness":{"red":5.0,"blue":10.0}},"eval":22.0},{"game":36,"cut":1,"features":{"empty":8,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":16.0},{"game":36,"cut":2,"features":{"empty":7,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":1.0},"location":{"red":2.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":36,"cut":3,"features":{"empty":6,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":1.0},"location":{"red":3.0,"blue":2.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":5.0},{"game":36,"cut":4,"features":{"empty":5,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":2.0},"location":{"red":3.0,"blue":4.0},"diamond":{"red":2.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-7.5},{"game":36,"cut":8,"features":{"empty":1,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":4.0,"blue":4.0},"location":{"red":7.0,"blue":8.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":0.0,"blue":2.0}},"eval":21.5},{"game":36,"cut":9,"features":{"empty":2,"triangle":{"red":3.0,"blue":0.0},"tokens":{"red":5.0,"blue":2.0},"location":{"red":9.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":2.0,"blue":0.0}},"eval":38.0},{"game":37,"cut":1,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":2.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":19.5},{"game":37,"cut":2,"features":{"empty":15,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":2.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-4.5},{"game":37,"cut":4,"features":{"empty":13,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":2.0},"location":{"red":2.0,"blue":4.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":2.0}},"eval":0.5},{"game":37,"cut":7,"features":{"empty":10,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":3.0},"location":{"red":6.0,"blue":6.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":3.0}},"eval":14.0},{"game":37,"cut":8,"features":{"empty":9,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":3.0,"blue":4.0},"location":{"red":6.0,"blue":8.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":4.0}},"eval":4.5},{"game":38,"cut":1,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":26.0},{"game":38,"cut":2,"features":{"empty":24,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":-2.0},{"game":38,"cut":10,"features":{"empty":20,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":2.0,"blue":3.0},"location":{"red":6.0,"blue":9.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":2.0}},"eval":2.0},{"game":38,"cut":16,"features":{"empty":14,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":5.0,"blue":6.0},"location":{"red":15.0,"blue":18.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":2.0,"blue":5.0}},"eval":10.0},{"game":38,"cut":31,"features":{"empty":7,"triangle":{"red":6.0,"blue":6.0},"tokens":{"red":9.0,"blue":9.0},"location":{"red":27.0,"blue":27.0},"diamond":{"red":0.0,"blue":2.0},"weakness":{"red":2.0,"blue":5.0}},"eval":20.5},{"game":38,"cut":32,"features":{"empty":6,"triangle":{"red":6.0,"blue":6.0},"tokens":{"red":9.0,"blue":10.0},"location":{"red":27.0,"blue":30.0},"diamond":{"red":0.0,"blue":3.0},"weakness":{"red":2.0,"blue":5.0}},"eval":10.0},{"game":39,"cut":1,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":1.0,"blue":0.0},"location":{"red":3.0,"blue":0.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":31.5},{"game":39,"cut":2,"features":{"empty":35,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":0.0,"blue":1.0},"location":{"red":0.0,"blue":3.0},"diamond":{"red":0.0,"blue":0.0},"weakness":{"red":0.0,"blue":0.0}},"eval":3.5},{"game":39,"cut":18,"features":{"empty":21,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":6.0,"blue":9.0},"location":{"red":17.0,"blue":26.0},"diamond":{"red":2.0,"blue":7.0},"weakness":{"red":2.0,"blue":5.0}},"eval":-2.5},{"game":39,"cut":27,"features":{"empty":16,"triangle":{"red":0.0,"blue":0.0},"tokens":{"red":11.0,"blue":9.0},"location":{"red":32.0,"blue":26.0},"diamond":{"red":5.0,"blue":4.0},"weakness":{"red":8.0,"blue":8.0}},"eval":32.0},{"game":39,"cut":53,"features":{"empty":5,"triangle":{"red":12.0,"blue":12.0},"tokens":{"red":17.0,"blue":14.0},"location":{"red":51.0,"blue":41.0},"diamond":{"red":5.0,"blue":0.0},"weakness":{"red":4.0,"blue":2.0}},"eval":20.5},{"game":39,"cut":54,"features":{"empty":6,"triangle":{"red":9.0,"blue":12.0},"tokens":{"red":15.0,"blue":15.0},"location":{"red":45.0,"blue":43.0},"diamond":{"red":3.0,"blue":0.0},"weakness":{"red":4.0,"blue":4.0}},"eval":-14.0}],"minimax":[{"game":0,"cut":2,"depth":1,"maximizing":true,"score":15.0,"action":["PLACE",2,2]},{"game":0,"cut":2,"depth":2,"maximizing":true,"score":2.5,"action":["PLACE",2,2]},{"game":0,"cut":2,"depth":3,"maximizing":true,"score":23.0,"action":["PLACE",0,0]},{"game":0,"cut":3,"depth":1,"maximizing":false,"score":-5.5,"action":["PLACE",0,0]},{"game":0,"cut":3,"depth":2,"maximizing":false,"score":21.0,"action":["PLACE",0,0]},{"game":0,"cut":3,"depth":3,"maximizing":false,"score":8.5,"action":["PLACE",2,1]},{"game":1,"cut":2,"depth":1,"maximizing":true,"score":18.5,"action":["PLACE",3,3]},{"game":1,"cut":2,"depth":2,"maximizing":true,"score":6.0,"action":["PLACE",3,3]},{"game":1,"cut":2,"depth":3,"maximizing":true,"score":26.5,"action":["PLACE",1,0]},{"game":1,"cut":8,"depth":1,"maximizing":true,"score":18.5,"action":["PLACE",1,0]},{"game":1,"cut":8,"depth":2,"maximizing":true,"score":-8.0,"action":["PLACE",1,0]},{"game":1,"cut":8,"depth":3,"maximizing":true,"score":7.5,"action":["PLACE",2,1]},{"game":1,"cut":13,"depth":1,"maximizing":false,"score":-2.0,"action":["PLACE",1,2]},{"game":1,"cut":13,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",3,2]},{"game":1,"cut":13,"depth":3,"maximizing":false,"score":"-inf","action":["PLACE",3,2]},{"game":2,"cut":2,"depth":1,"maximizing":true,"score":25.0,"action":["PLACE",4,4]},{"game":2,"cut":2,"depth":2,"maximizing":true,"score":10.5,"action":["PLACE",4,4]},{"game":2,"cut":9,"depth":1,"maximizing":false,"score":-13.5,"action":["PLACE",2,0]},{"game":2,"cut":9,"depth":2,"maximizing":false,"score":24.0,"action":["PLACE",2,0]},{"game":2,"cut":16,"depth":1,"maximizing":true,"score":61.0,"action":["PLACE",1,3]},{"game":2,"cut":16,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",4,1]},{"game":2,"cut":16,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",4,1]},{"game":3,"cut":2,"depth":1,"maximizing":true,"score":17.0,"action":["PLACE",5,5]},{"game":3,"cut":2,"depth":2,"maximizing":true,"score":2.5,"action":["PLACE",5,5]},{"game":3,"cut":8,"depth":1,"maximizing":true,"score":1.0,"action":["PLACE",3,0]},{"game":3,"cut":8,"depth":2,"maximizing":true,"score":-28.5,"action":["PLACE",3,0]},{"game":3,"cut":13,"depth":1,"maximizing":false,"score":-49.5,"action":["PLACE",2,2]},{"game":3,"cut":13,"depth":2,"maximizing":false,"score":-28.0,"action":["PLACE",2,2]},{"game":4,"cut":2,"depth":1,"maximizing":true,"score":41.0,"action":["PLACE",6,6]},{"game":4,"cut":2,"depth":2,"maximizing":true,"score":24.5,"action":["PLACE",6,6]},{"game":4,"cut":26,"depth":1,"maximizing":true,"score":95.0,"action":["PLACE",2,6]},{"game":4,"cut":26,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",0,6]},{"game":4,"cut":50,"depth":1,"maximizing":true,"score":112.5,"action":["PLACE",2,3]},{"game":4,"cut":50,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",0,3]},{"game":4,"cut":50,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",0,3]},{"game":5,"cut":2,"depth":1,"maximizing":true,"score":31.0,"action":["PLACE",7,7]},{"game":5,"cut":2,"depth":2,"maximizing":true,"score":14.5,"action":["PLACE",7,7]},{"game":5,"cut":34,"depth":1,"maximizing":true,"score":85.5,"action":["PLACE",6,4]},{"game":5,"cut":34,"depth":2,"maximizing":true,"score":32.5,"action":["PLACE",6,4]},{"game":5,"cut":66,"depth":1,"maximizing":true,"score":42.0,"action":["PLACE",1,3]},{"game":5,"cut":66,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",0,6]},{"game":6,"cut":2,"depth":1,"maximizing":true,"score":15.0,"action":["PLACE",2,2]},{"game":6,"cut":2,"depth":2,"maximizing":true,"score":2.5,"action":["PLACE",2,2]},{"game":6,"cut":2,"depth":3,"maximizing":true,"score":14.0,"action":["PLACE",2,2]},{"game":6,"cut":4,"depth":1,"maximizing":true,"score":14.0,"action":["PLACE",2,2]},{"game":6,"cut":4,"depth":2,"maximizing":true,"score":-5.5,"action":["PLACE",2,2]},{"game":6,"cut":4,"depth":3,"maximizing":true,"score":6.0,"action":["PLACE",2,2]},{"game":6,"cut":5,"depth":1,"maximizing":false,"score":-12.5,"action":["PLACE",0,2]},{"game":6,"cut":5,"depth":2,"maximizing":false,"score":4.0,"action":["PLACE",0,2]},{"game":6,"cut":5,"depth":3,"maximizing":false,"score":-21.5,"action":["PLACE",0,2]},{"game":7,"cut":2,"depth":1,"maximizing":true,"score":18.5,"action":["PLACE",3,3]},{"game":7,"cut":2,"depth":2,"maximizing":true,"score":6.0,"action":["PLACE",3,3]},{"game":7,"cut":2,"depth":3,"maximizing":true,"score":26.5,"action":["PLACE",1,3]},{"game":7,"cut":7,"depth":1,"maximizing":false,"score":8.0,"action":["PLACE",0,2]},{"game":7,"cut":7,"depth":2,"maximizing":false,"score":41.5,"action":["PLACE",0,2]},{"game":7,"cut":7,"depth":3,"maximizing":false,"score":8.0,"action":["PLACE",1,3]},{"game":7,"cut":12,"depth":1,"maximizing":true,"score":45.5,"action":["PLACE",1,3]},{"game":7,"cut":12,"depth":2,"maximizing":true,"score":18.0,"action":["PLACE",1,3]},{"game":7,"cut":12,"depth":3,"maximizing":true,"score":16.0,"action":["PLACE",3,2]},{"game":8,"cut":2,"depth":1,"maximizing":true,"score":11.5,"action":["PLACE",4,4]},{"game":8,"cut":2,"depth":2,"maximizing":true,"score":-3.0,"action":["PLACE",4,4]},{"game":8,"cut":15,"depth":1,"maximizing":false,"score":-11.0,"action":["PLACE",1,2]},{"game":8,"cut":15,"depth":2,"maximizing":false,"score":25.5,"action":["PLACE",1,2]},{"game":8,"cut":15,"depth":3,"maximizing":false,"score":-5.0,"action":["PLACE",1,2]},{"game":8,"cut":28,"depth":1,"maximizing":true,"score":-31.5,"action":["PLACE",2,1]},{"game":8,"cut":28,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",2,0]},{"game":8,"cut":28,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",2,0]},{"game":9,"cut":2,"depth":1,"maximizing":true,"score":30.5,"action":["PLACE",5,5]},{"game":9,"cut":2,"depth":2,"maximizing":true,"score":16.0,"action":["PLACE",5,5]},{"game":9,"cut":20,"depth":1,"maximizing":true,"score":23.5,"action":["PLACE",2,4]},{"game":9,"cut":20,"depth":2,"maximizing":true,"score":-6.0,"action":["PLACE",2,4]},{"game":9,"cut":38,"depth":1,"maximizing":true,"score":125.0,"action":["PLACE",4,2]},{"game":9,"cut":38,"depth":2,"maximizing":true,"score":87.5,"action":["PLACE",4,2]},{"game":9,"cut":38,"depth":3,"maximizing":true,"score":113.0,"action":["PLACE",4,2]},{"game":10,"cut":2,"depth":1,"maximizing":true,"score":39.0,"action":["PLACE",6,6]},{"game":10,"cut":2,"depth":2,"maximizing":true,"score":22.5,"action":["PLACE",6,6]},{"game":10,"cut":15,"depth":1,"maximizing":false,"score":1.5,"action":["PLACE",4,6]},{"game":10,"cut":15,"depth":2,"maximizing":false,"score":31.0,"action":["PLACE",4,6]},{"game":10,"cut":28,"depth":1,"maximizing":true,"score":84.0,"action":["PLACE",3,0]},{"game":10,"cut":28,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",6,3]},{"game":11,"cut":2,"depth":1,"maximizing":true,"score":44.5,"action":["PLACE",7,7]},{"game":11,"cut":2,"depth":2,"maximizing":true,"score":28.0,"action":["PLACE",7,7]},{"game":11,"cut":37,"depth":1,"maximizing":false,"score":57.0,"action":["PLACE",5,6]},{"game":11,"cut":37,"depth":2,"maximizing":false,"score":91.5,"action":["PLACE",5,6]},{"game":11,"cut":72,"depth":1,"maximizing":true,"score":152.0,"action":["PLACE",6,4]},{"game":11,"cut":72,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",7,1]},{"game":11,"cut":72,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",7,1]},{"game":12,"cut":2,"depth":1,"maximizing":true,"score":15.0,"action":["PLACE",2,2]},{"game":12,"cut":2,"depth":2,"maximizing":true,"score":2.5,"action":["PLACE",2,2]},{"game":12,"cut":2,"depth":3,"maximizing":true,"score":14.0,"action":["PLACE",2,2]},{"game":12,"cut":5,"depth":1,"maximizing":false,"score":-13.5,"action":["PLACE",0,2]},{"game":12,"cut":5,"depth":2,"maximizing":false,"score":6.0,"action":["PLACE",2,0]},{"game":12,"cut":5,"depth":3,"maximizing":false,"score":-21.5,"action":["PLACE",2,0]},{"game":12,"cut":8,"depth":1,"maximizing":true,"score":-21.0,"action":["PLACE",2,2]},{"game":12,"cut":8,"depth":2,"maximizing":true,"score":-36.5,"action":["PLACE",2,2]},{"game":12,"cut":8,"depth":3,"maximizing":true,"score":-25.0,"action":["PLACE",0,2]},{"game":13,"cut":2,"depth":1,"maximizing":true,"score":7.0,"action":["PLACE",3,3]},{"game":13,"cut":2,"depth":2,"maximizing":true,"score":-5.5,"action":["PLACE",3,3]},{"game":13,"cut":8,"depth":1,"maximizing":true,"score":41.0,"action":["PLACE",1,2]},{"game":13,"cut":8,"depth":2,"maximizing":true,"score":28.5,"action":["PLACE",1,2]},{"game":13,"cut":8,"depth":3,"maximizing":true,"score":43.0,"action":["PLACE",3,1]},{"game":13,"cut":14,"depth":1,"maximizing":true,"score":79.0,"action":["PLACE",2,0]},{"game":13,"cut":14,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",0,2]},{"game":13,"cut":14,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",0,2]},{"game":14,"cut":2,"depth":1,"maximizing":true,"score":25.0,"action":["PLACE",4,4]},{"game":14,"cut":2,"depth":2,"maximizing":true,"score":10.5,"action":["PLACE",4,4]},{"game":14,"cut":13,"depth":1,"maximizing":false,"score":-15.5,"action":["PLACE",2,0]},{"game":14,"cut":13,"depth":2,"maximizing":false,"score":22.0,"action":["PLACE",2,0]},{"game":14,"cut":13,"depth":3,"maximizing":false,"score":-13.5,"action":["PLACE",2,0]},{"game":14,"cut":23,"depth":1,"maximizing":false,"score":-25.5,"action":["PLACE",1,2]},{"game":14,"cut":23,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",3,1]},{"game":14,"cut":23,"depth":3,"maximizing":false,"score":"-inf","action":["PLACE",3,1]},{"game":15,"cut":2,"depth":1,"maximizing":true,"score":30.5,"action":["PLACE",5,5]},{"game":15,"cut":2,"depth":2,"maximizing":true,"score":16.0,"action":["PLACE",5,5]},{"game":15,"cut":19,"depth":1,"maximizing":false,"score":-18.0,"action":["PLACE",3,3]},{"game":15,"cut":19,"depth":2,"maximizing":false,"score":15.5,"action":["PLACE",3,3]},{"game":15,"cut":35,"depth":1,"maximizing":false,"score":-23.0,"action":["PLACE",1,2]},{"game":15,"cut":35,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",4,2]},{"game":15,"cut":35,"depth":3,"maximizing":false,"score":"-inf","action":["PLACE",4,2]},{"game":16,"cut":2,"depth":1,"maximizing":true,"score":25.5,"action":["PLACE",6,6]},{"game":16,"cut":2,"depth":2,"maximizing":true,"score":9.0,"action":["PLACE",6,6]},{"game":16,"cut":33,"depth":1,"maximizing":false,"score":-36.0,"action":["PLACE",5,3]},{"game":16,"cut":33,"depth":2,"maximizing":false,"score":3.5,"action":["PLACE",5,3]},{"game":16,"cut":63,"depth":1,"maximizing":false,"score":-63.0,"action":["PLACE",1,5]},{"game":16,"cut":63,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",3,0]},{"game":16,"cut":63,"depth":3,"maximizing":false,"score":"-inf","action":["PLACE",3,0]},{"game":17,"cut":2,"depth":1,"maximizing":true,"score":46.5,"action":["PLACE",7,7]},{"game":17,"cut":2,"depth":2,"maximizing":true,"score":30.0,"action":["PLACE",7,7]},{"game":17,"cut":41,"depth":1,"maximizing":false,"score":28.0,"action":["PLACE",6,1]},{"game":17,"cut":41,"depth":2,"maximizing":false,"score":59.5,"action":["PLACE",6,1]},{"game":17,"cut":80,"depth":1,"maximizing":true,"score":216.0,"action":["PLACE",3,5]},{"game":17,"cut":80,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",4,1]},{"game":17,"cut":80,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",4,1]},{"game":18,"cut":2,"depth":1,"maximizing":true,"score":3.5,"action":["PLACE",2,2]},{"game":18,"cut":2,"depth":2,"maximizing":true,"score":-9.0,"action":["PLACE",2,2]},{"game":18,"cut":2,"depth":3,"maximizing":true,"score":2.5,"action":["PLACE",2,2]},{"game":18,"cut":4,"depth":1,"maximizing":true,"score":19.5,"action":["PLACE",1,1]},{"game":18,"cut":4,"depth":2,"maximizing":true,"score":5.0,"action":["PLACE",1,1]},{"game":18,"cut":4,"depth":3,"maximizing":true,"score":16.5,"action":["PLACE",1,1]},{"game":18,"cut":6,"depth":1,"maximizing":true,"score":18.5,"action":["PLACE",1,2]},{"game":18,"cut":6,"depth":2,"maximizing":true,"score":4.0,"action":["PLACE",1,2]},{"game":18,"cut":6,"depth":3,"maximizing":true,"score":32.5,"action":["PLACE",1,2]},{"game":19,"cut":2,"depth":1,"maximizing":true,"score":18.5,"action":["PLACE",3,3]},{"game":19,"cut":2,"depth":2,"maximizing":true,"score":6.0,"action":["PLACE",3,3]},{"game":19,"cut":2,"depth":3,"maximizing":true,"score":17.5,"action":["PLACE",3,3]},{"game":19,"cut":6,"depth":1,"maximizing":true,"score":32.5,"action":["PLACE",0,2]},{"game":19,"cut":6,"depth":2,"maximizing":true,"score":15.0,"action":["PLACE",0,2]},{"game":19,"cut":6,"depth":3,"maximizing":true,"score":44.5,"action":["PLACE",0,2]},{"game":19,"cut":10,"depth":1,"maximizing":true,"score":17.5,"action":["PLACE",1,1]},{"game":19,"cut":10,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",3,0]},{"game":19,"cut":10,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",3,0]},{"game":20,"cut":2,"depth":1,"maximizing":true,"score":11.5,"action":["PLACE",4,4]},{"game":20,"cut":2,"depth":2,"maximizing":true,"score":-3.0,"action":["PLACE",4,4]},{"game":20,"cut":14,"depth":1,"maximizing":true,"score":28.5,"action":["PLACE",3,0]},{"game":20,"cut":14,"depth":2,"maximizing":true,"score":-3.5,"action":["PLACE",4,2]},{"game":20,"cut":14,"depth":3,"maximizing":true,"score":30.0,"action":["PLACE",4,2]},{"game":20,"cut":26,"depth":1,"maximizing":true,"score":57.5,"action":["PLACE",1,1]},{"game":20,"cut":26,"depth":2,"maximizing":true,"score":"inf","action":["PLACE",0,3]},{"game":20,"cut":26,"depth":3,"maximizing":true,"score":"inf","action":["PLACE",0,3]},{"game":21,"cut":2,"depth":1,"maximizing":true,"score":30.5,"action":["PLACE",5,5]},{"game":21,"cut":2,"depth":2,"maximizing":true,"score":16.0,"action":["PLACE",5,5]},{"game":21,"cut":15,"depth":1,"maximizing":false,"score":-22.0,"action":["PLACE",2,4]},{"game":21,"cut":15,"depth":2,"maximizing":false,"score":2.5,"action":["PLACE",1,1]},{"game":21,"cut":28,"depth":1,"maximizing":true,"score":6.5,"action":["PLACE",2,1]},{"game":21,"cut":28,"depth":2,"maximizing":true,"score":-25.0,"action":["PLACE",1,4]},{"game":21,"cut":28,"depth":3,"maximizing":true,"score":7.5,"action":["PLACE",1,4]},{"game":22,"cut":2,"depth":1,"maximizing":true,"score":37.0,"action":["PLACE",6,6]},{"game":22,"cut":2,"depth":2,"maximizing":true,"score":20.5,"action":["PLACE",6,6]},{"game":22,"cut":35,"depth":1,"maximizing":false,"score":-51.0,"action":["PLACE",2,1]},{"game":22,"cut":35,"depth":2,"maximizing":false,"score":-2.5,"action":["PLACE",2,1]},{"game":22,"cut":67,"depth":1,"maximizing":false,"score":39.0,"action":["PLACE",5,3]},{"game":22,"cut":67,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",1,6]},{"game":22,"cut":67,"depth":3,"maximizing":false,"score":"-inf","action":["PLACE",1,6]},{"game":23,"cut":2,"depth":1,"maximizing":true,"score":33.0,"action":["PLACE",7,7]},{"game":23,"cut":2,"depth":2,"maximizing":true,"score":16.5,"action":["PLACE",7,7]},{"game":23,"cut":30,"depth":1,"maximizing":true,"score":57.5,"action":["PLACE",4,2]},{"game":23,"cut":30,"depth":2,"maximizing":true,"score":26.0,"action":["PLACE",4,2]},{"game":23,"cut":57,"depth":1,"maximizing":false,"score":-90.5,"action":["PLACE",2,2]},{"game":23,"cut":57,"depth":2,"maximizing":false,"score":"-inf","action":["PLACE",5,1]}],"agentMoves":[{"n":3,"actions":[],"colour":"red","action":["PLACE",1,0]},{"n":3,"actions":[["PLACE",0,1]],"colour":"blue","action":["STEAL"]},{"n":3,"actions":[["PLACE",0,0]],"colour":"blue","action":["PLACE",0,1]},{"n":3,"actions":[["PLACE",2,1]],"colour":"blue","action":["PLACE",0,1]},{"n":4,"actions":[],"colour":"red","action":["PLACE",1,1]},{"n":4,"actions":[["PLACE",1,1]],"colour":"blue","action":["STEAL"]},{"n":4,"actions":[["PLACE",0,1]],"colour":"blue","action":["PLACE",1,1]},{"n":4,"actions":[["PLACE",0,0]],"colour":"blue","action":["PLACE",1,1]},{"n":4,"actions":[["PLACE",2,1]],"colour":"blue","action":["PLACE",1,1]},{"n":5,"actions":[],"colour":"red","action":["PLACE",1,1]},{"n":5,"actions":[["PLACE",1,1]],"colour":"blue","action":["STEAL"]},{"n":5,"actions":[["PLACE",0,1]],"colour":"blue","action":["PLACE",1,1]},{"n":5,"actions":[["PLACE",0,0]],"colour":"blue","action":["PLACE",1,1]},{"n":5,"actions":[["PLACE",2,1]],"colour":"blue","action":["PLACE",1,1]},{"n":6,"actions":[],"colour":"red","action":["PLACE",1,1]},{"n":6,"actions":[["PLACE",1,1]],"colour":"blue","action":["STEAL"]},{"n":6,"actions":[["PLACE",0,1]],"colour":"blue","action":["PLACE",1,1]},{"n":6,"actions":[["PLACE",0,0]],"colour":"blue","action":["PLACE",1,1]},{"n":6,"actions":[["PLACE",2,1]],"colour":"blue","action":["PLACE",1,1]},{"n":7,"actions":[],"colour":"red","action":["PLACE",1,1]},{"n":7,"actions":[["PLACE",1,1]],"colour":"blue","action":["STEAL"]},{"n":7,"actions":[["PLACE",0,1]],"colour":"blue","action":["PLACE",1,1]},{"n":7,"actions":[["PLACE",0,0]],"colour":"blue","action":["PLACE",1,1]},{"n":7,"actions":[["PLACE",2,1]],"colour":"blue","action":["PLACE",1,1]},{"game":0,"cut":3,"colour":"blue","action":["PLACE",0,0]},{"game":0,"cut":4,"colour":"red","action":["PLACE",0,0]},{"game":1,"cut":3,"colour":"blue","action":["PLACE",3,3]},{"game":1,"cut":8,"colour":"red","action":["PLACE",1,0]},{"game":1,"cut":14,"colour":"red","action":["PLACE",1,2]},{"game":2,"cut":3,"colour":"blue","action":["PLACE",4,4]},{"game":2,"cut":9,"colour":"blue","action":["PLACE",2,0]},{"game":2,"cut":17,"colour":"blue","action":["PLACE",2,1]},{"game":3,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":3,"cut":8,"colour":"red","action":["PLACE",3,0]},{"game":3,"cut":14,"colour":"red","action":["PLACE",3,0]},{"game":4,"cut":3,"colour":"blue","action":["PLACE",6,6]},{"game":4,"cut":26,"colour":"red","action":["PLACE",0,6]},{"game":4,"cut":51,"colour":"blue","action":["PLACE",2,5]},{"game":5,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":5,"cut":34,"colour":"red","action":["PLACE",6,4]},{"game":5,"cut":67,"colour":"blue","action":["PLACE",2,1]},{"game":6,"cut":3,"colour":"blue","action":["PLACE",2,2]},{"game":6,"cut":4,"colour":"red","action":["PLACE",2,2]},{"game":6,"cut":6,"colour":"red","action":["PLACE",0,2]},{"game":7,"cut":3,"colour":"blue","action":["PLACE",1,3]},{"game":7,"cut":7,"colour":"blue","action":["PLACE",0,2]},{"game":7,"cut":13,"colour":"blue","action":["PLACE",3,2]},{"game":8,"cut":3,"colour":"blue","action":["PLACE",4,4]},{"game":8,"cut":15,"colour":"blue","action":["PLACE",1,2]},{"game":8,"cut":29,"colour":"blue","action":["PLACE",2,1]},{"game":9,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":9,"cut":20,"colour":"red","action":["PLACE",2,4]},{"game":9,"cut":39,"colour":"blue","action":["PLACE",4,2]},{"game":10,"cut":3,"colour":"blue","action":["PLACE",6,6]},{"game":10,"cut":15,"colour":"blue","action":["PLACE",4,6]},{"game":10,"cut":29,"colour":"blue","action":["PLACE",3,2]},{"game":11,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":11,"cut":37,"colour":"blue","action":["PLACE",5,6]},{"game":11,"cut":73,"colour":"blue","action":["PLACE",7,1]},{"game":12,"cut":3,"colour":"blue","action":["PLACE",2,2]},{"game":12,"cut":5,"colour":"blue","action":["PLACE",0,2]},{"game":12,"cut":9,"colour":"blue","action":["PLACE",2,1]},{"game":13,"cut":3,"colour":"blue","action":["PLACE",3,3]},{"game":13,"cut":8,"colour":"red","action":["PLACE",1,2]},{"game":13,"cut":15,"colour":"blue","action":["PLACE",2,0]},{"game":14,"cut":3,"colour":"blue","action":["PLACE",4,4]},{"game":14,"cut":13,"colour":"blue","action":["PLACE",2,0]},{"game":14,"cut":24,"colour":"red","action":["PLACE",1,2]},{"game":15,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":15,"cut":19,"colour":"blue","action":["PLACE",3,3]},{"game":15,"cut":36,"colour":"red","action":["PLACE",4,0]},{"game":16,"cut":3,"colour":"blue","action":["PLACE",6,6]},{"game":16,"cut":33,"colour":"blue","action":["PLACE",5,3]},{"game":16,"cut":64,"colour":"red","action":["PLACE",1,5]},{"game":17,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":17,"cut":41,"colour":"blue","action":["PLACE",6,1]},{"game":17,"cut":81,"colour":"blue","action":["PLACE",3,5]},{"game":18,"cut":3,"colour":"blue","action":["PLACE",0,2]},{"game":18,"cut":4,"colour":"red","action":["PLACE",1,1]},{"game":18,"cut":7,"colour":"blue","action":["PLACE",1,2]},{"game":19,"cut":3,"colour":"blue","action":["PLACE",0,2]},{"game":19,"cut":6,"colour":"red","action":["PLACE",0,2]},{"game":19,"cut":11,"colour":"blue","action":["PLACE",1,1]},{"game":20,"cut":3,"colour":"blue","action":["PLACE",4,4]},{"game":20,"cut":14,"colour":"red","action":["PLACE",3,0]},{"game":20,"cut":27,"colour":"blue","action":["PLACE",1,1]},{"game":21,"cut":3,"colour":"blue","action":["PLACE",1,1]},{"game":21,"cut":15,"colour":"blue","action":["PLACE",2,4]},{"game":21,"cut":29,"colour":"blue","action":["PLACE",1,4]},{"game":22,"cut":3,"colour":"blue","action":["PLACE",2,3]},{"game":22,"cut":35,"colour":"blue","action":["PLACE",2,1]},{"game":22,"cut":68,"colour":"red","action":["PLACE",1,6]},{"game":23,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":23,"cut":30,"colour":"red","action":["PLACE",4,2]},{"game":23,"cut":58,"colour":"red","action":["PLACE",6,2]},{"game":24,"cut":3,"colour":"blue","action":["PLACE",1,2]},{"game":24,"cut":6,"colour":"red","action":["PLACE",1,1]},{"game":24,"cut":10,"colour":"red","action":["PLACE",1,2]},{"game":25,"cut":3,"colour":"blue","action":["PLACE",2,3]},{"game":25,"cut":7,"colour":"blue","action":["PLACE",2,3]},{"game":25,"cut":13,"colour":"blue","action":["PLACE",3,3]},{"game":26,"cut":3,"colour":"blue","action":["PLACE",4,1]},{"game":26,"cut":12,"colour":"red","action":["PLACE",3,3]},{"game":26,"cut":23,"colour":"blue","action":["PLACE",1,3]},{"game":27,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":27,"cut":23,"colour":"blue","action":["PLACE",5,2]},{"game":27,"cut":45,"colour":"blue","action":["PLACE",1,1]},{"game":28,"cut":3,"colour":"blue","action":["PLACE",6,6]},{"game":28,"cut":29,"colour":"blue","action":["PLACE",4,4]},{"game":28,"cut":56,"colour":"red","action":["PLACE",5,3]},{"game":29,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":29,"cut":41,"colour":"blue","action":["PLACE",2,6]},{"game":29,"cut":80,"colour":"red","action":["PLACE",2,7]},{"game":30,"cut":3,"colour":"blue","action":["PLACE",2,2]},{"game":30,"cut":5,"colour":"blue","action":["PLACE",0,2]},{"game":30,"cut":8,"colour":"red","action":["PLACE",1,2]},{"game":31,"cut":3,"colour":"blue","action":["PLACE",3,3]},{"game":31,"cut":8,"colour":"red","action":["PLACE",2,1]},{"game":31,"cut":14,"colour":"red","action":["PLACE",1,2]},{"game":32,"cut":3,"colour":"blue","action":["PLACE",1,4]},{"game":32,"cut":7,"colour":"blue","action":["PLACE",1,4]},{"game":32,"cut":13,"colour":"blue","action":["PLACE",2,1]},{"game":33,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":33,"cut":10,"colour":"red","action":["PLACE",1,2]},{"game":33,"cut":19,"colour":"blue","action":["PLACE",1,2]},{"game":34,"cut":3,"colour":"blue","action":["PLACE",6,6]},{"game":34,"cut":26,"colour":"red","action":["PLACE",2,5]},{"game":34,"cut":50,"colour":"red","action":["PLACE",5,4]},{"game":35,"cut":3,"colour":"blue","action":["PLACE",7,7]},{"game":35,"cut":35,"colour":"blue","action":["PLACE",2,5]},{"game":35,"cut":69,"colour":"blue","action":["PLACE",2,3]},{"game":36,"cut":3,"colour":"blue","action":["PLACE",0,1]},{"game":36,"cut":4,"colour":"red","action":["PLACE",0,1]},{"game":36,"cut":7,"colour":"blue","action":["PLACE",2,1]},{"game":37,"cut":3,"colour":"blue","action":["PLACE",3,3]},{"game":37,"cut":4,"colour":"red","action":["PLACE",1,1]},{"game":37,"cut":6,"colour":"red","action":["PLACE",2,3]},{"game":38,"cut":3,"colour":"blue","action":["PLACE",4,4]},{"game":38,"cut":16,"colour":"red","action":["PLACE",0,1]},{"game":38,"cut":30,"colour":"red","action":["PLACE",3,2]},{"game":39,"cut":3,"colour":"blue","action":["PLACE",5,5]},{"game":39,"cut":27,"colour":"blue","action":["PLACE",3,1]},{"game":39,"cut":52,"colour":"red","action":["PLACE",3,2]}],"agentGames":[{"n":3,"actions":[["PLACE",1,0],["PLACE",0,1],["PLACE",2,2],["PLACE",0,2],["PLACE",0,0],["PLACE",1,1],["PLACE",2,0]],"result":"winner: red"},{"n":4,"actions":[["PLACE",1,1],["STEAL"],["PLACE",3,3],["PLACE",3,2],["PLACE",3,1],["PLACE",3,0],["PLACE",1,0],["PLACE",2,0],["PLACE",2,1],["PLACE",2,2],["PLACE",2,3],["PLACE",3,1],["PLACE",2,0],["PLACE",1,3]],"result":"winner: blue"},{"n":5,"actions":[["PLACE",1,1],["STEAL"],["PLACE",4,4],["PLACE",4,3],["PLACE",4,2],["PLACE",4,1],["PLACE",4,0],["PLACE",1,4],["PLACE",3,0],["PLACE",0,4],["PLACE",3,1],["PLACE",3,2],["PLACE",3,1],["PLACE",4,2],["PLACE",2,1],["PLACE",3,3],["PLACE",2,0],["PLACE",2,3],["PLACE",3,4],["PLACE",2,4],["PLACE",1,0],["PLACE",1,3],["PLACE",0,0]],"result":"winner: red"},{"n":6,"actions":[["PLACE",1,1],["STEAL"],["PLACE",5,5],["PLACE",5,4],["PLACE",5,3],["PLACE",5,2],["PLACE",5,1],["PLACE",5,0],["PLACE",3,0],["PLACE",4,0],["PLACE",2,5],["PLACE",4,1],["PLACE",4,2],["PLACE",4,1],["PLACE",5,2],["PLACE",2,4],["PLACE",4,3],["PLACE",3,1],["PLACE",2,0],["PLACE",1,2],["PLACE",2,1],["PLACE",0,2],["PLACE",2,2],["PLACE",1,2],["PLACE",3,1],["PLACE",3,2],["PLACE",3,1],["PLACE",4,2],["PLACE",1,5],["PLACE",3,3],["PLACE",1,0],["PLACE",0,3],["PLACE",0,5],["PLACE",0,1],["PLACE",3,4]],"result":"winner: red"},{"n":7,"actions":[["PLACE",1,1],["STEAL"],["PLACE",6,6],["PLACE",6,5],["PLACE",6,4],["PLACE",6,3],["PLACE",6,2],["PLACE",6,1],["PLACE",6,0],["PLACE",4,0],["PLACE",5,0],["PLACE",3,6],["PLACE",5,1],["PLACE",5,2],["PLACE",5,1],["PLACE",6,2],["PLACE",4,1],["PLACE",5,3],["PLACE",4,2],["PLACE",4,3],["PLACE",3,2],["PLACE",2,6],["PLACE",3,1],["PLACE",3,5],["PLACE",2,2],["PLACE",4,4],["PLACE",2,1],["PLACE",3,4],["PLACE",3,0],["PLACE",2,5],["PLACE",2,0],["PLACE",1,6],["PLACE",1,2],["PLACE",1,5],["PLACE",0,2]],"result":"winner: red"}]}
\ No newline at end of file
diff --git a/web/src/lib/agent/agent-board.ts b/web/src/lib/agent/agent-board.ts
new file mode 100644
index 0000000..16170d6
--- /dev/null
+++ b/web/src/lib/agent/agent-board.ts
@@ -0,0 +1,69 @@
+/**
+ * Port of `Board_4399` (coursework/Project Part B/code/utility/board.py):
+ * the agent's own board, extending the referee board with the last action,
+ * last player, winner and a turn counter.
+ */
+import { Board } from "@/lib/cachex/board";
+import { type Action, type Colour, type Coord, isSteal } from "@/lib/cachex/types";
+
+export class AgentBoard extends Board {
+ lastAction: Action | null = null;
+ lastPlayer: Colour = "blue";
+ winner: Colour | null = null;
+ /** 1-based number of the turn about to be played. */
+ turn = 1;
+
+ constructor(n: number, data?: Uint8Array) {
+ super(n, data);
+ }
+
+ static fromActions(n: number, actions: readonly Action[]): AgentBoard {
+ const board = new AgentBoard(n);
+ actions.forEach((action, i) => board.update(i % 2 === 0 ? "red" : "blue", action));
+ return board;
+ }
+
+ override clone(): AgentBoard {
+ const copy = new AgentBoard(this.n, this.data);
+ copy.lastAction = this.lastAction;
+ copy.lastPlayer = this.lastPlayer;
+ copy.winner = this.winner;
+ copy.turn = this.turn;
+ return copy;
+ }
+
+ isOdd(): boolean {
+ return this.n % 2 === 1;
+ }
+
+ /** Empty cells (the original returns a set; order is irrelevant to callers). */
+ availableHexagons(): Coord[] {
+ const out: Coord[] = [];
+ for (let r = 0; r < this.n; r++) {
+ for (let q = 0; q < this.n; q++) {
+ if (!this.isOccupied(r, q)) out.push([r, q]);
+ }
+ }
+ return out;
+ }
+
+ emptyCount(): number {
+ let count = 0;
+ for (let i = 0; i < this.data.length; i++) if (this.data[i] === 0) count++;
+ return count;
+ }
+
+ /** Apply an already-validated action. */
+ update(player: Colour, action: Action): Coord[] {
+ let captures: Coord[] = [];
+ if (isSteal(action)) {
+ this.swap();
+ } else {
+ captures = this.place(player, action[1], action[2]);
+ }
+ this.turn += 1;
+ this.lastAction = action;
+ this.lastPlayer = player;
+ return captures;
+ }
+}
diff --git a/web/src/lib/agent/agent.test.ts b/web/src/lib/agent/agent.test.ts
new file mode 100644
index 0000000..2f8a944
--- /dev/null
+++ b/web/src/lib/agent/agent.test.ts
@@ -0,0 +1,170 @@
+import { readFileSync } from "node:fs";
+
+import { describe, expect, it } from "vitest";
+
+import { fromPy, partB, position, toAction } from "@/lib/__fixtures__/load";
+import { Game } from "@/lib/cachex/game";
+import { STEAL, place } from "@/lib/cachex/types";
+import { createRng } from "@/lib/rng";
+import { AgentBoard } from "./agent-board";
+import { computeFeatures, evaluate, scoreFeatures } from "./evaluation";
+import { scoreMatrix } from "./features";
+import { createContext, gameEnd, getValidActions, minimax } from "./minimax";
+import { agentAction, chooseAgentAction, dynamicDepthAllocation } from "./player";
+import { chooseRandomAction } from "./random-player";
+import weights from "./weights.json";
+
+const fixtures = partB();
+
+describe("weights", () => {
+ it("is a verbatim copy of the original utility/weights.json", () => {
+ const read = (path: string) => readFileSync(new URL(path, import.meta.url), "utf8");
+ const original = read("../../../../coursework/Project Part B/code/utility/weights.json");
+ expect(read("./weights.json")).toBe(original);
+ expect(weights).toEqual(JSON.parse(original));
+ });
+});
+
+describe("score_matrix parity", () => {
+ it.each(Object.entries(fixtures.scoreMatrices))("n = %s", (n, expected) => {
+ expect(scoreMatrix(Number(n))).toEqual(expected);
+ });
+});
+
+describe("evaluation feature parity", () => {
+ it.each(fixtures.evalPositions.map((p, i) => [i, p] as const))("position %i", (_, p) => {
+ const { n, actions } = position(fixtures, p);
+ const board = AgentBoard.fromActions(n, actions);
+ const f = computeFeatures(board);
+ const expected = p.features;
+ expect(f.empty).toBe(expected.empty);
+ for (const key of ["triangle", "tokens", "location", "diamond", "weakness"] as const) {
+ expect(f[key], key).toEqual({
+ red: fromPy(expected[key].red),
+ blue: fromPy(expected[key].blue),
+ });
+ }
+ expect(scoreFeatures(f)).toBe(fromPy(p.eval));
+ expect(evaluate(board)).toBe(fromPy(p.eval));
+ });
+});
+
+describe("minimax parity (canonical move order, no bias)", () => {
+ it.each(fixtures.minimax.map((m, i) => [i, m] as const))("case %i", (_, m) => {
+ const { n, actions } = position(fixtures, m);
+ const board = AgentBoard.fromActions(n, actions);
+ const [score, action] = minimax(
+ board,
+ m.depth,
+ -Infinity,
+ Infinity,
+ m.maximizing,
+ createContext(),
+ );
+ expect(score).toBe(fromPy(m.score));
+ expect(action).toEqual(m.action === null ? null : toAction(m.action));
+ });
+});
+
+describe("Player.action parity", () => {
+ it.each(fixtures.agentMoves.map((m, i) => [i, m] as const))("move %i", (_, m) => {
+ const { n, actions } = position(fixtures, m);
+ const decision = chooseAgentAction(n, actions, m.colour);
+ expect(decision.action).toEqual(toAction(m.action));
+ });
+
+ it.each(fixtures.agentGames.map((g) => [g.n, g] as const))(
+ "deterministic self-play on n = %i replays move for move",
+ (n, g) => {
+ const game = new Game(n);
+ const expected = g.actions.map(toAction);
+ for (const want of expected) {
+ const { action } = chooseAgentAction(
+ n,
+ game.log.map((t) => t.action),
+ game.turnPlayer(),
+ );
+ expect(action).toEqual(want);
+ game.update(game.turnPlayer(), action);
+ }
+ const result = game.result?.kind === "win" ? `winner: ${game.result.winner}` : "draw";
+ expect(result).toBe(g.result);
+ },
+ );
+});
+
+describe("agent behaviour", () => {
+ it("allocates deeper searches as the board fills up", () => {
+ const empty = new AgentBoard(10);
+ expect(dynamicDepthAllocation(empty)).toBe(1);
+ const nearlyFull = new AgentBoard(10);
+ nearlyFull.data.fill(1);
+ nearlyFull.data[0] = 0;
+ expect(dynamicDepthAllocation(nearlyFull)).toBe(4);
+ });
+
+ it("uses the opening book on the first two turns", () => {
+ expect(chooseAgentAction(5, [], "red").action).toEqual(place(1, 1));
+ expect(chooseAgentAction(5, [place(1, 1)], "blue").action).toEqual(STEAL);
+ expect(chooseAgentAction(3, [], "red").explanation.kind).toBe("opening");
+ });
+
+ it("takes an immediate win", () => {
+ // Red owns (0,0) and (1,0) on a 3x3 board; (2,0) wins.
+ const actions = [place(0, 0), place(0, 2), place(1, 0), place(1, 2)];
+ const decision = chooseAgentAction(3, actions, "red");
+ expect(decision.explanation.kind).toBe("instant-win");
+ const board = AgentBoard.fromActions(3, [...actions, decision.action]);
+ expect(gameEnd(board)).toBe(true);
+ });
+
+ it("explains searched moves with root candidates and a feature breakdown", () => {
+ const decision = agentAction(
+ AgentBoard.fromActions(5, [place(1, 1), place(3, 3), place(0, 4)]),
+ "blue",
+ {
+ order: createRng(1),
+ },
+ );
+ expect(decision.explanation.kind).toBe("search");
+ if (decision.explanation.kind === "search") {
+ expect(decision.explanation.candidates.length).toBe(22);
+ expect(decision.explanation.features).toHaveLength(6);
+ }
+ });
+
+ it("offers STEAL only on turn 2 and never the centre on turn 1", () => {
+ const b = new AgentBoard(5);
+ expect(getValidActions(b, "canonical")).not.toContainEqual(place(2, 2));
+ b.update("red", place(0, 0));
+ expect(getValidActions(b, "canonical")).toContainEqual(STEAL);
+ });
+});
+
+describe("random agent", () => {
+ it("always returns a legal action", () => {
+ const rng = createRng(7);
+ for (let trial = 0; trial < 20; trial++) {
+ const game = new Game(5);
+ while (!game.over()) {
+ const { action } = chooseRandomAction(
+ 5,
+ game.log.map((t) => t.action),
+ rng,
+ );
+ expect(game.isLegal(action)).toBe(true);
+ game.update(game.turnPlayer(), action);
+ }
+ }
+ });
+});
+
+describe("deterministicSelfPlay", () => {
+ it("reproduces the original self-play game on 7×7", async () => {
+ const { deterministicSelfPlay } = await import("./self-play");
+ const expected = fixtures.agentGames.find((g) => g.n === 7)!;
+ const { actions, game } = deterministicSelfPlay(7);
+ expect(actions).toEqual(expected.actions.map(toAction));
+ expect(game.result?.kind === "win" && game.result.winner).toBe("red");
+ });
+});
diff --git a/web/src/lib/agent/evaluation.ts b/web/src/lib/agent/evaluation.ts
new file mode 100644
index 0000000..0ef8bf9
--- /dev/null
+++ b/web/src/lib/agent/evaluation.ts
@@ -0,0 +1,162 @@
+/**
+ * Port of `Eval` (coursework/Project Part B/code/utility/evaluation.py).
+ *
+ * The score is from Red's point of view: Red maximises, Blue minimises.
+ * Weights come from a verbatim copy of the original `utility/weights.json`.
+ */
+import type { AgentBoard } from "./agent-board";
+import {
+ type ColourCounts,
+ countTokenInDiamond,
+ countTokenInDiffHexLocation,
+ countTokenInTriangle,
+ countTokenInWeakness,
+ nEmptyHex,
+ tokenCounter,
+} from "./features";
+import weightsFile from "./weights.json";
+
+export const MAGIC_NUMBER = 1e-5;
+
+export const POSITIVE_WEIGHTS: readonly number[] = weightsFile[0].positive_weights!;
+export const NEGATIVE_WEIGHTS: readonly number[] = weightsFile[1].negative_weights!;
+
+export type FeatureId = "empty" | "triangle" | "tokens" | "location" | "diamond" | "weakness";
+
+export interface FeatureSpec {
+ id: FeatureId;
+ label: string;
+ description: string;
+ sign: 1 | -1;
+ weight: number;
+}
+
+export const FEATURES: readonly FeatureSpec[] = [
+ {
+ id: "empty",
+ label: "Empty hexes",
+ description: "Number of empty cells left on the board (shared, not per colour).",
+ sign: 1,
+ weight: POSITIVE_WEIGHTS[0],
+ },
+ {
+ id: "triangle",
+ label: "Triangle formations",
+ description: "Tokens that form a solid triangle with two adjacent friendly neighbours.",
+ sign: 1,
+ weight: POSITIVE_WEIGHTS[1],
+ },
+ {
+ id: "tokens",
+ label: "Token count",
+ description: "Tokens of each colour currently on the board.",
+ sign: 1,
+ weight: POSITIVE_WEIGHTS[2],
+ },
+ {
+ id: "location",
+ label: "Positional value",
+ description: "Sum of cell scores: the rim scores higher than the centre.",
+ sign: 1,
+ weight: POSITIVE_WEIGHTS[3],
+ },
+ {
+ id: "diamond",
+ label: "Capturable diamonds",
+ description: "Tokens sitting in a half-built diamond the opponent could complete.",
+ sign: -1,
+ weight: NEGATIVE_WEIGHTS[0],
+ },
+ {
+ id: "weakness",
+ label: "Weak formations",
+ description: "Tokens with an exposed gap that invites an attack.",
+ sign: -1,
+ weight: NEGATIVE_WEIGHTS[1],
+ },
+];
+
+export interface Features {
+ empty: number;
+ triangle: ColourCounts;
+ tokens: ColourCounts;
+ location: ColourCounts;
+ diamond: ColourCounts;
+ weakness: ColourCounts;
+}
+
+export function computeFeatures(board: AgentBoard): Features {
+ return {
+ empty: nEmptyHex(board),
+ triangle: countTokenInTriangle(board),
+ tokens: tokenCounter(board),
+ location: countTokenInDiffHexLocation(board),
+ diamond: countTokenInDiamond(board),
+ weakness: countTokenInWeakness(board),
+ };
+}
+
+/** Weighted score of the features, before the random tie-break bias. */
+export function scoreFeatures(f: Features): number {
+ let score = 0;
+ // positive features: Red adds, Blue subtracts
+ score += f.empty * POSITIVE_WEIGHTS[0];
+ score += f.triangle.red * POSITIVE_WEIGHTS[1];
+ score -= f.triangle.blue * POSITIVE_WEIGHTS[1];
+ score += f.tokens.red * POSITIVE_WEIGHTS[2];
+ score -= f.tokens.blue * POSITIVE_WEIGHTS[2];
+ score += f.location.red * POSITIVE_WEIGHTS[3];
+ score -= f.location.blue * POSITIVE_WEIGHTS[3];
+ // negative features: Red subtracts, Blue adds
+ score -= f.diamond.red * NEGATIVE_WEIGHTS[0];
+ score += f.diamond.blue * NEGATIVE_WEIGHTS[0];
+ score -= f.weakness.red * NEGATIVE_WEIGHTS[1];
+ score += f.weakness.blue * NEGATIVE_WEIGHTS[1];
+ return score;
+}
+
+export interface FeatureContribution extends FeatureSpec {
+ red: number | null;
+ blue: number | null;
+ value: number | null;
+ contribution: number;
+}
+
+/** Per-feature breakdown used by the "explain move" panel. */
+export function explainFeatures(f: Features): FeatureContribution[] {
+ return FEATURES.map((spec) => {
+ if (spec.id === "empty") {
+ return {
+ ...spec,
+ red: null,
+ blue: null,
+ value: f.empty,
+ contribution: f.empty * spec.weight,
+ };
+ }
+ const c = f[spec.id];
+ return {
+ ...spec,
+ red: c.red,
+ blue: c.blue,
+ value: null,
+ contribution: spec.sign * (c.red - c.blue) * spec.weight,
+ };
+ });
+}
+
+/**
+ * `apply_bias`: multiply by 1 or 1 + 1e-5 at random so equal evaluations are
+ * broken differently from game to game.
+ */
+export type BiasFn = () => number;
+export const noBias: BiasFn = () => 1;
+export const randomBias =
+ (rng: () => number): BiasFn =>
+ () =>
+ (rng() < 0.5 ? 0 : 1) * MAGIC_NUMBER + 1;
+
+/** `Eval(board, player)` — the player argument is unused in the original. */
+export function evaluate(board: AgentBoard, bias: BiasFn = noBias): number {
+ return scoreFeatures(computeFeatures(board)) * bias();
+}
diff --git a/web/src/lib/agent/features.ts b/web/src/lib/agent/features.ts
new file mode 100644
index 0000000..2aa3692
--- /dev/null
+++ b/web/src/lib/agent/features.ts
@@ -0,0 +1,142 @@
+/**
+ * Port of the evaluation features in
+ * coursework/Project Part B/code/_4399/eval_func.py.
+ *
+ * Every feature returns a per-colour count (or sum), exactly like the
+ * original dictionaries, except that missing keys are reported as 0.
+ */
+import { CAPTURE_PATTERNS, HEX_STEPS } from "@/lib/cachex/board";
+import { COLOUR_OF, SWAP_TOKEN, type Token } from "@/lib/cachex/types";
+import type { AgentBoard } from "./agent-board";
+
+export interface ColourCounts {
+ red: number;
+ blue: number;
+}
+
+type Step = readonly [number, number];
+
+/** Pairs of adjacent neighbours: [steps[i], roll(steps, 1)[i]] */
+export const TRIANGLE_PATTERNS: readonly (readonly [Step, Step])[] = HEX_STEPS.map(
+ (n1, i) => [n1, HEX_STEPS[(i + 5) % 6]] as const,
+);
+
+/** Identical construction to the referee's capture patterns. */
+export const DIAMOND_PATTERNS = CAPTURE_PATTERNS;
+
+/** [n1, 2 * n1]: a token with an empty neighbour and a friendly token behind it. */
+export const WEAK_PATTERNS: readonly (readonly [Step, Step])[] = HEX_STEPS.map(
+ (n1) => [n1, [n1[0] * 2, n1[1] * 2] as const] as const,
+);
+
+function tokensAt(
+ board: AgentBoard,
+ r: number,
+ q: number,
+ pattern: readonly Step[],
+): Token[] | null {
+ const out: Token[] = [];
+ for (const [dr, dq] of pattern) {
+ const nr = r + dr;
+ const nq = q + dq;
+ if (!board.insideBounds(nr, nq)) return null;
+ out.push(board.tokenAt(nr, nq));
+ }
+ return out;
+}
+
+export function tokenInTriangle(board: AgentBoard, r: number, q: number): boolean {
+ const opp = board.tokenAt(r, q);
+ for (const pattern of TRIANGLE_PATTERNS) {
+ const t = tokensAt(board, r, q, pattern);
+ if (t && t[0] === opp && t[1] === opp) return true;
+ }
+ return false;
+}
+
+export function tokenInDiamond(board: AgentBoard, r: number, q: number): boolean {
+ const opp = board.tokenAt(r, q);
+ const mid = SWAP_TOKEN[opp];
+ for (const pattern of DIAMOND_PATTERNS) {
+ const t = tokensAt(board, r, q, pattern);
+ if (!t) continue;
+ if (t[0] === opp && t[1] === mid && t[2] === 0) return true;
+ if (t[0] === opp && t[1] === 0 && t[2] === mid) return true;
+ }
+ return false;
+}
+
+export function tokenInWeakness(board: AgentBoard, r: number, q: number): boolean {
+ const opp = board.tokenAt(r, q);
+ for (const pattern of WEAK_PATTERNS) {
+ const t = tokensAt(board, r, q, pattern);
+ if (t && t[0] === 0 && t[1] === opp) return true;
+ }
+ for (const pattern of DIAMOND_PATTERNS) {
+ const t = tokensAt(board, r, q, pattern);
+ if (t && t[0] === opp && t[1] === 0 && t[2] === 0) return true;
+ }
+ return false;
+}
+
+function countOccupied(
+ board: AgentBoard,
+ predicate: (board: AgentBoard, r: number, q: number) => boolean,
+): ColourCounts {
+ const result: ColourCounts = { red: 0, blue: 0 };
+ for (let r = 0; r < board.n; r++) {
+ for (let q = 0; q < board.n; q++) {
+ const t = board.tokenAt(r, q);
+ if (t !== 0 && predicate(board, r, q)) result[COLOUR_OF[t]] += 1;
+ }
+ }
+ return result;
+}
+
+/** `token_counter` */
+export const tokenCounter = (board: AgentBoard) => countOccupied(board, () => true);
+/** `count_token_in_triangle` */
+export const countTokenInTriangle = (board: AgentBoard) => countOccupied(board, tokenInTriangle);
+/** `count_token_in_diamond` */
+export const countTokenInDiamond = (board: AgentBoard) => countOccupied(board, tokenInDiamond);
+/** `count_token_in_weakness` */
+export const countTokenInWeakness = (board: AgentBoard) => countOccupied(board, tokenInWeakness);
+
+const scoreMatrixCache = new Map();
+
+/**
+ * `score_matrix`: positional value of each cell, high at the rim and
+ * decreasing towards the centre (the exact centre of odd boards scores 1).
+ */
+export function scoreMatrix(size: number): number[][] {
+ const cached = scoreMatrixCache.get(size);
+ if (cached) return cached;
+ const m = Array.from({ length: size }, () =>
+ new Array(size).fill(Math.trunc((size + 3) / 2 - 1)),
+ );
+ for (let n = 1; n < Math.floor(size / 2); n++) {
+ const value = Math.trunc((size + 3) / 2) - n;
+ for (let r = n; r < size - n; r++) {
+ for (let q = n; q < size - n; q++) m[r][q] = value;
+ }
+ }
+ if (size % 2 === 1) m[Math.floor(size / 2)][Math.floor(size / 2)] = 1;
+ scoreMatrixCache.set(size, m);
+ return m;
+}
+
+/** `count_token_in_diff_hex_location` */
+export function countTokenInDiffHexLocation(board: AgentBoard): ColourCounts {
+ const s = scoreMatrix(board.n);
+ const result: ColourCounts = { red: 0, blue: 0 };
+ for (let r = 0; r < board.n; r++) {
+ for (let q = 0; q < board.n; q++) {
+ const t = board.tokenAt(r, q);
+ if (t !== 0) result[COLOUR_OF[t]] += s[r][q];
+ }
+ }
+ return result;
+}
+
+/** `n_emptyhex` (utility/evaluation.py) */
+export const nEmptyHex = (board: AgentBoard) => board.emptyCount();
diff --git a/web/src/lib/agent/minimax.ts b/web/src/lib/agent/minimax.ts
new file mode 100644
index 0000000..ee99493
--- /dev/null
+++ b/web/src/lib/agent/minimax.ts
@@ -0,0 +1,132 @@
+/**
+ * Port of coursework/Project Part B/code/_4399/minimax.py:
+ * minimax with alpha-beta pruning, the terminal test and move generation.
+ */
+import { type Action, type Colour, PLAYER_AXIS, STEAL, isSteal, place } from "@/lib/cachex/types";
+import { type Rng, shuffle } from "@/lib/rng";
+import type { AgentBoard } from "./agent-board";
+import { type BiasFn, evaluate, noBias } from "./evaluation";
+
+export type MoveOrder = "canonical" | Rng;
+
+export interface SearchContext {
+ /**
+ * How candidate moves are ordered. The original shuffles them with
+ * `random.shuffle`; "canonical" sorts them like Python sorts the action
+ * tuples (PLACE by (r, q), then STEAL), which is what the parity tests use.
+ */
+ order: MoveOrder;
+ bias: BiasFn;
+ /** Number of nodes visited (for the UI). */
+ nodes: number;
+ /** Root-level (action, score) pairs, recorded when requested. */
+ rootScores?: { action: Action; score: number }[];
+}
+
+export const createContext = (
+ order: MoveOrder = "canonical",
+ bias: BiasFn = noBias,
+): SearchContext => ({
+ order,
+ bias,
+ nodes: 0,
+});
+
+/**
+ * `game_end`: true if the last PLACE completed a winning chain for the player
+ * who made it (sets `board.winner`). Note the original's quirks are kept: a
+ * full board, a STEAL, or no move yet all count as "not ended".
+ */
+export function gameEnd(board: AgentBoard): boolean {
+ if (board.emptyCount() === 0) return false;
+ const last = board.lastAction;
+ if (last === null || isSteal(last)) return false;
+ const [, r, q] = last;
+ const reachable = board.connectedCoords(r, q);
+ const axis = PLAYER_AXIS[board.lastPlayer];
+ let min = Infinity;
+ let max = -Infinity;
+ for (const c of reachable) {
+ if (c[axis] < min) min = c[axis];
+ if (c[axis] > max) max = c[axis];
+ }
+ if (min === 0 && max === board.n - 1) {
+ board.winner = board.lastPlayer;
+ return true;
+ }
+ return false;
+}
+
+/** `get_valid_actions`: every empty cell, minus the centre on move 1, plus STEAL on move 2. */
+export function getValidActions(board: AgentBoard, order: MoveOrder): Action[] {
+ const centre = Math.floor(board.n / 2);
+ const actions: Action[] = [];
+ for (const [r, q] of board.availableHexagons()) {
+ if (board.turn === 1 && board.isOdd() && r === centre && q === centre) continue;
+ actions.push(place(r, q));
+ }
+ if (board.turn === 2) actions.push(STEAL);
+ // availableHexagons() is already sorted by (r, q) with STEAL appended last,
+ // which matches Python's sort order for ("PLACE", r, q) < ("STEAL",).
+ if (order !== "canonical") shuffle(order, actions);
+ return actions;
+}
+
+/**
+ * `minimax(board, depth, alpha, beta, maximizingPlayer)`.
+ * Red is the maximising player, Blue the minimising player.
+ * Returns [score, action]; action is null at leaves.
+ */
+export function minimax(
+ board: AgentBoard,
+ depth: number,
+ alpha: number,
+ beta: number,
+ maximizingPlayer: boolean,
+ ctx: SearchContext,
+ isRoot = false,
+): [number, Action | null] {
+ ctx.nodes += 1;
+ const player: Colour = maximizingPlayer ? "red" : "blue";
+
+ if (depth === 0 || gameEnd(board)) {
+ if (board.winner === null) return [evaluate(board, ctx.bias), null];
+ return [board.winner === "red" ? Infinity : -Infinity, null];
+ }
+
+ const actions = getValidActions(board, ctx.order);
+
+ if (maximizingPlayer) {
+ let maxScore = -Infinity;
+ let maxAction: Action | null = null;
+ for (const action of actions) {
+ const child = board.clone();
+ child.update(player, action);
+ const [score] = minimax(child, depth - 1, alpha, beta, false, ctx);
+ if (isRoot) ctx.rootScores?.push({ action, score });
+ if (score >= maxScore) {
+ maxScore = score;
+ maxAction = action;
+ }
+ if (maxScore >= alpha) alpha = maxScore;
+ if (alpha >= beta) break;
+ }
+ return [maxScore, maxAction];
+ }
+
+ let minScore = Infinity;
+ let minAction: Action | null = null;
+ for (const action of actions) {
+ const child = board.clone();
+ child.update(player, action);
+ const [score] = minimax(child, depth - 1, alpha, beta, true, ctx);
+ if (isRoot) ctx.rootScores?.push({ action, score });
+ if (score <= minScore) {
+ minScore = score;
+ minAction = action;
+ }
+ if (beta <= minScore) beta = minScore;
+ if (alpha >= beta) break;
+ }
+ return [minScore, minAction];
+}
diff --git a/web/src/lib/agent/player.ts b/web/src/lib/agent/player.ts
new file mode 100644
index 0000000..860752c
--- /dev/null
+++ b/web/src/lib/agent/player.ts
@@ -0,0 +1,137 @@
+/**
+ * Port of the `_4399` Player.action logic
+ * (coursework/Project Part B/code/_4399/player.py):
+ *
+ * 1. forced opening moves on the first two turns,
+ * 2. play an immediately winning move if one exists,
+ * 3. otherwise minimax + alpha-beta with a dynamically allocated depth.
+ */
+import { type Action, type Colour, STEAL, place } from "@/lib/cachex/types";
+import { AgentBoard } from "./agent-board";
+import {
+ type BiasFn,
+ type FeatureContribution,
+ computeFeatures,
+ explainFeatures,
+ noBias,
+} from "./evaluation";
+import { type MoveOrder, createContext, gameEnd, getValidActions, minimax } from "./minimax";
+
+/** Empty-cell ratios at which the search deepens (index + 1 = depth). */
+export const TARGET_RATES = [0.15, 0.1, 0.05] as const;
+
+/** `dynamic_depth_allocation` */
+export function dynamicDepthAllocation(board: AgentBoard): number {
+ const emptyRate = board.emptyCount() / board.n ** 2;
+ for (let i = 0; i < TARGET_RATES.length; i++) {
+ if (emptyRate >= TARGET_RATES[i]) return i + 1;
+ }
+ return 4;
+}
+
+/** `enforced_gamestart_play` — the hand-written opening book. */
+export function enforcedGamestartPlay(
+ n: number,
+ player: Colour,
+ board: AgentBoard,
+): { action: Action; rule: string } {
+ if (n === 3) {
+ if (player === "blue" && board.isOccupied(0, 1)) {
+ return { action: STEAL, rule: "On a 3×3 board Blue steals Red's opening at (0, 1)." };
+ }
+ if (player === "red")
+ return { action: place(1, 0), rule: "On a 3×3 board Red opens at (1, 0)." };
+ return { action: place(0, 1), rule: "On a 3×3 board Blue takes (0, 1)." };
+ }
+ if (player === "blue" && board.isOccupied(1, 1)) {
+ return { action: STEAL, rule: "Red opened on the strong cell (1, 1), so Blue steals it." };
+ }
+ return { action: place(1, 1), rule: "The opening book always plays the strong cell (1, 1)." };
+}
+
+export interface CandidateScore {
+ action: Action;
+ score: number;
+}
+
+export type MoveExplanation =
+ | { kind: "opening"; rule: string }
+ | { kind: "instant-win" }
+ | {
+ kind: "search";
+ depth: number;
+ score: number;
+ nodes: number;
+ candidates: CandidateScore[];
+ /** Features of the board after the chosen move. */
+ features: FeatureContribution[];
+ }
+ | { kind: "random"; options: number };
+
+export interface AgentDecision {
+ action: Action;
+ explanation: MoveExplanation;
+}
+
+export interface AgentOptions {
+ order?: MoveOrder;
+ bias?: BiasFn;
+ /** Use the opening book on turns 1 and 2 (the original's default). */
+ enforceGamePlay?: boolean;
+}
+
+/** Choose the agent's action for `colour`, given the full action history. */
+export function chooseAgentAction(
+ n: number,
+ history: readonly Action[],
+ colour: Colour,
+ options: AgentOptions = {},
+): AgentDecision {
+ const board = AgentBoard.fromActions(n, history);
+ return agentAction(board, colour, options);
+}
+
+export function agentAction(
+ board: AgentBoard,
+ colour: Colour,
+ options: AgentOptions = {},
+): AgentDecision {
+ const { order = "canonical", bias = noBias, enforceGamePlay = true } = options;
+
+ if (board.turn <= 2 && enforceGamePlay) {
+ const { action, rule } = enforcedGamestartPlay(board.n, colour, board);
+ return { action, explanation: { kind: "opening", rule } };
+ }
+
+ // Play an immediate win without searching.
+ for (const action of getValidActions(board, order)) {
+ const tmp = board.clone();
+ tmp.update(colour, action);
+ if (gameEnd(tmp)) return { action, explanation: { kind: "instant-win" } };
+ }
+
+ const depth = dynamicDepthAllocation(board);
+ const ctx = createContext(order, bias);
+ ctx.rootScores = [];
+ const [score, action] = minimax(board, depth, -Infinity, Infinity, colour === "red", ctx, true);
+ if (action === null) throw new Error("minimax found no legal action");
+
+ const after = board.clone();
+ after.update(colour, action);
+ const cmp = (x: number, y: number) => (x === y ? 0 : x < y ? -1 : 1);
+ const candidates = [...ctx.rootScores].sort((a, b) =>
+ colour === "red" ? cmp(b.score, a.score) : cmp(a.score, b.score),
+ );
+
+ return {
+ action,
+ explanation: {
+ kind: "search",
+ depth,
+ score,
+ nodes: ctx.nodes,
+ candidates,
+ features: explainFeatures(computeFeatures(after)),
+ },
+ };
+}
diff --git a/web/src/lib/agent/random-player.ts b/web/src/lib/agent/random-player.ts
new file mode 100644
index 0000000..2e98cda
--- /dev/null
+++ b/web/src/lib/agent/random-player.ts
@@ -0,0 +1,36 @@
+/**
+ * Port of the random baseline used to train/test the agent
+ * (coursework/Project Part B/skeleton-code-B/random_play_agent/player.py).
+ *
+ * On its first move as Blue it steals with probability 1/2; otherwise it
+ * places on a uniformly random empty cell (never the centre on move 1).
+ */
+import { Board } from "@/lib/cachex/board";
+import { type Action, STEAL, place } from "@/lib/cachex/types";
+import { type Rng, choice } from "@/lib/rng";
+import type { AgentDecision } from "./player";
+
+export function chooseRandomAction(n: number, history: readonly Action[], rng: Rng): AgentDecision {
+ const board = new Board(n);
+ history.forEach((action, i) => {
+ if (action[0] === "STEAL") board.swap();
+ else board.place(i % 2 === 0 ? "red" : "blue", action[1], action[2]);
+ });
+ const turn = history.length + 1;
+
+ if (turn === 2 && rng() < 0.5) {
+ return { action: STEAL, explanation: { kind: "random", options: 2 } };
+ }
+
+ const moves: [number, number][] = [];
+ for (let r = 0; r < n; r++) {
+ for (let q = 0; q < n; q++) {
+ if (!board.isOccupied(r, q)) moves.push([r, q]);
+ }
+ }
+ const centre = Math.floor(n / 2);
+ const legal =
+ n % 2 === 1 && turn === 1 ? moves.filter(([r, q]) => r !== centre || q !== centre) : moves;
+ const [r, q] = choice(rng, legal);
+ return { action: place(r, q), explanation: { kind: "random", options: legal.length } };
+}
diff --git a/web/src/lib/agent/run-agent.ts b/web/src/lib/agent/run-agent.ts
new file mode 100644
index 0000000..118dcc7
--- /dev/null
+++ b/web/src/lib/agent/run-agent.ts
@@ -0,0 +1,39 @@
+/**
+ * A single entry point used by the Web Worker (and the main-thread fallback)
+ * to ask either agent for a move.
+ */
+import type { Action, Colour } from "@/lib/cachex/types";
+import { createRng } from "@/lib/rng";
+import { randomBias } from "./evaluation";
+import { type AgentDecision, chooseAgentAction } from "./player";
+import { chooseRandomAction } from "./random-player";
+
+export type AgentKind = "minimax" | "random";
+
+export interface AgentRequest {
+ id: number;
+ kind: AgentKind;
+ n: number;
+ history: Action[];
+ colour: Colour;
+ /** Seeds the move shuffle and evaluation bias (the original used `random`). */
+ seed: number;
+}
+
+export type AgentResponse =
+ | { id: number; ok: true; decision: AgentDecision; elapsedMs: number }
+ | { id: number; ok: false; error: string };
+
+export function runAgent(req: AgentRequest): AgentResponse {
+ const started = performance.now();
+ try {
+ const rng = createRng(req.seed);
+ const decision =
+ req.kind === "random"
+ ? chooseRandomAction(req.n, req.history, rng)
+ : chooseAgentAction(req.n, req.history, req.colour, { order: rng, bias: randomBias(rng) });
+ return { id: req.id, ok: true, decision, elapsedMs: performance.now() - started };
+ } catch (err) {
+ return { id: req.id, ok: false, error: err instanceof Error ? err.message : String(err) };
+ }
+}
diff --git a/web/src/lib/agent/self-play.ts b/web/src/lib/agent/self-play.ts
new file mode 100644
index 0000000..aa83777
--- /dev/null
+++ b/web/src/lib/agent/self-play.ts
@@ -0,0 +1,21 @@
+/**
+ * Deterministic self-play: the agent (canonical move order, no random bias)
+ * playing itself. Used to render a genuine final position on the landing page.
+ */
+import { Game } from "@/lib/cachex/game";
+import type { Action } from "@/lib/cachex/types";
+import { chooseAgentAction } from "./player";
+
+export function deterministicSelfPlay(
+ n: number,
+ maxTurns = 400,
+): { actions: Action[]; game: Game } {
+ const game = new Game(n);
+ const actions: Action[] = [];
+ while (!game.over() && actions.length < maxTurns) {
+ const { action } = chooseAgentAction(n, actions, game.turnPlayer());
+ game.update(game.turnPlayer(), action);
+ actions.push(action);
+ }
+ return { actions, game };
+}
diff --git a/web/src/lib/agent/weights.json b/web/src/lib/agent/weights.json
new file mode 100644
index 0000000..72b0b99
--- /dev/null
+++ b/web/src/lib/agent/weights.json
@@ -0,0 +1,19 @@
+[
+ {
+ "positive_weights": [0.5, 3, 8, 2],
+ "f_name": [
+ "number of empty hexagons",
+ "number of token in triangular",
+ "number of token of each color",
+ "count_token_in_diff_hex_location"
+ ]
+ },
+
+ {
+ "negative_weights": [4, 3],
+ "f_name": [
+ "number of token in a capture-able diamond shape",
+ "number of token in weakness"
+ ]
+ }
+]
diff --git a/web/src/lib/astar/astar.test.ts b/web/src/lib/astar/astar.test.ts
new file mode 100644
index 0000000..3e35ffe
--- /dev/null
+++ b/web/src/lib/astar/astar.test.ts
@@ -0,0 +1,132 @@
+import { readFileSync } from "node:fs";
+import { resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+import { describe, expect, it } from "vitest";
+
+import { partA } from "@/lib/__fixtures__/load";
+import { AStarInputError, astar, distanceDiff, formatCliOutput } from "./astar";
+import { parsePartAInput, stringifyPartAInput } from "./input";
+import { PRESETS } from "./presets";
+import { pythonNeighbourOrder, pythonTupleHash, toSigned64 } from "./python-set-order";
+
+const fixtures = partA();
+const blockOf = (b: "Red" | "Blue" | null) => (b === null ? null : b === "Red" ? "red" : "blue");
+
+describe("CPython set-order simulation", () => {
+ it("reproduces hash((r, q)) from CPython", () => {
+ // values printed by CPython 3.12
+ expect(toSigned64(pythonTupleHash([2, 3]))).toBe(8409376899596376432n);
+ expect(toSigned64(pythonTupleHash([0, 0]))).toBe(-8458139203682520985n);
+ });
+
+ it("matches HexNode.next iteration order for every cell, n = 1..14", () => {
+ for (const [nKey, cells] of Object.entries(fixtures.neighbourOrders)) {
+ const n = Number(nKey);
+ cells.forEach((expected, i) => {
+ const r = Math.floor(i / n);
+ const q = i % n;
+ expect(pythonNeighbourOrder(n, r, q), `n=${n} (${r},${q})`).toEqual(expected);
+ });
+ }
+ });
+});
+
+describe("A* parity with the original CachexBoard.AStar", () => {
+ it.each(
+ fixtures.cases.map((c, i) => [`${c.name} ${c.heuristic} block=${c.block} #${i}`, c] as const),
+ )("%s", (_, c) => {
+ const board = parsePartAInput(JSON.stringify(c.input));
+ const result = astar(board, c.heuristic, blockOf(c.block));
+ expect(result.path).toEqual(c.path);
+ expect(result.pops).toBe(c.pops);
+ expect(result.pushes).toBe(c.pushes);
+ });
+
+ it("covers reachable and unreachable goals", () => {
+ expect(fixtures.cases.some((c) => c.path.length === 0)).toBe(true);
+ expect(fixtures.cases.some((c) => c.path.length > 8)).toBe(true);
+ });
+});
+
+const CODE_DIR = fileURLToPath(
+ new URL("../../../../coursework/Project Part A/code/", import.meta.url),
+);
+
+/** Parse a recorded sample_output*.txt: a length line, then "(r, q)" per line. */
+function readRecordedOutput(file: string) {
+ const [count, ...lines] = readFileSync(resolve(CODE_DIR, file), "utf8").trim().split(/\r?\n/);
+ const path = lines.map((l) => {
+ const m = /^\((\d+),\s*(\d+)\)$/.exec(l.trim());
+ if (!m) throw new Error(`unexpected line in ${file}: ${l}`);
+ return [Number(m[1]), Number(m[2])];
+ });
+ expect(path).toHaveLength(Number(count));
+ return path;
+}
+
+describe("original recorded outputs", () => {
+ it.each([
+ ["sample_input.json", "sample_output.txt", "sample-1"],
+ ["sample_input2.json", "sample_output2.txt", "sample-2"],
+ ])("%s → %s, read from coursework/, for both heuristics", (input, output, presetId) => {
+ const recorded = readRecordedOutput(output);
+ const board = parsePartAInput(readFileSync(resolve(CODE_DIR, input), "utf8"));
+ const preset = PRESETS.find((p) => p.id === presetId)!;
+ expect(parsePartAInput(JSON.stringify(preset.input))).toEqual(board);
+ expect(preset.originalPath).toEqual(recorded);
+ expect(preset.originalHeuristic).toBe("manhattan");
+ for (const heuristic of ["manhattan", "euclidean"] as const) {
+ expect(astar(board, heuristic).path, heuristic).toEqual(recorded);
+ }
+ });
+
+ it("CLI output format (search/main.py) for sample_input.json", () => {
+ const preset = PRESETS.find((p) => p.id === "sample-1")!;
+ const result = astar(parsePartAInput(JSON.stringify(preset.input)), "euclidean");
+ expect(formatCliOutput(result.path)).toBe(
+ ["8", "(4,2)", "(4,1)", "(3,1)", "(2,1)", "(1,2)", "(0,2)", "(0,1)", "(0,0)"].join("\n"),
+ );
+ });
+
+ it.each(PRESETS.map((p) => [p.label, p] as const))(
+ "%s matches the recorded path",
+ (_, preset) => {
+ const result = astar(
+ parsePartAInput(JSON.stringify(preset.input)),
+ preset.originalHeuristic ?? "euclidean",
+ );
+ expect(result.path).toEqual(preset.originalPath ?? []);
+ },
+ );
+});
+
+describe("heuristics", () => {
+ it("Manhattan and Euclidean follow the Minkowski formula", () => {
+ expect(distanceDiff([0, 0], [3, 4], "manhattan")).toBe(7);
+ expect(distanceDiff([0, 0], [3, 4], "euclidean")).toBe(5);
+ });
+});
+
+describe("input format", () => {
+ it("round-trips the original JSON format", () => {
+ const text = JSON.stringify(PRESETS[1].input);
+ const board = parsePartAInput(text);
+ expect(parsePartAInput(stringifyPartAInput(board))).toEqual(board);
+ });
+
+ it("rejects malformed input with a helpful message", () => {
+ expect(() => parsePartAInput("{")).toThrow(AStarInputError);
+ expect(() => parsePartAInput('{"n": 3, "start": [0, 0]}')).toThrow(/goal/);
+ expect(() =>
+ parsePartAInput('{"n": 3, "board": [["b", 5, 0]], "start": [0,0], "goal": [1,1]}'),
+ ).toThrow(/outside/);
+ });
+
+ it("refuses an occupied start when every tile blocks (KeyError in the original)", () => {
+ const board = parsePartAInput(
+ '{"n": 3, "board": [["r", 0, 0]], "start": [0, 0], "goal": [2, 2]}',
+ );
+ expect(() => astar(board, "manhattan", null)).toThrow(AStarInputError);
+ expect(astar(board, "manhattan", "blue").path.length).toBeGreaterThan(0);
+ });
+});
diff --git a/web/src/lib/astar/astar.ts b/web/src/lib/astar/astar.ts
new file mode 100644
index 0000000..3a70020
--- /dev/null
+++ b/web/src/lib/astar/astar.ts
@@ -0,0 +1,168 @@
+/**
+ * Port of `CachexBoard.AStar` (coursework/Project Part A/code/cachex/CachexBoard.py)
+ * with the Minkowski heuristics from `HexNode.distance_diff`.
+ *
+ * Faithful details that affect the output:
+ * - the open set is a priority queue of [f, insert_order, node]; a node whose
+ * g improves while it is still queued keeps its old f in the queue;
+ * - closed nodes can be re-opened if a cheaper route to them is found;
+ * - neighbours are visited in CPython set-iteration order (see python-set-order.ts).
+ *
+ * The port additionally records a trace of every expansion for the A* Lab.
+ */
+import type { Colour, Coord } from "@/lib/cachex/types";
+import { PriorityQueue } from "./priority-queue";
+import { pythonNeighbourOrder } from "./python-set-order";
+
+export type Heuristic = "manhattan" | "euclidean";
+/** Which colour's tiles block the search; null means every tile blocks (the CLI default). */
+export type BlockMode = Colour | null;
+export type CellState = Colour | null;
+
+export interface AStarBoard {
+ n: number;
+ /** Row-major cell states: index r * n + q. */
+ cells: CellState[];
+ start: Coord;
+ goal: Coord;
+}
+
+export interface AStarStep {
+ /** The node popped from the priority queue. */
+ node: Coord;
+ /** g-score of the node when it was popped. */
+ g: number;
+ /** f-score it was queued with. */
+ f: number;
+ /** Nodes newly pushed onto the queue while expanding this node. */
+ pushed: Coord[];
+ /** Nodes whose g improved while they were already queued. */
+ improved: Coord[];
+}
+
+export interface AStarResult {
+ /** Start-to-goal path (inclusive), or [] when the goal is unreachable. */
+ path: Coord[];
+ /** Priority-queue pops (node expansions, including the goal). */
+ pops: number;
+ /** Priority-queue pushes (including the start node). */
+ pushes: number;
+ steps: AStarStep[];
+}
+
+export const HEURISTIC_P: Record = { manhattan: 1, euclidean: 2 };
+
+/** `HexNode.minkowski` */
+export function minkowski(a: Coord, b: Coord, p: number): number {
+ return Math.pow(Math.pow(Math.abs(a[0] - b[0]), p) + Math.pow(Math.abs(a[1] - b[1]), p), 1 / p);
+}
+
+export function distanceDiff(a: Coord, b: Coord, heuristic: Heuristic): number {
+ return minkowski(a, b, HEURISTIC_P[heuristic]);
+}
+
+export class AStarInputError extends Error {}
+
+export function validateBoard(board: AStarBoard): void {
+ const { n, start, goal, cells } = board;
+ if (!Number.isInteger(n) || n < 1) throw new AStarInputError("n must be a positive integer");
+ if (cells.length !== n * n) throw new AStarInputError("cells must have n × n entries");
+ // The original only checks the upper bound (InvalidStartError / InvalidGoalError).
+ const inside = ([r, q]: Coord) => r >= 0 && q >= 0 && r < n && q < n;
+ if (!inside(start))
+ throw new AStarInputError("Current start point out of board existing board dimension.");
+ if (!inside(goal))
+ throw new AStarInputError("Current goal point out of board existing board dimension.");
+}
+
+export function astar(
+ board: AStarBoard,
+ heuristic: Heuristic,
+ block: BlockMode = null,
+): AStarResult {
+ validateBoard(board);
+ const { n, cells, start, goal } = board;
+ const id = (c: Coord) => c[0] * n + c[1];
+ const coordOf = (i: number): Coord => [Math.floor(i / n), i % n];
+
+ const traversable = (i: number) => (block !== null ? cells[i] !== block : cells[i] === null);
+
+ // With no block colour, only empty cells get a score entry; a non-empty start
+ // raises a KeyError in the original.
+ if (block === null && cells[id(start)] !== null) {
+ throw new AStarInputError("The start cell must be empty when every tile blocks the search.");
+ }
+
+ const g = new Float64Array(n * n).fill(Infinity);
+ const h = new Float64Array(n * n).fill(Infinity);
+ const f = new Float64Array(n * n).fill(Infinity);
+
+ const queue = new PriorityQueue();
+ const explored = new Map();
+ const tracker = new Set([id(start)]);
+ let insertOrder = 0;
+ let pushes = 0;
+ let pops = 0;
+ const steps: AStarStep[] = [];
+
+ queue.put({ f: 0, order: insertOrder, value: id(start) });
+ pushes++;
+ g[id(start)] = 0;
+ h[id(start)] = distanceDiff(start, goal, heuristic);
+
+ const goalId = id(goal);
+
+ while (!queue.empty()) {
+ const item = queue.get();
+ pops++;
+ const current = item.value;
+ tracker.delete(current);
+ const step: AStarStep = {
+ node: coordOf(current),
+ g: g[current],
+ f: item.f,
+ pushed: [],
+ improved: [],
+ };
+ steps.push(step);
+
+ if (current === goalId) {
+ const path: number[] = [];
+ let node = current;
+ while (explored.has(node)) {
+ node = explored.get(node)!;
+ path.push(node);
+ }
+ path.unshift(goalId);
+ return { path: path.reverse().map(coordOf), pops, pushes, steps };
+ }
+
+ const [r, q] = coordOf(current);
+ for (const next of pythonNeighbourOrder(n, r, q)) {
+ const ni = id(next);
+ if (!traversable(ni)) continue;
+ if (g[current] + 1 < g[ni]) {
+ g[ni] = g[current] + 1;
+ h[ni] = distanceDiff(next, goal, heuristic);
+ f[ni] = g[ni] + h[ni];
+ explored.set(ni, current);
+ if (!tracker.has(ni)) {
+ insertOrder++;
+ queue.put({ f: f[ni], order: insertOrder, value: ni });
+ pushes++;
+ tracker.add(ni);
+ step.pushed.push(next);
+ } else {
+ step.improved.push(next);
+ }
+ }
+ }
+ }
+
+ return { path: [], pops, pushes, steps };
+}
+
+/** Output in the original CLI format: the path length, then one "(r,q)" per line. */
+export function formatCliOutput(path: readonly Coord[]): string {
+ return [String(path.length), ...path.map(([r, q]) => `(${r},${q})`)].join("\n");
+}
diff --git a/web/src/lib/astar/input.ts b/web/src/lib/astar/input.ts
new file mode 100644
index 0000000..2c2570a
--- /dev/null
+++ b/web/src/lib/astar/input.ts
@@ -0,0 +1,88 @@
+/**
+ * Read and write the original Part A input format (sample_input.json):
+ *
+ * { "n": 5, "board": [["b", 1, 0], ["r", 3, 2]], "start": [4, 2], "goal": [0, 0] }
+ */
+import type { Coord } from "@/lib/cachex/types";
+import { AStarInputError, type AStarBoard, type CellState } from "./astar";
+
+export interface PartAInput {
+ n: number;
+ board: [string, number, number][];
+ start: [number, number];
+ goal: [number, number];
+}
+
+const isInt = (x: unknown): x is number => typeof x === "number" && Number.isInteger(x);
+const isPair = (x: unknown): x is [number, number] =>
+ Array.isArray(x) && x.length === 2 && isInt(x[0]) && isInt(x[1]);
+
+export function parsePartAInput(text: string): AStarBoard {
+ let raw: unknown;
+ try {
+ raw = JSON.parse(text);
+ } catch {
+ throw new AStarInputError("That isn't valid JSON.");
+ }
+ if (typeof raw !== "object" || raw === null) throw new AStarInputError("Expected a JSON object.");
+ const data = raw as Record;
+ if (!isInt(data.n) || data.n < 1) throw new AStarInputError('"n" must be a positive integer.');
+ if (data.n > 30)
+ throw new AStarInputError("Boards larger than 30 × 30 are not supported in the lab.");
+ if (!isPair(data.start)) throw new AStarInputError('"start" must be a pair [r, q].');
+ if (!isPair(data.goal)) throw new AStarInputError('"goal" must be a pair [r, q].');
+ const n = data.n;
+ const board = data.board ?? [];
+ if (!Array.isArray(board))
+ throw new AStarInputError('"board" must be a list of [colour, r, q] entries.');
+
+ const cells: CellState[] = new Array(n * n).fill(null);
+ for (const entry of board) {
+ if (
+ !Array.isArray(entry) ||
+ entry.length !== 3 ||
+ typeof entry[0] !== "string" ||
+ !isInt(entry[1]) ||
+ !isInt(entry[2])
+ ) {
+ throw new AStarInputError('Each board entry must look like ["b", r, q].');
+ }
+ const [colour, r, q] = entry as [string, number, number];
+ if (r < 0 || q < 0 || r >= n || q >= n) {
+ throw new AStarInputError(`Board entry (${r}, ${q}) is outside an n = ${n} board.`);
+ }
+ const c = colour.toLowerCase();
+ if (c === "r") cells[r * n + q] = "red";
+ else if (c === "b") cells[r * n + q] = "blue";
+ }
+
+ return { n, cells, start: data.start as Coord, goal: data.goal as Coord };
+}
+
+export function toPartAInput(board: AStarBoard): PartAInput {
+ const entries: [string, number, number][] = [];
+ board.cells.forEach((cell, i) => {
+ if (cell !== null)
+ entries.push([cell === "red" ? "r" : "b", Math.floor(i / board.n), i % board.n]);
+ });
+ return {
+ n: board.n,
+ board: entries,
+ start: [board.start[0], board.start[1]],
+ goal: [board.goal[0], board.goal[1]],
+ };
+}
+
+/** Pretty JSON in the same shape as the original sample files. */
+export function stringifyPartAInput(board: AStarBoard): string {
+ const input = toPartAInput(board);
+ const tiles = input.board.map((t) => ` ${JSON.stringify(t).replace(/,/g, ", ")}`).join(",\n");
+ return [
+ "{",
+ ` "n": ${input.n},`,
+ ` "board": [${tiles ? `\n${tiles}\n ` : ""}],`,
+ ` "start": [${input.start.join(", ")}],`,
+ ` "goal": [${input.goal.join(", ")}]`,
+ "}",
+ ].join("\n");
+}
diff --git a/web/src/lib/astar/playback.test.ts b/web/src/lib/astar/playback.test.ts
new file mode 100644
index 0000000..82135b1
--- /dev/null
+++ b/web/src/lib/astar/playback.test.ts
@@ -0,0 +1,25 @@
+import { describe, expect, it } from "vitest";
+
+import { astar } from "./astar";
+import { parsePartAInput } from "./input";
+import { searchFrame } from "./playback";
+import { PRESETS } from "./presets";
+
+describe("searchFrame", () => {
+ const board = parsePartAInput(JSON.stringify(PRESETS[0].input));
+ const result = astar(board, "manhattan");
+
+ it("starts with only the start node open", () => {
+ const f = searchFrame(result, board.n, board.start, 0);
+ expect([...f.open]).toEqual([board.start[0] * board.n + board.start[1]]);
+ expect(f.closed.size).toBe(0);
+ expect(f.current).toBeNull();
+ });
+
+ it("ends with the same counters as the full search", () => {
+ const f = searchFrame(result, board.n, board.start, Infinity);
+ expect(f.done).toBe(true);
+ expect(f.expanded).toBe(result.pops);
+ expect(f.pushes).toBe(result.pushes);
+ });
+});
diff --git a/web/src/lib/astar/playback.ts b/web/src/lib/astar/playback.ts
new file mode 100644
index 0000000..aee0db2
--- /dev/null
+++ b/web/src/lib/astar/playback.ts
@@ -0,0 +1,47 @@
+/**
+ * Reconstruct the A* open/closed sets at any point of a recorded search, for
+ * the step-by-step animation in the A* Lab.
+ */
+import type { Coord } from "@/lib/cachex/types";
+import type { AStarResult } from "./astar";
+
+export interface SearchFrame {
+ /** Number of expansions shown (0 .. steps.length). */
+ index: number;
+ open: Set;
+ closed: Set;
+ current: number | null;
+ expanded: number;
+ pushes: number;
+ done: boolean;
+}
+
+export function searchFrame(
+ result: AStarResult,
+ n: number,
+ start: Coord,
+ index: number,
+): SearchFrame {
+ const k = Math.max(0, Math.min(index, result.steps.length));
+ const id = (c: Coord) => c[0] * n + c[1];
+ const open = new Set([id(start)]);
+ const popped = new Set();
+ let pushes = 1;
+ for (let i = 0; i < k; i++) {
+ const step = result.steps[i];
+ open.delete(id(step.node));
+ popped.add(id(step.node));
+ for (const c of step.pushed) open.add(id(c));
+ pushes += step.pushed.length;
+ }
+ const closed = new Set([...popped].filter((x) => !open.has(x)));
+ return {
+ index: k,
+ open,
+ closed,
+ current: k > 0 ? id(result.steps[k - 1].node) : null,
+ expanded: k,
+ pushes,
+ done: k === result.steps.length,
+ };
+}
diff --git a/web/src/lib/astar/presets.ts b/web/src/lib/astar/presets.ts
new file mode 100644
index 0000000..f58d168
--- /dev/null
+++ b/web/src/lib/astar/presets.ts
@@ -0,0 +1,141 @@
+/**
+ * Boards from the original repository: the two sample inputs shipped with
+ * Part A (and their recorded outputs), plus the group-defined test boards from
+ * "Part A Testing Nodebook.ipynb".
+ */
+import type { Coord } from "@/lib/cachex/types";
+import type { Heuristic } from "./astar";
+import type { PartAInput } from "./input";
+
+export interface Preset {
+ id: string;
+ label: string;
+ source: string;
+ input: PartAInput;
+ /** Path recorded in the original repo, if any. */
+ originalPath?: Coord[] | null;
+ /** Heuristic used when the original output was recorded. */
+ originalHeuristic?: Heuristic;
+}
+
+const BASE: [string, number, number][] = [
+ ["b", 1, 0],
+ ["b", 1, 1],
+ ["b", 3, 2],
+ ["b", 1, 3],
+];
+
+const c = (pairs: [number, number][]): Coord[] => pairs;
+
+export const PRESETS: readonly Preset[] = [
+ {
+ id: "sample-1",
+ label: "Sample input 1",
+ // sample_output.txt was written by notebook cell 5 with heuristic="manhattan".
+ source: "code/sample_input.json → sample_output.txt",
+ input: { n: 5, board: BASE, start: [4, 2], goal: [0, 0] },
+ originalPath: c([
+ [4, 2],
+ [4, 1],
+ [3, 1],
+ [2, 1],
+ [1, 2],
+ [0, 2],
+ [0, 1],
+ [0, 0],
+ ]),
+ originalHeuristic: "manhattan",
+ },
+ {
+ id: "sample-2",
+ label: "Sample input 2",
+ // sample_output2.txt matches notebook cell 14, which also uses "manhattan".
+ source: "code/sample_input2.json → sample_output2.txt",
+ input: {
+ n: 5,
+ board: [
+ ["b", 3, 1],
+ ["b", 3, 2],
+ ["b", 3, 3],
+ ["b", 3, 4],
+ ["b", 1, 0],
+ ["b", 1, 1],
+ ["b", 1, 2],
+ ["b", 1, 3],
+ ],
+ start: [4, 2],
+ goal: [0, 0],
+ },
+ originalPath: c([
+ [4, 2],
+ [4, 1],
+ [4, 0],
+ [3, 0],
+ [2, 1],
+ [2, 2],
+ [2, 3],
+ [1, 4],
+ [0, 4],
+ [0, 3],
+ [0, 2],
+ [0, 1],
+ [0, 0],
+ ]),
+ originalHeuristic: "manhattan",
+ },
+ {
+ id: "notebook-short",
+ label: "Notebook: short hop",
+ source: "Part A Testing Nodebook.ipynb",
+ input: { n: 5, board: BASE, start: [4, 2], goal: [1, 4] },
+ originalPath: c([
+ [4, 2],
+ [3, 3],
+ [2, 4],
+ [1, 4],
+ ]),
+ originalHeuristic: "manhattan",
+ },
+ {
+ id: "notebook-diagonal",
+ label: "Notebook: corner to corner",
+ source: "Part A Testing Nodebook.ipynb",
+ input: { n: 5, board: BASE, start: [4, 0], goal: [0, 4] },
+ originalPath: c([
+ [4, 0],
+ [3, 1],
+ [2, 2],
+ [1, 2],
+ [0, 3],
+ [0, 4],
+ ]),
+ originalHeuristic: "manhattan",
+ },
+ {
+ id: "notebook-detour",
+ label: "Notebook: forced detour",
+ source: "Part A Testing Nodebook.ipynb",
+ input: { n: 5, board: [...BASE, ["b", 0, 3]], start: [0, 0], goal: [0, 4] },
+ originalPath: c([
+ [0, 0],
+ [0, 1],
+ [0, 2],
+ [1, 2],
+ [2, 2],
+ [2, 3],
+ [1, 4],
+ [0, 4],
+ ]),
+ originalHeuristic: "manhattan",
+ },
+ {
+ id: "notebook-blocked",
+ label: "Notebook: no path",
+ source: "Part A Testing Nodebook.ipynb",
+ input: { n: 5, board: [...BASE, ["b", 0, 3], ["b", 1, 2]], start: [4, 0], goal: [0, 0] },
+ originalPath: null,
+ originalHeuristic: "manhattan",
+ },
+];
+
+export const DEFAULT_PRESET = PRESETS[0];
diff --git a/web/src/lib/astar/priority-queue.ts b/web/src/lib/astar/priority-queue.ts
new file mode 100644
index 0000000..f739720
--- /dev/null
+++ b/web/src/lib/astar/priority-queue.ts
@@ -0,0 +1,59 @@
+/**
+ * Binary min-heap with the same ordering as Python's `queue.PriorityQueue`
+ * holding `[f, insert_order, node]` lists: compare by f, then by insert order
+ * (insert orders are unique, so the node itself is never compared).
+ */
+export interface QueueItem {
+ f: number;
+ order: number;
+ value: T;
+}
+
+const less = (a: QueueItem, b: QueueItem) =>
+ a.f < b.f || (a.f === b.f && a.order < b.order);
+
+export class PriorityQueue {
+ private heap: QueueItem[] = [];
+
+ get size(): number {
+ return this.heap.length;
+ }
+
+ empty(): boolean {
+ return this.heap.length === 0;
+ }
+
+ put(item: QueueItem): void {
+ const h = this.heap;
+ h.push(item);
+ let i = h.length - 1;
+ while (i > 0) {
+ const parent = (i - 1) >> 1;
+ if (!less(h[i], h[parent])) break;
+ [h[i], h[parent]] = [h[parent], h[i]];
+ i = parent;
+ }
+ }
+
+ get(): QueueItem {
+ const h = this.heap;
+ if (h.length === 0) throw new Error("get() from an empty priority queue");
+ const top = h[0];
+ const last = h.pop()!;
+ if (h.length > 0) {
+ h[0] = last;
+ let i = 0;
+ for (;;) {
+ const l = 2 * i + 1;
+ const r = l + 1;
+ let m = i;
+ if (l < h.length && less(h[l], h[m])) m = l;
+ if (r < h.length && less(h[r], h[m])) m = r;
+ if (m === i) break;
+ [h[i], h[m]] = [h[m], h[i]];
+ i = m;
+ }
+ }
+ return top;
+ }
+}
diff --git a/web/src/lib/astar/python-set-order.ts b/web/src/lib/astar/python-set-order.ts
new file mode 100644
index 0000000..00f0e8c
--- /dev/null
+++ b/web/src/lib/astar/python-set-order.ts
@@ -0,0 +1,181 @@
+/**
+ * The original A* iterates `HexNode.next`, a Python `set` of (r, q) tuples.
+ * Because the priority queue breaks ties by insertion order, the order in
+ * which neighbours come out of that set decides which of several equal-cost
+ * paths is returned (and how many nodes are expanded).
+ *
+ * To reproduce the original output exactly, this module simulates CPython
+ * 3.8+ semantics: the xxHash-based tuple hash and the open-addressing set
+ * table (linear probes of 9, perturbation shift 5, resize when 3/5 full).
+ * Parity is checked against CPython 3.12 in the vitest suite.
+ */
+import type { Coord } from "@/lib/cachex/types";
+
+const MASK64 = (1n << 64n) - 1n;
+const XXPRIME_1 = 11400714785074694791n;
+const XXPRIME_2 = 14029467366897019727n;
+const XXPRIME_5 = 2870177450012600261n;
+const LINEAR_PROBES = 9;
+const PERTURB_SHIFT = 5n;
+const SET_MINSIZE = 8;
+
+function intHash(k: number): bigint {
+ // hash(-1) == -2 in CPython; every other small int hashes to itself.
+ const h = k === -1 ? -2n : BigInt(k);
+ return h & MASK64; // unsigned (size_t) view of Py_hash_t
+}
+
+/** `hash((a, b, ...))` for small ints, as an unsigned 64-bit value. */
+export function pythonTupleHash(items: readonly number[]): bigint {
+ let acc = XXPRIME_5;
+ for (const item of items) {
+ acc = (acc + intHash(item) * XXPRIME_2) & MASK64;
+ acc = ((acc << 31n) | (acc >> 33n)) & MASK64;
+ acc = (acc * XXPRIME_1) & MASK64;
+ }
+ acc = (acc + (BigInt(items.length) ^ (XXPRIME_5 ^ 3527539n))) & MASK64;
+ if (acc === MASK64) return 1546275796n;
+ return acc;
+}
+
+/** Signed view, for comparing with Python's `hash()` output. */
+export const toSigned64 = (h: bigint) => (h >= 1n << 63n ? h - (1n << 64n) : h);
+
+type Slot = { key: string; hash: bigint } | "dummy" | null;
+
+class PySetSimulator {
+ table: Slot[] = new Array(SET_MINSIZE).fill(null);
+ mask = SET_MINSIZE - 1;
+ fill = 0;
+ used = 0;
+
+ add(key: string, hash: bigint): void {
+ const mask = BigInt(this.mask);
+ let i = hash & mask;
+ let perturb = hash;
+ let freeslot: number | null = null;
+ for (;;) {
+ let idx = Number(i);
+ let probes = idx + LINEAR_PROBES <= this.mask ? LINEAR_PROBES : 0;
+ do {
+ const slot = this.table[idx];
+ if (slot === null) {
+ if (freeslot !== null) {
+ this.used++;
+ this.table[freeslot] = { key, hash };
+ return;
+ }
+ this.fill++;
+ this.used++;
+ this.table[idx] = { key, hash };
+ if (this.fill * 5 >= this.mask * 3) this.resize(this.used * 4);
+ return;
+ }
+ if (slot === "dummy") {
+ if (freeslot === null) freeslot = idx;
+ } else if (slot.hash === hash && slot.key === key) {
+ return; // already present
+ }
+ idx++;
+ } while (probes-- > 0);
+ perturb >>= PERTURB_SHIFT;
+ i = (i * 5n + 1n + perturb) & mask;
+ }
+ }
+
+ private resize(minused: number): void {
+ let newsize = SET_MINSIZE;
+ while (newsize <= minused) newsize <<= 1;
+ const old = this.table;
+ this.table = new Array(newsize).fill(null);
+ this.mask = newsize - 1;
+ this.fill = this.used;
+ for (const slot of old) {
+ if (slot !== null && slot !== "dummy") this.insertClean(slot.key, slot.hash);
+ }
+ }
+
+ private insertClean(key: string, hash: bigint): void {
+ const mask = BigInt(this.mask);
+ let perturb = hash;
+ let i = hash & mask;
+ for (;;) {
+ let idx = Number(i);
+ if (this.table[idx] === null) {
+ this.table[idx] = { key, hash };
+ return;
+ }
+ if (idx + LINEAR_PROBES <= this.mask) {
+ for (let j = 0; j < LINEAR_PROBES; j++) {
+ idx++;
+ if (this.table[idx] === null) {
+ this.table[idx] = { key, hash };
+ return;
+ }
+ }
+ }
+ perturb >>= PERTURB_SHIFT;
+ i = (i * 5n + 1n + perturb) & mask;
+ }
+ }
+
+ discard(key: string): void {
+ const idx = this.table.findIndex((s) => s !== null && s !== "dummy" && s.key === key);
+ if (idx >= 0) {
+ this.table[idx] = "dummy";
+ this.used--;
+ }
+ }
+
+ keys(): string[] {
+ const out: string[] = [];
+ for (const slot of this.table) if (slot !== null && slot !== "dummy") out.push(slot.key);
+ return out;
+ }
+}
+
+/** Per-board-size cache of neighbour orders (only a few sizes are kept). */
+const cache = new Map();
+const MAX_CACHED_SIZES = 4;
+const hashCache = new Map();
+
+function cellHash(a: number, b: number): bigint {
+ const key = `${a},${b}`;
+ let h = hashCache.get(key);
+ if (h === undefined) {
+ h = pythonTupleHash([a, b]);
+ hashCache.set(key, h);
+ }
+ return h;
+}
+
+/**
+ * `HexNode.find_next_moves` for cell (r, q) on an n×n board, returned in the
+ * order CPython iterates the resulting set.
+ */
+export function pythonNeighbourOrder(n: number, r: number, q: number): Coord[] {
+ let perSize = cache.get(n);
+ if (!perSize) {
+ perSize = new Array(n * n);
+ cache.set(n, perSize);
+ if (cache.size > MAX_CACHED_SIZES) cache.delete(cache.keys().next().value!);
+ }
+ const hit = perSize[r * n + q];
+ if (hit) return hit;
+
+ const set = new PySetSimulator();
+ const inBoard = (a: number, b: number) => a >= 0 && a < n && b >= 0 && b < n;
+ for (let a = r - 1; a < r + 2; a++) {
+ for (let b = q - 1; b < q + 2; b++) {
+ if (inBoard(a, b)) set.add(`${a},${b}`, cellHash(a, b));
+ }
+ }
+ // remove the two diagonal cells along the major axis, and the cell itself
+ set.discard(`${r - 1},${q - 1}`);
+ set.discard(`${r + 1},${q + 1}`);
+ set.discard(`${r},${q}`);
+
+ const order = set.keys().map((k) => k.split(",").map(Number) as unknown as Coord);
+ perSize[r * n + q] = order;
+ return order;
+}
diff --git a/web/src/lib/astar/random-board.test.ts b/web/src/lib/astar/random-board.test.ts
new file mode 100644
index 0000000..b554547
--- /dev/null
+++ b/web/src/lib/astar/random-board.test.ts
@@ -0,0 +1,39 @@
+import { describe, expect, it } from "vitest";
+
+import { createRng } from "@/lib/rng";
+import { astar } from "./astar";
+import { notebookExpansions, randomNotebookBoard, runHeuristicBenchmark } from "./random-board";
+
+describe("notebook random board generator", () => {
+ it("produces distinct, empty start and goal cells", () => {
+ const rng = createRng(42);
+ for (let d = 2; d < 30; d++) {
+ const board = randomNotebookBoard(d, rng);
+ const { start, goal, cells, n } = board;
+ expect(start).not.toEqual(goal);
+ expect(cells[start[0] * n + start[1]]).toBeNull();
+ expect(cells[goal[0] * n + goal[1]]).toBeNull();
+ // at most (d*d - d) / 2 barriers
+ expect(cells.filter(Boolean).length).toBeLessThanOrEqual(Math.floor((d * d - d) / 2));
+ }
+ });
+
+ it("benchmark is reproducible for a seed", () => {
+ const dims = [5, 10, 20];
+ expect(runHeuristicBenchmark(dims, 3)).toEqual(runHeuristicBenchmark(dims, 3));
+ });
+
+ it("charts the notebook's insertion counter (pushes - 1), not queue pops", () => {
+ const dims = [2, 7, 15, 31];
+ const rows = runHeuristicBenchmark(dims, 11);
+ const rng = createRng(11);
+ dims.forEach((d, i) => {
+ const board = randomNotebookBoard(d, rng);
+ const m = astar(board, "manhattan");
+ const e = astar(board, "euclidean");
+ expect(rows[i].manhattan).toBe(m.pushes - 1);
+ expect(rows[i].euclidean).toBe(e.pushes - 1);
+ });
+ expect(notebookExpansions({ pushes: 1 })).toBe(0);
+ });
+});
diff --git a/web/src/lib/astar/random-board.ts b/web/src/lib/astar/random-board.ts
new file mode 100644
index 0000000..7992c52
--- /dev/null
+++ b/web/src/lib/astar/random-board.ts
@@ -0,0 +1,63 @@
+/**
+ * Port of the random board generator used for the heuristic study in
+ * "Part A Testing Nodebook.ipynb", plus the benchmark loop that compares
+ * Manhattan and Euclidean node expansions.
+ */
+import type { Coord } from "@/lib/cachex/types";
+import { type Rng, createRng, randInt, sample } from "@/lib/rng";
+import { type AStarBoard, type AStarResult, type CellState, astar } from "./astar";
+
+/**
+ * barriers = sample(nodes, randint(0, d*d - d)); barriers = sample(barriers, len // divisor);
+ * start/goal are distinct non-barrier cells. Barriers are blue tiles.
+ */
+export function randomNotebookBoard(dimension: number, rng: Rng, divisor = 2): AStarBoard {
+ const nodes: Coord[] = [];
+ for (let r = 0; r < dimension; r++) for (let q = 0; q < dimension; q++) nodes.push([r, q]);
+
+ let barriers = sample(rng, nodes, randInt(rng, 0, dimension * dimension - dimension));
+ barriers = sample(rng, barriers, Math.floor(barriers.length / divisor));
+ const blocked = new Set(barriers.map(([r, q]) => r * dimension + q));
+
+ const free = nodes.filter(([r, q]) => !blocked.has(r * dimension + q));
+ const [start] = sample(rng, free, 1);
+ const [goal] = sample(
+ rng,
+ free.filter((c) => c !== start),
+ 1,
+ );
+
+ const cells: CellState[] = new Array(dimension * dimension).fill(null);
+ for (const i of blocked) cells[i] = "blue";
+ return { n: dimension, cells, start, goal };
+}
+
+export interface BenchmarkRow {
+ dimension: number;
+ manhattan: number;
+ euclidean: number;
+ pathFound: boolean;
+}
+
+/**
+ * The notebook's "node expansion" metric: the `order` insertion counter its
+ * AStar returns. It starts at 0 for the start node and is incremented on every
+ * later push, so it equals pushes - 1 (not the number of queue pops).
+ */
+export const notebookExpansions = (result: Pick) => result.pushes - 1;
+
+/** The notebook metric for each heuristic on one random board per dimension. */
+export function runHeuristicBenchmark(dimensions: readonly number[], seed: number): BenchmarkRow[] {
+ const rng = createRng(seed);
+ return dimensions.map((dimension) => {
+ const board = randomNotebookBoard(dimension, rng);
+ const m = astar(board, "manhattan");
+ const e = astar(board, "euclidean");
+ return {
+ dimension,
+ manhattan: notebookExpansions(m),
+ euclidean: notebookExpansions(e),
+ pathFound: m.path.length > 0,
+ };
+ });
+}
diff --git a/web/src/lib/cachex/board.ts b/web/src/lib/cachex/board.ts
new file mode 100644
index 0000000..ad26a7f
--- /dev/null
+++ b/web/src/lib/cachex/board.ts
@@ -0,0 +1,157 @@
+/**
+ * TypeScript port of the subject-provided referee board
+ * (coursework/Project Part B/code/referee/board.py).
+ *
+ * Coordinates are axial (r, q) with 0 <= r, q < n. Red connects r = 0 to
+ * r = n - 1; Blue connects q = 0 to q = n - 1.
+ */
+import { COLOUR_OF, type Colour, type Coord, SWAP_TOKEN, TOKEN_OF, type Token } from "./types";
+
+type Step = readonly [number, number];
+
+/** Neighbour hex steps in clockwise order (`_HEX_STEPS`). */
+export const HEX_STEPS: readonly Step[] = [
+ [1, -1],
+ [1, 0],
+ [0, 1],
+ [-1, 1],
+ [-1, 0],
+ [0, -1],
+];
+
+const add = (a: Step, b: Step): Step => [a[0] + b[0], a[1] + b[1]];
+
+/** numpy.roll(steps, k)[i] === steps[i - k] */
+const rolled = (k: number) => HEX_STEPS.map((_, i) => HEX_STEPS[(i - k + 6) % 6]);
+
+/**
+ * Diamond capture patterns: [opposite offset, neighbour 1 offset, neighbour 2 offset].
+ * "Longways" diamonds use adjacent neighbours (roll 1), "sideways" diamonds use
+ * neighbours spaced apart (roll 2), so each cell is part of 6 + 6 diamonds.
+ */
+export const CAPTURE_PATTERNS: readonly (readonly [Step, Step, Step])[] = [
+ ...HEX_STEPS.map((n1, i) => [n1, rolled(1)[i]] as const),
+ ...HEX_STEPS.map((n1, i) => [n1, rolled(2)[i]] as const),
+].map(([n1, n2]) => [add(n1, n2), n1, n2] as const);
+
+export class Board {
+ readonly n: number;
+ data: Uint8Array;
+
+ constructor(n: number, data?: Uint8Array) {
+ this.n = n;
+ this.data = data ? data.slice() : new Uint8Array(n * n);
+ }
+
+ clone(): Board {
+ return new Board(this.n, this.data);
+ }
+
+ index(r: number, q: number): number {
+ return r * this.n + q;
+ }
+
+ tokenAt(r: number, q: number): Token {
+ return this.data[r * this.n + q] as Token;
+ }
+
+ /** `board[coord]` — the colour string or null. */
+ get(r: number, q: number): Colour | null {
+ const t = this.tokenAt(r, q);
+ return t === 0 ? null : COLOUR_OF[t];
+ }
+
+ set(r: number, q: number, colour: Colour | null): void {
+ this.data[r * this.n + q] = colour === null ? 0 : TOKEN_OF[colour];
+ }
+
+ /** Board state digest used to detect repeated states. */
+ digest(): string {
+ return this.data.join("");
+ }
+
+ insideBounds(r: number, q: number): boolean {
+ return r >= 0 && r < this.n && q >= 0 && q < this.n;
+ }
+
+ isOccupied(r: number, q: number): boolean {
+ return this.tokenAt(r, q) !== 0;
+ }
+
+ /**
+ * Mirror the state along the major board axis: a matrix transpose combined
+ * with swapping the player token types (the STEAL action).
+ */
+ swap(): void {
+ const n = this.n;
+ const next = new Uint8Array(n * n);
+ for (let r = 0; r < n; r++) {
+ for (let q = 0; q < n; q++) {
+ next[r * n + q] = SWAP_TOKEN[this.data[q * n + r] as Token];
+ }
+ }
+ this.data = next;
+ }
+
+ /** Place a token and apply captures. Returns the captured coordinates. */
+ place(colour: Colour, r: number, q: number): Coord[] {
+ this.set(r, q, colour);
+ return this.applyCaptures(r, q);
+ }
+
+ /** In-bounds neighbours of a coordinate, in `_HEX_STEPS` order. */
+ neighbours(r: number, q: number): Coord[] {
+ const out: Coord[] = [];
+ for (const [dr, dq] of HEX_STEPS) {
+ const nr = r + dr;
+ const nq = q + dq;
+ if (this.insideBounds(nr, nq)) out.push([nr, nq]);
+ }
+ return out;
+ }
+
+ /** Cells connected to start (same token type), found with a BFS. */
+ connectedCoords(r: number, q: number): Coord[] {
+ const token = this.tokenAt(r, q);
+ const seen = new Set();
+ const queue: Coord[] = [[r, q]];
+ const out: Coord[] = [];
+ while (queue.length > 0) {
+ const [cr, cq] = queue.shift()!;
+ const key = cr * this.n + cq;
+ if (seen.has(key)) continue;
+ seen.add(key);
+ out.push([cr, cq]);
+ for (const [nr, nq] of this.neighbours(cr, cq)) {
+ if (!seen.has(nr * this.n + nq) && this.tokenAt(nr, nq) === token) {
+ queue.push([nr, nq]);
+ }
+ }
+ }
+ return out;
+ }
+
+ /**
+ * Check the placed coordinate for diamond captures and apply them.
+ * Captures are deferred so overlapping diamonds are handled correctly.
+ */
+ private applyCaptures(r: number, q: number): Coord[] {
+ const oppType = this.tokenAt(r, q);
+ const midType = SWAP_TOKEN[oppType];
+ const captured = new Map();
+
+ for (const pattern of CAPTURE_PATTERNS) {
+ const coords = pattern.map(([dr, dq]) => [r + dr, q + dq] as const);
+ if (!coords.every(([cr, cq]) => this.insideBounds(cr, cq))) continue;
+ const [a, b, c] = coords.map(([cr, cq]) => this.tokenAt(cr, cq));
+ if (a === oppType && b === midType && c === midType) {
+ for (const coord of coords.slice(1)) {
+ captured.set(coord[0] * this.n + coord[1], coord);
+ }
+ }
+ }
+
+ for (const [cr, cq] of captured.values()) this.set(cr, cq, null);
+ return [...captured.values()];
+ }
+}
diff --git a/web/src/lib/cachex/game.test.ts b/web/src/lib/cachex/game.test.ts
new file mode 100644
index 0000000..59e4ce4
--- /dev/null
+++ b/web/src/lib/cachex/game.test.ts
@@ -0,0 +1,117 @@
+import { describe, expect, it } from "vitest";
+
+import { partB, toAction } from "@/lib/__fixtures__/load";
+import { Board } from "./board";
+import { Game, IllegalActionError, MAX_TURNS } from "./game";
+import { STEAL, place } from "./types";
+
+const fixtures = partB();
+
+describe("referee parity (seeded random games from the original referee)", () => {
+ it.each(fixtures.refereeGames.map((g, i) => [i, g] as const))("game %i", (_, g) => {
+ const game = new Game(g.n);
+ g.actions.forEach((pyAction, i) => {
+ const action = toAction(pyAction);
+ game.update(game.turnPlayer(), action);
+ const step = g.steps[i];
+ expect(game.board.digest(), `turn ${i + 1}`).toBe(step.board);
+ const captures =
+ action[0] === "STEAL"
+ ? []
+ : [...game.lastCaptures].map((c) => [...c]).sort((a, b) => a[0] - b[0] || a[1] - b[1]);
+ expect(captures, `captures on turn ${i + 1}`).toEqual(step.captures);
+ const result =
+ game.result === null
+ ? null
+ : game.result.kind === "win"
+ ? `winner: ${game.result.winner}`
+ : "draw";
+ expect(result).toBe(step.result);
+ });
+ });
+
+ it("the fixtures exercise captures, steals and wins for both colours", () => {
+ const steps = fixtures.refereeGames.flatMap((g) => g.steps);
+ expect(steps.filter((s) => s.captures.length > 0).length).toBeGreaterThan(20);
+ expect(
+ fixtures.refereeGames.filter((g) => g.actions[1]?.[0] === "STEAL").length,
+ ).toBeGreaterThan(3);
+ const results = new Set(steps.map((s) => s.result).filter(Boolean));
+ expect(results).toEqual(new Set(["winner: red", "winner: blue"]));
+ });
+});
+
+describe("capture rule", () => {
+ it("captures both cells of a completed diamond", () => {
+ // Blue at (1,1) and (2,0) form the narrow axis of a diamond; red holds (1,0) and plays (2,1).
+ const b = new Board(4);
+ b.place("blue", 1, 1);
+ b.place("blue", 2, 0);
+ b.place("red", 1, 0);
+ const captured = b.place("red", 2, 1);
+ expect(captured.map((c) => [...c]).sort()).toEqual([
+ [1, 1],
+ [2, 0],
+ ]);
+ expect(b.get(1, 1)).toBeNull();
+ expect(b.get(2, 0)).toBeNull();
+ expect(b.get(2, 1)).toBe("red");
+ });
+
+ it("does not capture when the diamond is incomplete", () => {
+ const b = new Board(4);
+ b.place("blue", 1, 1);
+ b.place("red", 1, 0);
+ expect(b.place("red", 2, 1)).toEqual([]);
+ });
+});
+
+describe("game rules", () => {
+ it("swaps by transposing and recolouring on STEAL", () => {
+ const g = new Game(5);
+ g.update("red", place(1, 3));
+ g.update("blue", STEAL);
+ expect(g.board.get(3, 1)).toBe("blue");
+ expect(g.board.get(1, 3)).toBeNull();
+ expect(g.turnPlayer()).toBe("red");
+ });
+
+ it("only allows STEAL on Blue's first move", () => {
+ const g = new Game(5);
+ expect(() => g.update("red", STEAL)).toThrow(IllegalActionError);
+ g.update("red", place(0, 0));
+ g.update("blue", place(1, 1));
+ expect(() => g.update("red", STEAL)).toThrow(IllegalActionError);
+ });
+
+ it("forbids the centre on the first move of odd boards only", () => {
+ expect(() => new Game(5).update("red", place(2, 2))).toThrow(/centre/);
+ expect(() => new Game(4).update("red", place(2, 2))).not.toThrow();
+ const g = new Game(5);
+ g.update("red", place(0, 0));
+ expect(() => g.update("blue", place(2, 2))).not.toThrow();
+ });
+
+ it("rejects occupied cells, out-of-bounds cells and out-of-turn moves", () => {
+ const g = new Game(3);
+ g.update("red", place(0, 0));
+ expect(() => g.update("blue", place(0, 0))).toThrow(/occupied/);
+ expect(() => g.update("blue", place(3, 0))).toThrow(/outside/);
+ expect(() => g.update("red", place(1, 0))).toThrow(/turn/);
+ });
+
+ it("detects a Red win along the r axis", () => {
+ const g = Game.fromActions(3, [
+ place(0, 0),
+ place(0, 1),
+ place(1, 0),
+ place(1, 1),
+ place(2, 0),
+ ]);
+ expect(g.result).toMatchObject({ kind: "win", winner: "red" });
+ });
+
+ it("declares a draw after the maximum number of turns", () => {
+ expect(MAX_TURNS).toBe(343);
+ });
+});
diff --git a/web/src/lib/cachex/game.ts b/web/src/lib/cachex/game.ts
new file mode 100644
index 0000000..f60339b
--- /dev/null
+++ b/web/src/lib/cachex/game.ts
@@ -0,0 +1,171 @@
+/**
+ * TypeScript port of the referee's game rules
+ * (coursework/Project Part B/code/referee/game.py, class `Game`):
+ * turn order, action validation, STEAL, captures, win and draw detection.
+ */
+import { Board } from "./board";
+import { type Action, type Colour, type Coord, PLAYER_AXIS, formatAction, isSteal } from "./types";
+
+export const PLAYER_TURN_ORDER: readonly Colour[] = ["red", "blue"];
+export const MAX_REPEAT_STATES = 7;
+export const MAX_TURNS = 343;
+
+export type GameResult =
+ | { kind: "win"; winner: Colour; cluster: Coord[] }
+ | { kind: "draw"; reason: "repetition" | "max-turns" };
+
+export class IllegalActionError extends Error {
+ constructor(
+ message: string,
+ readonly action: Action,
+ ) {
+ super(`${message} (${formatAction(action)})`);
+ this.name = "IllegalActionError";
+ }
+}
+
+export interface TurnRecord {
+ turn: number;
+ player: Colour;
+ action: Action;
+ captures: Coord[];
+}
+
+export class Game {
+ readonly n: number;
+ board: Board;
+ nturns = 0;
+ lastCaptures: Coord[] = [];
+ lastCoord: Coord = [-1, -1];
+ history = new Map();
+ result: GameResult | null = null;
+ log: TurnRecord[] = [];
+
+ constructor(n: number) {
+ if (!Number.isInteger(n) || n < 1) throw new Error(`invalid board size ${n}`);
+ this.n = n;
+ this.board = new Board(n);
+ this.history.set(this.board.digest(), 1);
+ }
+
+ /** Rebuild a game by replaying a list of actions from the start. */
+ static fromActions(n: number, actions: readonly Action[]): Game {
+ const game = new Game(n);
+ for (const action of actions) game.update(game.turnPlayer(), action);
+ return game;
+ }
+
+ turnPlayer(): Colour {
+ return PLAYER_TURN_ORDER[this.nturns % 2];
+ }
+
+ over(): boolean {
+ return this.result !== null;
+ }
+
+ /** True iff STEAL is currently a legal action (Blue's first move only). */
+ canSteal(): boolean {
+ return this.nturns === 1 && !this.over();
+ }
+
+ /** True iff (r, q) is the centre cell and this is the first move of the game. */
+ isForbiddenOpening(r: number, q: number): boolean {
+ return this.nturns === 0 && r * 2 === this.n - 1 && q * 2 === this.n - 1;
+ }
+
+ isLegal(action: Action): boolean {
+ if (this.over()) return false;
+ if (isSteal(action)) return this.nturns === 1;
+ const [, r, q] = action;
+ return (
+ this.board.insideBounds(r, q) &&
+ !this.isForbiddenOpening(r, q) &&
+ !this.board.isOccupied(r, q)
+ );
+ }
+
+ legalPlacements(): Coord[] {
+ const out: Coord[] = [];
+ for (let r = 0; r < this.n; r++) {
+ for (let q = 0; q < this.n; q++) {
+ if (this.isLegal(["PLACE", r, q])) out.push([r, q]);
+ }
+ }
+ return out;
+ }
+
+ /** Validate and apply an action, then check for end conditions. */
+ update(player: Colour, action: Action): Action {
+ if (this.over()) throw new IllegalActionError("The game is already over.", action);
+ if (player !== this.turnPlayer()) {
+ throw new IllegalActionError(`It is not ${player}'s turn!`, action);
+ }
+
+ if (isSteal(action)) {
+ if (this.nturns !== 1) {
+ throw new IllegalActionError(
+ "STEAL may only be played by Blue on their first move.",
+ action,
+ );
+ }
+ this.board.swap();
+ this.lastCoord = [-1, -1];
+ this.lastCaptures = [];
+ } else {
+ const [, r, q] = action;
+ if (!Number.isInteger(r) || !Number.isInteger(q) || !this.board.insideBounds(r, q)) {
+ throw new IllegalActionError(`(${r}, ${q}) is outside the board (n = ${this.n}).`, action);
+ }
+ if (this.isForbiddenOpening(r, q)) {
+ throw new IllegalActionError(
+ "The centre cell cannot be taken on the first move of the game.",
+ action,
+ );
+ }
+ if (this.board.isOccupied(r, q)) {
+ throw new IllegalActionError(`(${r}, ${q}) is already occupied.`, action);
+ }
+ this.lastCaptures = this.board.place(player, r, q);
+ this.lastCoord = [r, q];
+ }
+
+ this.log.push({
+ turn: this.nturns + 1,
+ player,
+ action,
+ captures: this.lastCaptures,
+ });
+ this.turnDetectEnd(player, action);
+ return action;
+ }
+
+ private turnDetectEnd(player: Colour, action: Action): void {
+ this.nturns += 1;
+ const digest = this.board.digest();
+ const seen = (this.history.get(digest) ?? 0) + 1;
+ this.history.set(digest, seen);
+
+ // Condition 1: a continuous path spanning the board (only possible after 2n - 1 turns).
+ if (this.nturns >= this.n * 2 - 1 && !isSteal(action)) {
+ const [, r, q] = action;
+ const reachable = this.board.connectedCoords(r, q);
+ const axis = PLAYER_AXIS[player];
+ const vals = reachable.map((c) => c[axis]);
+ if (Math.min(...vals) === 0 && Math.max(...vals) === this.n - 1) {
+ this.result = { kind: "win", winner: player, cluster: reachable };
+ return;
+ }
+ }
+
+ // Condition 2: the same state has occurred too many times.
+ if (seen >= MAX_REPEAT_STATES) {
+ this.result = { kind: "draw", reason: "repetition" };
+ return;
+ }
+
+ // Condition 3: too many turns.
+ if (this.nturns >= MAX_TURNS) {
+ this.result = { kind: "draw", reason: "max-turns" };
+ }
+ }
+}
diff --git a/web/src/lib/cachex/match.test.ts b/web/src/lib/cachex/match.test.ts
new file mode 100644
index 0000000..791a69f
--- /dev/null
+++ b/web/src/lib/cachex/match.test.ts
@@ -0,0 +1,70 @@
+import { describe, expect, it } from "vitest";
+
+import { deriveMatchView, evaluationTrend, undoToHumanTurn } from "./match";
+import { STEAL, place } from "./types";
+
+describe("deriveMatchView", () => {
+ it("reports the last move and the colour of captured tokens", () => {
+ const view = deriveMatchView(4, [
+ place(1, 1),
+ place(0, 0),
+ place(1, 0),
+ place(3, 3),
+ place(2, 0),
+ place(2, 2),
+ ]);
+ expect(view.lastMove).toEqual([2, 2]);
+ expect(view.cells.filter(Boolean)).toHaveLength(6);
+
+ const capture = deriveMatchView(4, [
+ place(1, 1),
+ place(1, 0),
+ place(2, 0),
+ place(3, 3),
+ place(0, 3),
+ place(2, 1),
+ ]);
+ // Blue's (2,1) with Blue at (1,0) completes a diamond around Red's (1,1) and (2,0)
+ expect(capture.captured.map((c) => c.colour)).toEqual(["red", "red"]);
+ expect(capture.cells[1 * 4 + 1]).toBeNull();
+ });
+
+ it("has no last move after a steal", () => {
+ expect(deriveMatchView(5, [place(1, 1), STEAL]).lastMove).toBeNull();
+ });
+
+ it("exposes the winning chain", () => {
+ const view = deriveMatchView(3, [
+ place(0, 0),
+ place(0, 1),
+ place(1, 0),
+ place(1, 1),
+ place(2, 0),
+ ]);
+ expect(view.winning).toHaveLength(3);
+ });
+});
+
+describe("undoToHumanTurn", () => {
+ const kinds = { red: "human", blue: "minimax" } as const;
+
+ it("removes the AI reply and the human move", () => {
+ const actions = [place(0, 0), place(1, 1), place(2, 2), place(3, 3)];
+ expect(undoToHumanTurn(actions, kinds)).toEqual([place(0, 0), place(1, 1)]);
+ });
+
+ it("removes only the human move while the AI is thinking", () => {
+ expect(undoToHumanTurn([place(0, 0), place(1, 1), place(2, 2)], kinds)).toEqual([
+ place(0, 0),
+ place(1, 1),
+ ]);
+ });
+});
+
+describe("evaluationTrend", () => {
+ it("starts from the empty-board score and adds one value per move", () => {
+ const trend = evaluationTrend(3, [place(0, 0), place(2, 2)]);
+ expect(trend).toHaveLength(3);
+ expect(trend[0]).toBe(9 * 0.5);
+ });
+});
diff --git a/web/src/lib/cachex/match.ts b/web/src/lib/cachex/match.ts
new file mode 100644
index 0000000..08177cf
--- /dev/null
+++ b/web/src/lib/cachex/match.ts
@@ -0,0 +1,61 @@
+/**
+ * Framework-free helpers that turn an action history into what the board UI
+ * needs: cell colours, the latest move, captured tokens and the winning chain.
+ */
+import { AgentBoard } from "@/lib/agent/agent-board";
+import { evaluate } from "@/lib/agent/evaluation";
+import { Game } from "./game";
+import { type Action, type Colour, type Coord, isSteal, opponent } from "./types";
+
+export type PlayerKind = "human" | "minimax" | "random";
+
+export interface MatchView {
+ game: Game;
+ cells: (Colour | null)[];
+ lastMove: Coord | null;
+ captured: { coord: Coord; colour: Colour }[];
+ winning: Coord[] | null;
+}
+
+export function deriveMatchView(n: number, actions: readonly Action[]): MatchView {
+ const game = Game.fromActions(n, actions);
+ const cells: (Colour | null)[] = [];
+ for (let r = 0; r < n; r++) for (let q = 0; q < n; q++) cells.push(game.board.get(r, q));
+ const last = game.log.at(-1);
+ const lastMove =
+ last && !isSteal(last.action) ? ([last.action[1], last.action[2]] as const) : null;
+ const captured = last
+ ? last.captures.map((coord) => ({ coord, colour: opponent(last.player) }))
+ : [];
+ const winning = game.result?.kind === "win" ? game.result.cluster : null;
+ return { game, cells, lastMove, captured, winning };
+}
+
+/** The original evaluation (Red-positive, no random bias) after every move. */
+export function evaluationTrend(n: number, actions: readonly Action[]): number[] {
+ const board = new AgentBoard(n);
+ const out: number[] = [evaluate(board)];
+ actions.forEach((action, i) => {
+ board.update(i % 2 === 0 ? "red" : "blue", action);
+ out.push(evaluate(board));
+ });
+ return out;
+}
+
+/** Player to move after `count` actions. */
+export const playerToMove = (count: number): Colour => (count % 2 === 0 ? "red" : "blue");
+
+/**
+ * Undo back to the most recent position where a human is to move, removing
+ * at least one action.
+ */
+export function undoToHumanTurn(
+ actions: readonly Action[],
+ kinds: Record,
+): Action[] {
+ const next = actions.slice();
+ if (next.length === 0) return next;
+ next.pop();
+ while (next.length > 0 && kinds[playerToMove(next.length)] !== "human") next.pop();
+ return next;
+}
diff --git a/web/src/lib/cachex/types.ts b/web/src/lib/cachex/types.ts
new file mode 100644
index 0000000..a282727
--- /dev/null
+++ b/web/src/lib/cachex/types.ts
@@ -0,0 +1,41 @@
+export type Colour = "red" | "blue";
+
+/** Internal token codes, identical to the referee: 0 empty, 1 red, 2 blue. */
+export const EMPTY = 0;
+export const RED_TOKEN = 1;
+export const BLUE_TOKEN = 2;
+export type Token = 0 | 1 | 2;
+
+export type Coord = readonly [r: number, q: number];
+
+export type PlaceAction = readonly ["PLACE", number, number];
+export type StealAction = readonly ["STEAL"];
+export type Action = PlaceAction | StealAction;
+
+export const STEAL: StealAction = ["STEAL"];
+export const place = (r: number, q: number): PlaceAction => ["PLACE", r, q];
+
+export const isSteal = (a: Action): a is StealAction => a[0] === "STEAL";
+
+export const TOKEN_OF: Record = { red: RED_TOKEN, blue: BLUE_TOKEN };
+export const COLOUR_OF: Record<1 | 2, Colour> = { 1: "red", 2: "blue" };
+/** `_SWAP_PLAYER` in the referee. */
+export const SWAP_TOKEN: Record = { 0: 0, 1: 2, 2: 1 };
+
+export const opponent = (c: Colour): Colour => (c === "red" ? "blue" : "red");
+
+/** Red aims to connect along the r axis (0), Blue along the q axis (1). */
+export const PLAYER_AXIS: Record = { red: 0, blue: 1 };
+
+export function actionKey(a: Action): string {
+ return isSteal(a) ? "STEAL" : `${a[1]},${a[2]}`;
+}
+
+export function formatAction(a: Action): string {
+ return isSteal(a) ? "STEAL" : `PLACE (${a[1]}, ${a[2]})`;
+}
+
+export function sameAction(a: Action | null, b: Action | null): boolean {
+ if (a === null || b === null) return a === b;
+ return actionKey(a) === actionKey(b);
+}
diff --git a/web/src/lib/data/agent-benchmark.json b/web/src/lib/data/agent-benchmark.json
new file mode 100644
index 0000000..59e3dc0
--- /dev/null
+++ b/web/src/lib/data/agent-benchmark.json
@@ -0,0 +1,83 @@
+{
+ "meta": {
+ "generatedBy": "scripts/benchmark_agent.py",
+ "python": "3.12.7",
+ "pythonHashSeed": "0",
+ "opponent": "random_play_agent (coursework/Project Part B/skeleton-code-B)",
+ "agent": "_4399 (coursework/Project Part B/code)"
+ },
+ "results": [
+ {
+ "n": 4,
+ "agentColour": "red",
+ "games": 20,
+ "wins": 17,
+ "losses": 3,
+ "draws": 0,
+ "avgTurns": 14.2
+ },
+ {
+ "n": 4,
+ "agentColour": "blue",
+ "games": 20,
+ "wins": 15,
+ "losses": 5,
+ "draws": 0,
+ "avgTurns": 13.8
+ },
+ {
+ "n": 5,
+ "agentColour": "red",
+ "games": 20,
+ "wins": 18,
+ "losses": 2,
+ "draws": 0,
+ "avgTurns": 20.5
+ },
+ {
+ "n": 5,
+ "agentColour": "blue",
+ "games": 20,
+ "wins": 19,
+ "losses": 1,
+ "draws": 0,
+ "avgTurns": 20.1
+ },
+ {
+ "n": 6,
+ "agentColour": "red",
+ "games": 20,
+ "wins": 18,
+ "losses": 2,
+ "draws": 0,
+ "avgTurns": 29.6
+ },
+ {
+ "n": 6,
+ "agentColour": "blue",
+ "games": 20,
+ "wins": 18,
+ "losses": 2,
+ "draws": 0,
+ "avgTurns": 32.2
+ },
+ {
+ "n": 7,
+ "agentColour": "red",
+ "games": 20,
+ "wins": 20,
+ "losses": 0,
+ "draws": 0,
+ "avgTurns": 44.3
+ },
+ {
+ "n": 7,
+ "agentColour": "blue",
+ "games": 20,
+ "wins": 19,
+ "losses": 1,
+ "draws": 0,
+ "avgTurns": 43.5
+ }
+ ]
+}
diff --git a/web/src/lib/hex-geometry.test.ts b/web/src/lib/hex-geometry.test.ts
new file mode 100644
index 0000000..d01bccf
--- /dev/null
+++ b/web/src/lib/hex-geometry.test.ts
@@ -0,0 +1,41 @@
+import { describe, expect, it } from "vitest";
+
+import { HEX_STEPS } from "./cachex/board";
+import { SQRT3, boardGeometry } from "./hex-geometry";
+
+describe("board geometry", () => {
+ const g = boardGeometry(5, 10);
+ const dist = (a: { x: number; y: number }, b: { x: number; y: number }) =>
+ Math.hypot(a.x - b.x, a.y - b.y);
+
+ it("places every hex neighbour exactly one hex-width away", () => {
+ for (const [dr, dq] of HEX_STEPS) {
+ expect(dist(g.centre(2, 2), g.centre(2 + dr, 2 + dq))).toBeCloseTo(SQRT3 * 10, 6);
+ }
+ });
+
+ it("draws row 0 at the bottom with rows shifting right as they go up", () => {
+ expect(g.centre(0, 0).y).toBeGreaterThan(g.centre(4, 0).y);
+ expect(g.centre(4, 0).x).toBeGreaterThan(g.centre(0, 0).x);
+ });
+
+ it("keeps every hex inside the viewBox", () => {
+ for (let r = 0; r < 5; r++) {
+ for (let q = 0; q < 5; q++) {
+ const c = g.centre(r, q);
+ expect(c.x - 10).toBeGreaterThanOrEqual(0);
+ expect(c.x + 10).toBeLessThanOrEqual(g.width);
+ expect(c.y - 10).toBeGreaterThanOrEqual(0);
+ expect(c.y + 10).toBeLessThanOrEqual(g.height);
+ }
+ }
+ });
+
+ it("builds edge polylines whose ends meet at the corners", () => {
+ const { top, right, bottom, left } = g.edges;
+ expect(dist(top[top.length - 1], right[0])).toBeCloseTo(0, 6);
+ expect(dist(right[right.length - 1], bottom[bottom.length - 1])).toBeCloseTo(0, 6);
+ expect(dist(left[0], bottom[0])).toBeCloseTo(0, 6);
+ expect(dist(left[left.length - 1], top[0])).toBeCloseTo(0, 6);
+ });
+});
diff --git a/web/src/lib/hex-geometry.ts b/web/src/lib/hex-geometry.ts
new file mode 100644
index 0000000..9507f2a
--- /dev/null
+++ b/web/src/lib/hex-geometry.ts
@@ -0,0 +1,106 @@
+/**
+ * Geometry for drawing an n×n Cachex board with pointy-top hexagons.
+ *
+ * Row r = 0 is drawn at the bottom and each row up is shifted half a hex to
+ * the right (the same layout as the original `print_board`), so Red's goal
+ * edges are the top and bottom rows and Blue's are the slanted left and right
+ * sides.
+ */
+export const SQRT3 = Math.sqrt(3);
+
+export interface Point {
+ x: number;
+ y: number;
+}
+
+export interface BoardGeometry {
+ n: number;
+ radius: number;
+ width: number;
+ height: number;
+ /** Padding around the outline (for edge bands and glow). */
+ pad: number;
+ centre: (r: number, q: number) => Point;
+ hexPoints: (r: number, q: number, scale?: number) => string;
+ /** Outline segments: Red owns top/bottom, Blue owns left/right. */
+ edges: { top: Point[]; bottom: Point[]; left: Point[]; right: Point[] };
+ outline: Point[];
+ viewBox: string;
+}
+
+export function boardGeometry(n: number, radius = 10, pad = radius * 1.1): BoardGeometry {
+ const w = SQRT3 * radius;
+ const centre = (r: number, q: number): Point => ({
+ x: pad + w / 2 + w * (q + r / 2),
+ y: pad + radius + 1.5 * radius * (n - 1 - r),
+ });
+
+ const vertex = (c: Point, k: number, scale = 1): Point => {
+ // pointy-top: vertex 0 at the top, clockwise
+ const angle = (Math.PI / 180) * (60 * k - 90);
+ return { x: c.x + radius * scale * Math.cos(angle), y: c.y + radius * scale * Math.sin(angle) };
+ };
+
+ const hexPoints = (r: number, q: number, scale = 1) => {
+ const c = centre(r, q);
+ return Array.from({ length: 6 }, (_, k) => vertex(c, k, scale))
+ .map((p) => `${p.x.toFixed(3)},${p.y.toFixed(3)}`)
+ .join(" ");
+ };
+
+ // vertices: 0 top, 1 upper-right, 2 lower-right, 3 bottom, 4 lower-left, 5 upper-left
+ const top: Point[] = [];
+ for (let q = 0; q < n; q++) {
+ const c = centre(n - 1, q);
+ if (q === 0) top.push(vertex(c, 5));
+ top.push(vertex(c, 0), vertex(c, 1));
+ }
+ const bottom: Point[] = [];
+ for (let q = 0; q < n; q++) {
+ const c = centre(0, q);
+ if (q === 0) bottom.push(vertex(c, 4));
+ bottom.push(vertex(c, 3), vertex(c, 2));
+ }
+ const left: Point[] = [];
+ for (let r = 0; r < n; r++) {
+ const c = centre(r, 0);
+ if (r === 0) left.push(vertex(c, 4));
+ left.push(vertex(c, 5));
+ if (r < n - 1) left.push(vertex(c, 0));
+ }
+ const right: Point[] = [];
+ for (let r = n - 1; r >= 0; r--) {
+ const c = centre(r, n - 1);
+ if (r === n - 1) right.push(vertex(c, 1));
+ right.push(vertex(c, 2));
+ if (r > 0) right.push(vertex(c, 3));
+ }
+
+ // closed outline: top (left→right), right (top→bottom), bottom (right→left), left (bottom→top)
+ const outline = [
+ ...top,
+ ...right.slice(1),
+ ...bottom.slice().reverse().slice(1),
+ ...left.slice(1, -1),
+ ];
+
+ const width = pad * 2 + w * n + (w / 2) * (n - 1);
+ const height = pad * 2 + radius * 2 + 1.5 * radius * (n - 1);
+
+ return {
+ n,
+ radius,
+ width,
+ height,
+ pad,
+ centre,
+ hexPoints,
+ edges: { top, bottom, left, right },
+ outline,
+ viewBox: `0 0 ${width.toFixed(3)} ${height.toFixed(3)}`,
+ };
+}
+
+export const toPath = (points: Point[], close = false) =>
+ points.map((p, i) => `${i === 0 ? "M" : "L"}${p.x.toFixed(3)} ${p.y.toFixed(3)}`).join(" ") +
+ (close ? " Z" : "");
diff --git a/web/src/lib/rng.ts b/web/src/lib/rng.ts
new file mode 100644
index 0000000..23be1e7
--- /dev/null
+++ b/web/src/lib/rng.ts
@@ -0,0 +1,47 @@
+/**
+ * Small seeded PRNG (mulberry32). The original Python agents use the global
+ * `random` module; in the browser we use a seeded generator so that a game can
+ * be replayed exactly from its seed.
+ */
+export type Rng = () => number;
+
+export function createRng(seed: number): Rng {
+ let a = seed >>> 0;
+ return () => {
+ a = (a + 0x6d2b79f5) >>> 0;
+ let t = a;
+ t = Math.imul(t ^ (t >>> 15), t | 1);
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
+ };
+}
+
+/** Uniform integer in [min, max] (inclusive), like Python's randint. */
+export function randInt(rng: Rng, min: number, max: number): number {
+ return min + Math.floor(rng() * (max - min + 1));
+}
+
+export function choice(rng: Rng, items: readonly T[]): T {
+ if (items.length === 0) throw new Error("choice() from an empty list");
+ return items[Math.floor(rng() * items.length)];
+}
+
+/** In-place Fisher–Yates shuffle. */
+export function shuffle(rng: Rng, items: T[]): T[] {
+ for (let i = items.length - 1; i > 0; i--) {
+ const j = Math.floor(rng() * (i + 1));
+ [items[i], items[j]] = [items[j], items[i]];
+ }
+ return items;
+}
+
+/** Random sample without replacement, like Python's random.sample. */
+export function sample(rng: Rng, items: readonly T[], k: number): T[] {
+ const pool = items.slice();
+ shuffle(rng, pool);
+ return pool.slice(0, k);
+}
+
+export function randomSeed(): number {
+ return Math.floor(Math.random() * 2 ** 31);
+}
diff --git a/web/src/lib/site.ts b/web/src/lib/site.ts
new file mode 100644
index 0000000..bffd272
--- /dev/null
+++ b/web/src/lib/site.ts
@@ -0,0 +1,20 @@
+export const SITE = {
+ name: "Cachex Arena",
+ description:
+ "Play Cachex against the minimax agent we built for COMP30024 Artificial Intelligence at the University of Melbourne, watch agents battle, and step through our A* search.",
+ repo: "https://github.com/rNLKJA/Cachex-AI",
+ /** Production URL on Vercel (override with NEXT_PUBLIC_SITE_URL). */
+ url: process.env.NEXT_PUBLIC_SITE_URL ?? "https://cachex-ai.vercel.app",
+ subject: { code: "COMP30024", name: "Artificial Intelligence", term: "Semester 1, 2022" },
+ team: [
+ { name: 'Sunchuangyu "Rin" Huang', github: "https://github.com/rNLKJA" },
+ { name: "Wei Zhao", github: null },
+ ],
+} as const;
+
+export const NAV = [
+ { href: "/play", label: "Play" },
+ { href: "/spectate", label: "Spectate" },
+ { href: "/astar", label: "A* Lab" },
+ { href: "/#about", label: "About" },
+] as const;
diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts
new file mode 100644
index 0000000..fe0d169
--- /dev/null
+++ b/web/src/lib/utils.ts
@@ -0,0 +1 @@
+export { cn } from "cn";
diff --git a/web/src/workers/agent.worker.ts b/web/src/workers/agent.worker.ts
new file mode 100644
index 0000000..3f4f8b6
--- /dev/null
+++ b/web/src/workers/agent.worker.ts
@@ -0,0 +1,16 @@
+/**
+ * Runs the ported agents off the main thread so the board stays responsive.
+ */
+import { type AgentRequest, runAgent } from "@/lib/agent/run-agent";
+
+const ctx = self as unknown as {
+ postMessage: (message: unknown) => void;
+ addEventListener: (
+ type: "message",
+ listener: (event: MessageEvent) => void,
+ ) => void;
+};
+
+ctx.addEventListener("message", (event) => {
+ ctx.postMessage(runAgent(event.data));
+});
diff --git a/web/src/workers/astar-benchmark.worker.ts b/web/src/workers/astar-benchmark.worker.ts
new file mode 100644
index 0000000..5f5dea9
--- /dev/null
+++ b/web/src/workers/astar-benchmark.worker.ts
@@ -0,0 +1,36 @@
+/**
+ * Runs the Manhattan vs Euclidean heuristic study off the main thread.
+ */
+import { type BenchmarkRow, runHeuristicBenchmark } from "@/lib/astar/random-board";
+
+export interface BenchmarkRequest {
+ id: number;
+ dimensions: number[];
+ seed: number;
+}
+
+export type BenchmarkResponse =
+ | { id: number; ok: true; rows: BenchmarkRow[]; elapsedMs: number }
+ | { id: number; ok: false; error: string };
+
+const ctx = self as unknown as {
+ postMessage: (message: BenchmarkResponse) => void;
+ addEventListener: (
+ type: "message",
+ listener: (event: MessageEvent) => void,
+ ) => void;
+};
+
+ctx.addEventListener("message", ({ data }) => {
+ const started = performance.now();
+ try {
+ const rows = runHeuristicBenchmark(data.dimensions, data.seed);
+ ctx.postMessage({ id: data.id, ok: true, rows, elapsedMs: performance.now() - started });
+ } catch (err) {
+ ctx.postMessage({
+ id: data.id,
+ ok: false,
+ error: err instanceof Error ? err.message : String(err),
+ });
+ }
+});
diff --git a/web/tsconfig.json b/web/tsconfig.json
new file mode 100644
index 0000000..7d553a8
--- /dev/null
+++ b/web/tsconfig.json
@@ -0,0 +1,34 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts",
+ "**/*.mts"
+ ],
+ "exclude": ["node_modules"]
+}
diff --git a/web/vitest.config.mts b/web/vitest.config.mts
new file mode 100644
index 0000000..1d8e145
--- /dev/null
+++ b/web/vitest.config.mts
@@ -0,0 +1,12 @@
+import { fileURLToPath } from "node:url";
+import { defineConfig } from "vitest/config";
+
+export default defineConfig({
+ resolve: {
+ alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) },
+ },
+ test: {
+ environment: "node",
+ include: ["src/**/*.test.ts"],
+ },
+});