Skip to content

Commit c2ec6aa

Browse files
committed
Merge branch 'develop'
2 parents 4781d2f + 99df44e commit c2ec6aa

File tree

5 files changed

+173
-18
lines changed

5 files changed

+173
-18
lines changed

src/common/dominoes/Domino.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
export interface IDominoData {
2+
l: number;
3+
r: number;
4+
}
5+
6+
export class Domino {
7+
public readonly l: number;
8+
public readonly r: number;
9+
10+
constructor(l: number, r: number) {
11+
this.l = Math.min(l, r);
12+
this.r = Math.max(l, r);
13+
}
14+
15+
public uid(): string {
16+
return `${this.l}|${this.r}`;
17+
}
18+
19+
public clone(): Domino {
20+
return new Domino(this.l, this.r);
21+
}
22+
23+
public serialize(): string {
24+
return JSON.stringify({l: this.l, r: this.r});
25+
}
26+
27+
public static deserialize(json: string): Domino {
28+
const data = JSON.parse(json) as IDominoData;
29+
return new Domino(data.l, data.r);
30+
}
31+
}

src/common/dominoes/DominoDeck.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { Domino, IDominoData } from "./Domino";
2+
3+
interface IDeckItem {
4+
domino: Domino;
5+
faceUp: boolean;
6+
}
7+
8+
export class DominoDeck {
9+
private _dominoes: IDeckItem[];
10+
11+
public get dominoes(): Domino[] {
12+
return this._dominoes.map((d) => d.domino);
13+
}
14+
15+
public get size(): number {
16+
return this._dominoes.length;
17+
}
18+
19+
constructor(dominoes: Domino[] = []) {
20+
this._dominoes = dominoes.map((d) => ({ domino: d.clone(), faceUp: false }));
21+
}
22+
23+
public static fromDouble(n: number): DominoDeck {
24+
const dominoes: Domino[] = [];
25+
for (let i = 0; i <= n; i++) {
26+
for (let j = i; j <= n; j++) {
27+
dominoes.push(new Domino(i, j));
28+
}
29+
}
30+
return new DominoDeck(dominoes);
31+
}
32+
33+
public shuffle(justFaceDown = false): void {
34+
if (justFaceDown) {
35+
const indices: number[] = [];
36+
this._dominoes.forEach((d, i) => {
37+
if (!d.faceUp) {
38+
indices.push(i);
39+
}
40+
});
41+
for (let i = indices.length - 1; i > 0; i--) {
42+
const j = Math.floor(Math.random() * (i + 1));
43+
const idxI = indices[i];
44+
const idxJ = indices[j];
45+
[this._dominoes[idxI].domino, this._dominoes[idxJ].domino] = [this._dominoes[idxJ].domino, this._dominoes[idxI].domino];
46+
}
47+
} else {
48+
this._dominoes.forEach((d) => (d.faceUp = false));
49+
for (let i = this._dominoes.length - 1; i > 0; i--) {
50+
const j = Math.floor(Math.random() * (i + 1));
51+
[this._dominoes[i], this._dominoes[j]] = [this._dominoes[j], this._dominoes[i]];
52+
}
53+
}
54+
}
55+
56+
public draw(): Domino | undefined {
57+
const item = this._dominoes.pop();
58+
return item?.domino;
59+
}
60+
61+
public add(domino: Domino, faceUp = true): void {
62+
this._dominoes.push({ domino, faceUp });
63+
}
64+
65+
public remove(dominoes: Domino[]): void {
66+
for (const target of dominoes) {
67+
const idx = this._dominoes.findIndex((item) => (item.domino.l === target.l && item.domino.r === target.r));
68+
if (idx !== -1) {
69+
this._dominoes.splice(idx, 1);
70+
}
71+
}
72+
}
73+
74+
public revealAll(): void {
75+
this._dominoes.forEach((d) => (d.faceUp = true));
76+
}
77+
78+
public clone(): DominoDeck {
79+
const newDeck = new DominoDeck();
80+
newDeck._dominoes = this._dominoes.map((d) => ({ domino: d.domino.clone(), faceUp: d.faceUp }));
81+
return newDeck;
82+
}
83+
84+
public serialize(): string {
85+
return JSON.stringify(this._dominoes.map((d) => ({ l: d.domino.l, r: d.domino.r, faceUp: d.faceUp })));
86+
}
87+
88+
public static deserialize(json: string): DominoDeck {
89+
const data = JSON.parse(json) as (IDominoData & { faceUp?: boolean })[];
90+
const deck = new DominoDeck();
91+
deck._dominoes = data.map((d) => ({
92+
domino: new Domino(d.l, d.r),
93+
faceUp: d.faceUp ?? false,
94+
}));
95+
return deck;
96+
}
97+
}

