Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions locales/en/apgames.json
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@
"garden": "To make it very clear what happened on a previous turn, each move is displayed over four separate boards. The first board shows the game after the piece was first placed. The second board shows the state after adjacent pieces were flipped. The third board shows any harvests. The fourth board is the final game state and is where you make your moves.\n\nIn our implementation, black is always the \"tome\" or tie-breaker colour. The last player to harvest black will have a `0.1` after their score.",
"gyges": "The goal squares are adjacent to all the cells in the back row. The renderer cannot currently handle \"floating\" cells.",
"halma": "To prevent the [drawish nature](https://boardgamegeek.com/thread/3706389/unspoiling-halma-redux) of the game, the following rules apply: (a) a player wins if the opposite home-base is complete with at least one friendly stone (David Parlett's criteria); (b) Any piece in the player's home-base must make progress towards the enemy camp whenever this is possible by jumping over an enemy piece. (Zillions rule, to remove drawish strategies); (c) No stone can return to its home-base.\n\n[Halma](https://en.wikipedia.org/wiki/Halma) was one of the first commercial successes for an abstract game. The game was designed by [George Howard Monks](https://en.wikipedia.org/wiki/George_Howard_Monks) in 1883/4. It is said that Halma was inspired by an older British game called *Hoppity*. However, this game has no documentation or surviving boards, turning this lineal statement into a historical mystery. Halma was later adapted (c.1892/3) into an even bigger success: [Chinese Checkers](https://boardgamegeek.com/boardgame/2386/chinese-checkers) (which could easily be played by three or six players).\n\nSuper Halma is a more dynamic, uncredited variant, presented in the 1992 book **New Rules for Classic Games** by Wayne Schmittberger. This variant proposes long jumps, where the number of empty cells before and after the jumped stone must be equal. The base's move restrictions still apply in this implementation of Super Halma.",
"halmaclimbers": "Halma Climbers was designed by Alexander Brady in 2021.\n\nThis implementation allows players to move at will, rather than restricting them to moves that strictly increase the overall score (as mentioned in David Ploog's [ruleset](https://blackandwhite.develz.org/games/HalmaClimbers.pdf)). This design choice removes the burden of calculating many combinations just to find out that no more moves exist that increase the overall score. This also prevents the software from having to compute an excessive number of permutations, which can be quite high given the two-action turn structure and complex jump sequences. The game ends when both players pass their turns consecutively, or if the last player's evacuate his own area, or if the current player does not have forward jumps available.",
"halmaclimbers": "Halma Climbers was designed by Alexander Brady in 2021.\n\nThis implementation allows players to move at will, rather than restricting them to moves that strictly increase the overall score (as mentioned in David Ploog's [ruleset](https://blackandwhite.develz.org/games/HalmaClimbers.pdf)). This design choice removes the burden of checking multiple move combinations just to find out that no more moves exist that increase the overall score. This also prevents the software from having to compute an excessive number of permutations, which can be quite high given the two-action turn structure and complex jump sequences. The game ends when both players pass their turns consecutively, or if the previous player evacuate his own area, or if the current player does not have forward jumps available.",
"homeworlds": "The win condition is what's called \"Sinister Homeworlds.\" You only win by defeating the opponent to your left. If someone else does that, the game continues, but your left-hand opponent now shifts clockwise. For example, in a four-player game, if I'm South, then I win if I eliminate West. But if the North player ends up eliminating West, the game continues, but now my left-hand opponent is North.",
"jacynth": "More information on the Decktet system can be found on the [official Decktet website](https://www.decktet.com). Cards in players' hands are hidden from observers and opponents.",
"konane": "Several competing opening protocols exist, but the most common ruleset is the Naihe Ruleset, used by tournaments at the Bishop Museum in Hawaii and described in the BGG reference. This is what is implemented here.",
Expand Down Expand Up @@ -5098,18 +5098,19 @@
"PARTIAL": "Select an empty cell to place a second stone. It must be adjacent to the same number of groups as the first stone."
},
"halma": {
"INITIAL_INSTRUCTIONS": "Move to an adjacent empty cell, or multiple short-jump a friendly piece. Players cannot re-enter their home-base and cannot leave the enemy home-base once inside. Forward jumps over enemy stones inside the player's home-base takes precedence.",
"INITIAL_INSTRUCTIONS": "Move to an adjacent empty cell, or do a multiple short-jump with a friendly piece. Players cannot re-enter their home-base and cannot leave the enemy home-base once inside. Forward jumps over enemy stones inside the player's home-base takes precedence.",
"NONEXISTENT": "Trying to interact with a friendly piece that doesn't exist at {{where}}.",
"ILLEGAL_MOVE": "No piece can return to his home-base, nor can pieces inside the opponent's home-base leave again.",
"FORCED_MOVES": "Pieces still at home-base are forced to forward-jump over enemy neighbors: pick {{forced}}.",
"BAD_MOVE": "This movement is illegal!"
},
"halmaclimbers": {
"INITIAL_INSTRUCTIONS": "Either move to an adjacent empty cell, or make a multiple short-jump over pieces of either color. The sequence of jumps must start inside the player's home-base.",
"INSTRUCTIONS": "An action is a movement to an adjacent empty cell, or a multiple short-jump over pieces of either color. The sequence of jumps must start inside the player's home-base. Each player makes two actions.",
"INITIAL_INSTRUCTIONS": "Select a friendly piece and use it to jump over another piece, or pass your turn.",
"INSTRUCTIONS": "An action is either a backward movement to an adjacent empty cell, or a sequence of short-jumps over pieces of either color. The sequence of jumps must start inside the player's home-base. Each player makes two actions (or just pass his turn).",
"NEXT_ACTION": "When the first piece movement is decided, just click on the second stone to start moving or jumping.",
"NONEXISTENT": "Trying to interact with a friendly piece that doesn't exist at {{where}}!",
"ILLEGAL_JUMP": "The sequence of jumps must start inside the player's home-base!",
"TOO_MANY_ACTIONS": "This number of actions is not allowed: only one action at the beggining, then two!",
"TOO_MANY_ACTIONS": "This number of actions is not allowed: only one action at the beginning, then two!",
"BAD_MOVE": "This movement is illegal!"
},
"havannah": {
Expand Down
27 changes: 11 additions & 16 deletions src/games/halmaclimbers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GameBase, IAPGameState, IClickResult, ICustomButton, IIndividualState, IScores, IValidationResult } from "./_base";
import { APGamesInformation } from "../schemas/gameinfo";
import { APRenderRep, RowCol, Colourfuncs, MarkerFlood } from "@abstractplay/renderer/src/schemas/schema";
import { APRenderRep, RowCol, MarkerFlood } from "@abstractplay/renderer/src/schemas/schema";
import { APMoveResult } from "../schemas/moveresults";
import { reviver, UserFacingError, HexTriGraph } from "../common";
import { HexDir } from "../common/graphs/hextri";
Expand Down Expand Up @@ -430,9 +430,12 @@ export class HalmaClimbersGame extends GameBase {
result.complete = isJump ? 0 : 1; // moves are final, jumps can be multiple
}
result.canrender = true;
result.message = i18next.t("apgames:validation._general.VALID_MOVE");
if ( result.complete === 1 || m.includes(',') ) {
result.message = i18next.t("apgames:validation._general.VALID_MOVE");
} else {
result.message = i18next.t("apgames:validation.halmaclimbers.NEXT_ACTION");
}
return result;

}

