Skip to content

Commit bbaf15b

Browse files
authored
Merge pull request #256 from AbstractPlay/bluestone
Penta-Hex Graph and Bluestone Implementation
2 parents 65b2591 + e0a089a commit bbaf15b

File tree

6 files changed

+806
-4
lines changed

6 files changed

+806
-4
lines changed

locales/en/apgames.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"blockade": "Blockade (also known as Cul-de-sac) is a 'beat the barrier' game where you get one of your pawns to a starting space of your opponent. Players place 2-wide walls to block each other.",
2929
"blooms": "Each player owns 2 colours of stones. Players take turns placing one or two stones each turn (if you place two, they must be different colours), then capture all fenced enemy blooms. The first player to capture a certain number of stones wins.",
3030
"bloqueo": "Manipulate pawns to create towers of player pieces. Score points based on connected groups of controlled towers. Highest score wins.",
31+
"bluestone": "Connect your groups to as many of the blue pieces on the perimeter of the board, in this mixture of territory and connection game.",
3132
"boom": "A minimalist abstract that combines simple move and capture mechanics with a scoring mechanic. Score by bearing your stacks off the opposing side of the board, but you'll want to reduce your opponent's scoring opportunities at the same time.",
3233
"bounce": "Manoeuvre your disconnected checkers into a single, orthogonally connected whole.",
3334
"boxes": "A territorial game where you try to complete boxes by drawing lines to connect the dots. If a box is claimed, you may make another move.",
@@ -590,6 +591,14 @@
590591
"name": "Largest board (base 10)"
591592
}
592593
},
594+
"bluestone": {
595+
"#board": {
596+
"name": "Default board (25 blue stones)"
597+
},
598+
"size-8": {
599+
"name": "Larger board (35 blue stones)"
600+
}
601+
},
593602
"boom": {
594603
"#setup": {
595604
"name": "4 pieces each"
@@ -3413,6 +3422,11 @@
34133422
"PARTIAL_dest": "Select the destination.",
34143423
"PARTIAL_place": "Select a cell to place one of your pieces."
34153424
},
3425+
"bluestone": {
3426+
"INITIAL_INSTRUCTIONS_FIRST_TURN": "Place one pieces onto any empty intersection.",
3427+
"INITIAL_INSTRUCTIONS": "Place one or two pieces onto empty intersections.",
3428+
"FULL_INSTRUCTIONS": "Place one or two pieces onto empty intersections. You cannot place both pieces as a part of the same group or where they would be immediately removed."
3429+
},
34163430
"boom": {
34173431
"INITIAL_INSTRUCTIONS": "Select a stack to move or attack with.",
34183432
"OUT_OF_RANGE": "Stacks can only move/attack a distance equal to the stack's height.",

src/common/graphs/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,13 @@ import { SquareOrth3DGraph } from "./square-orth-3d";
1919
import { SquareDiag3DGraph } from "./square-diag-3d";
2020
import { HexFieldGraph } from "./hex-field";
2121
import { SquareDiamondsDirectedGraph } from "./square-diamonds-directed";
22+
import { PentaHexGraph } from "./penta-hex";
2223

23-
export { IGraph, IGraph3D, Square3DGraph, SquareGraph, SquareDirectedGraph, SquareOrth3DGraph, SquareOrthGraph, SquareOrthDirectedGraph, SquareDiag3DGraph, SquareDiagGraph, SquareFanoronaGraph, SnubSquareGraph, OnyxGraph, HexTriGraph, HexMoonGraph, HexSlantedGraph, HexConeGraph, HexFieldGraph, BaoGraph, SowingNoEndsGraph, SquareDiamondsDirectedGraph };
24+
export { IGraph, IGraph3D, Square3DGraph, SquareGraph, SquareDirectedGraph,
25+
SquareOrth3DGraph, SquareOrthGraph, SquareOrthDirectedGraph, SquareDiag3DGraph,
26+
SquareDiagGraph, SquareFanoronaGraph, SnubSquareGraph, OnyxGraph, HexTriGraph,
27+
HexMoonGraph, HexSlantedGraph, HexConeGraph, HexFieldGraph, BaoGraph,
28+
SowingNoEndsGraph, SquareDiamondsDirectedGraph, PentaHexGraph };
2429

2530
import { UndirectedGraph } from "graphology";
2631
import { connectedComponents } from "graphology-components";

src/common/graphs/penta-hex.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { UndirectedGraph } from "graphology";
2+
import { bidirectional } from 'graphology-shortest-path/unweighted';
3+
import { IGraph } from "./IGraph";
4+
5+
// Similar to PentaHexGraph but the center node only has 5 edges
6+
export class PentaHexGraph implements IGraph {
7+
public readonly size: number;
8+
public graph: UndirectedGraph;
9+
10+
constructor(size: number) {
11+
if (size < 2) throw new Error(`PentaHexGraph cannot be less than size 2`);
12+
this.size = size;
13+
this.graph = this.buildGraph();
14+
}
15+
16+
public coords2algebraic(x: number, y: number): string {
17+
if (y < 0 || y > this.size) throw new Error(`The x coord must be a circle inside the graph`);
18+
if (y == 0) return "0-0";
19+
let trueX = x;
20+
do {
21+
trueX += 5*y;
22+
} while (trueX < 0);
23+
return y + "-" + (trueX%(5*y));
24+
}
25+
26+
public algebraic2coords(cell: string): [number, number] {
27+
const pair: string[] = cell.split("-");
28+
const y = Number(pair[0]);
29+
const x = Number(pair[1]);
30+
if (y === undefined || isNaN(y) || x === undefined || isNaN(x)) {
31+
throw new Error(`The algebraic coords cannot be parsed`);
32+
}
33+
return [x,y];
34+
}
35+
36+
private buildGraph(): UndirectedGraph {
37+
const graph = new UndirectedGraph();
38+
for (let y = 0; y < this.size; y++) {
39+
if (y == 0) {
40+
graph.addNode(this.coords2algebraic(0,0));
41+
}
42+
for (let x = 0; x < 5*y; x++) {
43+
graph.addNode(this.coords2algebraic(x,y));
44+
}
45+
}
46+
47+
for (let y = 0; y < this.size; y++) {
48+
if (y == 0) {
49+
const cell = this.coords2algebraic(0,0);
50+
graph.addEdge(cell, this.coords2algebraic(0,1));
51+
graph.addEdge(cell, this.coords2algebraic(1,1));
52+
graph.addEdge(cell, this.coords2algebraic(2,1));
53+
graph.addEdge(cell, this.coords2algebraic(3,1));
54+
graph.addEdge(cell, this.coords2algebraic(4,1));
55+
}
56+
let counter = -1;
57+
for (let x = 0; x < 5*y; x++) {
58+
const cell = this.coords2algebraic(x,y);
59+
graph.addEdge(cell, this.coords2algebraic(x+1, y));
60+
if (y+1 >= this.size) continue;
61+
if (x % y == 0) {
62+
//Three edges
63+
graph.addEdge(cell, this.coords2algebraic(x+counter++, y+1));
64+
graph.addEdge(cell, this.coords2algebraic(x+counter++, y+1));
65+
graph.addEdge(cell, this.coords2algebraic(x+counter--, y+1));
66+
} else {
67+
//Two edges
68+
graph.addEdge(cell, this.coords2algebraic(x+counter++, y+1));
69+
graph.addEdge(cell, this.coords2algebraic(x+counter--, y+1));
70+
}
71+
}
72+
}
73+
return graph;
74+
}
75+
76+
public listCells(ordered = false): string[] | string[][] {
77+
if (!ordered) {
78+
return this.graph.nodes();
79+
} else {
80+
const result: string[][] = [];
81+
for (let y = 0; y < this.size; y++) {
82+
const node: string[] = [];
83+
if (y == 0) {
84+
node.push(this.coords2algebraic(0,0));
85+
}
86+
for (let x = 0; x < 5*y; x++) {
87+
node.push(this.coords2algebraic(x,y));
88+
}
89+
result.push(node);
90+
}
91+
return result;
92+
}
93+
}
94+
95+
public neighbours(node: string): string[] {
96+
return this.graph.neighbors(node);
97+
}
98+
99+
public path(from: string, to: string): string[] | null {
100+
return bidirectional(this.graph, from, to);
101+
}
102+
}

0 commit comments

Comments
 (0)