src/common/dominoes/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { Domino } from "./Domino";
2+
export { DominoDeck } from "./DominoDeck";

src/games/minefield.ts

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -262,26 +262,43 @@ export class MinefieldGame extends GameBase {
262262
for (const delta of transform) {
263263
const nx = x + delta.dx;
264264
const ny = y + delta.dy;
265-
if (nx < 0 || nx >= this.boardSize || ny < 0 || ny >= this.boardSize) {
266-
match = false;
267-
break;
268-
}
269-
const check = this.coords2algebraic(nx, ny);
270-
const contents = this.board.get(check);
271265

272-
let isFriendly = (contents === player);
273-
let isEnemy = (contents !== undefined && contents !== player);
274-
let isEmpty = (contents === undefined);
266+
let isFriendly = false;
267+
let isEnemy = false;
268+
let isEmpty = false;
275269

276-
if (name === "cartwheel" && isEmpty) {
277-
if (ny === 0 || ny === this.boardSize - 1) {
278-
if (player === 1) { isFriendly = true; } else { isEnemy = true; }
279-
isEmpty = false;
270+
if (name === "cartwheel") {
271+
if (nx < -1 || nx > this.boardSize || ny < -1 || ny > this.boardSize) {
272+
match = false;
273+
break;
280274
}
281-
if (nx === 0 || nx === this.boardSize - 1) {
282-
if (player === 2) { isFriendly = true; } else { isEnemy = true; }
283-
isEmpty = false;
275+
276+
if (nx >= 0 && nx < this.boardSize && ny >= 0 && ny < this.boardSize) {
277+
const check = this.coords2algebraic(nx, ny);
278+
const contents = this.board.get(check);
279+
if (contents === player) { isFriendly = true; }
280+
else if (contents !== undefined) { isEnemy = true; }
281+
else { isEmpty = true; }
282+
} else {
283+
if (ny === -1 || ny === this.boardSize) {
284+
if (player === 1) { isFriendly = true; }
285+
else { isEnemy = true; }
286+
}
287+
if (nx === -1 || nx === this.boardSize) {
288+
if (player === 2) { isFriendly = true; }
289+
else { isEnemy = true; }
290+
}
291+
}
292+
} else {
293+
if (nx < 0 || nx >= this.boardSize || ny < 0 || ny >= this.boardSize) {
294+
match = false;
295+
break;
284296
}
297+
const check = this.coords2algebraic(nx, ny);
298+
const contents = this.board.get(check);
299+
if (contents === player) { isFriendly = true; }
300+
else if (contents !== undefined) { isEnemy = true; }
301+
else { isEmpty = true; }
285302
}
286303

287304
if (delta.payload === "f" && !isFriendly) {

test/games/minefield.test.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,17 @@ describe("Minefield", () => {
183183
expect(g.canPlace("j16", 2)).to.be.true;
184184
g = new MinefieldGame(undefined, ["cartwheel"]);
185185
g.board = new Map<string, playerid>([
186-
["c8", 1], ["d10", 2], ["d9", 2],
186+
["d1", 2], ["d2", 2],
187+
["e3", 1],
188+
["g1", 2], ["g2", 2]
187189
]);
188-
expect(g.canPlace("b8", 1)).to.be.false;
190+
expect(g.canPlace("f3", 1)).to.be.false;
191+
g = new MinefieldGame(undefined, ["cartwheel"]);
192+
g.board = new Map<string, playerid>([
193+
["c11", 2], ["c10", 2],
194+
["b9", 1],
195+
]);
196+
expect(g.canPlace("a9", 1)).to.be.false;
189197
});
190198
});
191199

0 commit comments

Comments
 (0)