public move(m: string, {trusted = false, partial = false} = {}): HalmaClimbersGame {
Expand Down Expand Up @@ -512,7 +515,7 @@ export class HalmaClimbersGame extends GameBase {
return this.homeBase(player).every(c => !this.board.has(c) || this.board.get(c) !== player);
}

private jumpsForward(player?: playerid): boolean {
private notJumpsForward(player?: playerid): boolean {
if (player === undefined) { player = this.currplayer; }
const res: string[] = [];
const g = this.graph;
Expand Down Expand Up @@ -544,7 +547,7 @@ export class HalmaClimbersGame extends GameBase {
// or if the player's home base is empty (the player that just ended his turn)
|| this.isBaseEmpty(prevplayer)
// or if the current player does not have forward jumps available
|| this.jumpsForward(this.currplayer);
|| this.notJumpsForward(this.currplayer);

if ( this.gameover ) {
const scoreP1 = this.getPlayerScore(1);
Expand Down Expand Up @@ -616,7 +619,7 @@ export class HalmaClimbersGame extends GameBase {
const [x, y] = this.graph.algebraic2coords(cell);
markers.push({
type: "flood",
colour: this.getPlayerColour(player),
colour: player,
opacity: 0.5,
points: [{ row: y, col: x }],
});
Expand All @@ -633,8 +636,8 @@ export class HalmaClimbersGame extends GameBase {
markers,
},
legend: {
A: { name: "piece", colour: this.getPlayerColour(1) },
B: { name: "piece", colour: this.getPlayerColour(2) },
A: { name: "piece", colour: 1 },
B: { name: "piece", colour: 2 },
},
pieces: pstr.map(p => p.join("")).join("\n"),
};
Expand Down Expand Up @@ -668,14 +671,6 @@ export class HalmaClimbersGame extends GameBase {
return rep;
}

public getPlayerColour(p: playerid): Colourfuncs {
if (p === 1) {
return { func: "custom", default: 1, palette: 1 };
} else {
return { func: "custom", default: 2, palette: 2 };
}
}

private isDigit(c: string): boolean {
return /^[0-9]$/.test(c);
}
Expand Down
Loading