diff --git a/locales/en/apgames.json b/locales/en/apgames.json index adcaf789..47d3a33b 100644 --- a/locales/en/apgames.json +++ b/locales/en/apgames.json @@ -5092,7 +5092,8 @@ "TOO_MANY": "You may not place more than two tiles." }, "product": { - "INSTRUCTIONS": "Players place, on empty hexes, two stones of either color. The only exception is on the first turn, where the first player places just one stone of either color.", + "INITIAL_INSTRUCTIONS": "At the start, place one stone of either color. Click current friendly stone to flip color, click again to empty hex.", + "INSTRUCTIONS": "Players place, on empty hexes, two stones of either color. Click current friendly stone to flip color, click again to empty hex.", "INCOMPLETE_TURN": "To complete the turn you need two placements.", "INVALID_PLACEMENT": "Unable to interpret the move notation: {{move}}.", "NORMALISE": "The move needs to be normalised. Try {{normalised}}.", diff --git a/src/games/product.ts b/src/games/product.ts index 6287fa27..f4cb09f8 100644 --- a/src/games/product.ts +++ b/src/games/product.ts @@ -264,7 +264,9 @@ export class ProductGame extends GameBase { newmove = `${this.currplayer}${cell}`; } else { const moves : string[] = move.split(","); - newmove = this.processMoves(moves, cell, this.currplayer).sort((a, b) => this.sort(a, b)).join(","); + newmove = this.processMoves(moves, cell, this.currplayer) + .sort((a, b) => this.sort(a, b)) + .join(","); } const result = this.validateMove(newmove) as IClickResult; if (!result.valid) { @@ -306,7 +308,11 @@ export class ProductGame extends GameBase { result.valid = true; result.complete = -1; result.canrender = true; - result.message = i18next.t("apgames:validation.product.INSTRUCTIONS", {count: nMovesTurn}); + if (this.stack.length == 1) { + result.message = i18next.t("apgames:validation.product.INITIAL_INSTRUCTIONS"); + } else { + result.message = i18next.t("apgames:validation.product.INSTRUCTIONS"); + } return result; } @@ -316,7 +322,7 @@ export class ProductGame extends GameBase { if (moves.length > nMovesTurn) { result.valid = false; - result.message = i18next.t("apgames:validation.product.TOO_MANY_MOVES", {count: nMovesTurn}); + result.message = i18next.t("apgames:validation.product.TOO_MANY_MOVES"); return result; } @@ -325,9 +331,9 @@ export class ProductGame extends GameBase { try { for (const move of moves) { currentMove = move.slice(1); - const [, y] = this.graph.algebraic2coords(currentMove); - // `algebraic2coords` does not check if the cell is on the board fully. - if (y < 0) { throw new Error("Invalid cell."); } + if (! (this.graph.listCells() as string []).includes(currentMove)) { + throw new Error("Invalid cell."); + } } } catch { result.valid = false; @@ -338,7 +344,7 @@ export class ProductGame extends GameBase { // Is is an empty cell? let notEmpty; for (const move of moves) { - if (this.board.has(move.slice(1))) { notEmpty = move; break; } + if (this.board.has(move.slice(1))) { notEmpty = move.slice(1); break; } } if (notEmpty) { result.valid = false; @@ -347,7 +353,7 @@ export class ProductGame extends GameBase { } // possible to use moves() list to validate, but regex is (kind of?) fun - const regex = new RegExp(`^\\d[a-z]\\d+(,\\d[a-z]\\d+)?$`); + const regex = new RegExp(`^[12][a-z]\\d+(,[12][a-z]\\d+)?$`); if (!regex.test(m)) { result.valid = false; result.message = i18next.t("apgames:validation.product.INVALID_PLACEMENT", {move: m});