Skip to content

Commit 6c557b1

Browse files
authored
Merge pull request #61 from Mind-Sports-Games/pla-777-bg-multi-add-doubling-cube-action-sg-ui
Pla 777 bg multi add doubling cube action sg UI
2 parents fafe7c4 + ac1288c commit 6c557b1

File tree

7 files changed

+262
-20
lines changed

7 files changed

+262
-20
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "chessground",
3-
"version": "7.11.1-pstrat3.8",
3+
"version": "7.11.1-pstrat3.9",
44
"description": "playstrategy.org chess ui, forked from lichess.org",
55
"type": "module",
66
"module": "dist/chessground.js",

src/board.ts

+89-12
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,9 @@ export function areMyDiceAtDomPos(
672672
myPlayerIndex: cg.PlayerIndex,
673673
bounds: ClientRect,
674674
variant: cg.Variant = 'chess',
675+
cubeActions: cg.CubeAction[] = [],
675676
): boolean {
677+
if (cubeActions && cubeActions.length > 0) return false;
676678
if (turnPlayerIndex !== myPlayerIndex) return false;
677679
const correctWidth =
678680
(orientation === 'p1' && turnPlayerIndex === 'p2') || (orientation === 'p1vflip' && turnPlayerIndex === 'p1')
@@ -683,22 +685,97 @@ export function areMyDiceAtDomPos(
683685
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctWidth && correctHeight;
684686
}
685687

686-
export function isButtonAtDomPos(
688+
function isButtonAtPos(
687689
pos: cg.NumberPair,
688690
orientation: cg.Orientation,
689691
turnPlayerIndex: cg.PlayerIndex,
690-
myPlayerIndex: cg.PlayerIndex,
691692
bounds: ClientRect,
692-
variant: cg.Variant = 'chess',
693+
placement: 'left' | 'right',
693694
): boolean {
694-
if (turnPlayerIndex !== myPlayerIndex) return false;
695+
const rightBound = placement === 'left' ? [9.875 / 15, 12.125 / 15] : [2.875 / 15, 5.125 / 15];
696+
const leftBound = placement === 'left' ? [2.875 / 15, 5.125 / 15] : [9.875 / 15, 12.125 / 15];
695697
const correctWidth =
696698
(orientation === 'p1' && turnPlayerIndex === 'p2') || (orientation === 'p1vflip' && turnPlayerIndex === 'p1')
697-
? (pos[0] - bounds.left) / bounds.width > 8 / 15 && (pos[0] - bounds.left) / bounds.width < 14 / 15
698-
: (pos[0] - bounds.left) / bounds.width > 1 / 15 && (pos[0] - bounds.left) / bounds.width < 7 / 15;
699+
? (pos[0] - bounds.left) / bounds.width > rightBound[0] && (pos[0] - bounds.left) / bounds.width < rightBound[1]
700+
: (pos[0] - bounds.left) / bounds.width > leftBound[0] && (pos[0] - bounds.left) / bounds.width < leftBound[1];
699701
const correctHeight =
700-
(pos[1] - bounds.top) / bounds.height > 6.5 / 15 && (pos[1] - bounds.top) / bounds.height < 8.5 / 15;
701-
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctWidth && correctHeight;
702+
(pos[1] - bounds.top) / bounds.height > 6.95 / 15 && (pos[1] - bounds.top) / bounds.height < 8.05 / 15;
703+
return correctWidth && correctHeight;
704+
}
705+
706+
export function isUndoButtonAtDomPos(
707+
pos: cg.NumberPair,
708+
orientation: cg.Orientation,
709+
turnPlayerIndex: cg.PlayerIndex,
710+
myPlayerIndex: cg.PlayerIndex,
711+
bounds: ClientRect,
712+
variant: cg.Variant = 'chess',
713+
cubeActions: cg.CubeAction[] = [],
714+
): boolean {
715+
if (cubeActions && cubeActions.length > 0) return false;
716+
if (turnPlayerIndex !== myPlayerIndex) return false;
717+
const correctPlacement = isButtonAtPos(pos, orientation, turnPlayerIndex, bounds, 'left');
718+
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctPlacement;
719+
}
720+
721+
export function isDoubleButtonAtDomPos(
722+
pos: cg.NumberPair,
723+
orientation: cg.Orientation,
724+
turnPlayerIndex: cg.PlayerIndex,
725+
myPlayerIndex: cg.PlayerIndex,
726+
bounds: ClientRect,
727+
variant: cg.Variant = 'chess',
728+
cubeActions: cg.CubeAction[] = [],
729+
): boolean {
730+
if (!(cubeActions && cubeActions.includes('offer'))) return false;
731+
if (turnPlayerIndex !== myPlayerIndex) return false;
732+
const correctPlacement = isButtonAtPos(pos, orientation, turnPlayerIndex, bounds, 'left');
733+
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctPlacement;
734+
}
735+
736+
export function isRollButtonAtDomPos(
737+
pos: cg.NumberPair,
738+
orientation: cg.Orientation,
739+
turnPlayerIndex: cg.PlayerIndex,
740+
myPlayerIndex: cg.PlayerIndex,
741+
bounds: ClientRect,
742+
variant: cg.Variant = 'chess',
743+
cubeActions: cg.CubeAction[] = [],
744+
): boolean {
745+
if (!(cubeActions && cubeActions.includes('offer'))) return false;
746+
if (turnPlayerIndex !== myPlayerIndex) return false;
747+
const correctPlacement = isButtonAtPos(pos, orientation, turnPlayerIndex, bounds, 'right');
748+
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctPlacement;
749+
}
750+
751+
export function isDropButtonAtDomPos(
752+
pos: cg.NumberPair,
753+
orientation: cg.Orientation,
754+
turnPlayerIndex: cg.PlayerIndex,
755+
myPlayerIndex: cg.PlayerIndex,
756+
bounds: ClientRect,
757+
variant: cg.Variant = 'chess',
758+
cubeActions: cg.CubeAction[] = [],
759+
): boolean {
760+
if (!(cubeActions && cubeActions.includes('reject'))) return false;
761+
if (turnPlayerIndex !== myPlayerIndex) return false;
762+
const correctPlacement = isButtonAtPos(pos, orientation, turnPlayerIndex, bounds, 'left');
763+
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctPlacement;
764+
}
765+
766+
export function isTakeButtonAtDomPos(
767+
pos: cg.NumberPair,
768+
orientation: cg.Orientation,
769+
turnPlayerIndex: cg.PlayerIndex,
770+
myPlayerIndex: cg.PlayerIndex,
771+
bounds: ClientRect,
772+
variant: cg.Variant = 'chess',
773+
cubeActions: cg.CubeAction[] = [],
774+
): boolean {
775+
if (!(cubeActions && cubeActions.includes('accept'))) return false;
776+
if (turnPlayerIndex !== myPlayerIndex) return false;
777+
const correctPlacement = isButtonAtPos(pos, orientation, turnPlayerIndex, bounds, 'right');
778+
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctPlacement;
702779
}
703780

704781
export function isPocketAtDomPos(
@@ -711,8 +788,8 @@ export function isPocketAtDomPos(
711788
const correctWidth = (pos[0] - bounds.left) / bounds.width < 8 / 15 && (pos[0] - bounds.left) / bounds.width > 7 / 15;
712789
const correctHeight =
713790
(orientation === 'p1' && turnPlayerIndex === 'p1') || (orientation === 'p1vflip' && turnPlayerIndex === 'p2')
714-
? (pos[1] - bounds.top) / bounds.height > 2 / 15 && (pos[1] - bounds.top) / bounds.height < 7.4 / 15
715-
: (pos[1] - bounds.top) / bounds.height > 7.6 / 15 && (pos[1] - bounds.top) / bounds.height < 13 / 15;
791+
? (pos[1] - bounds.top) / bounds.height > 1.6 / 15 && (pos[1] - bounds.top) / bounds.height < 7 / 15
792+
: (pos[1] - bounds.top) / bounds.height > 8 / 15 && (pos[1] - bounds.top) / bounds.height < 13.4 / 15;
716793
return (variant === 'backgammon' || variant === 'hyper' || variant === 'nackgammon') && correctWidth && correctHeight;
717794
}
718795

@@ -725,9 +802,9 @@ export function reorderDice(state: HeadlessState): void {
725802
}
726803
}
727804

728-
export function undoButtonPressed(state: HeadlessState): void {
805+
export function buttonPressed(state: HeadlessState, button: cg.Button): void {
729806
if (state.gameButtonsActive) {
730-
callUserFunction(state.events.undoButton);
807+
callUserFunction(state.events.buttonClick, button);
731808
}
732809
}
733810

src/config.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@ export interface Config {
1717
coordinates?: boolean; // include coords attributes
1818
boardScores?: boolean; //include board-scores attributes
1919
dice?: cg.Dice[]; // dice to display on the board
20+
doublingCube?: cg.DoublingCube; // doubling cube to display on the board
21+
cubeActions?: cg.CubeAction[]; // actions to display on the doubling cube related options
2022
canUndo?: boolean; // can user undo thier last action
2123
showUndoButton?: boolean; //show the undo button
2224
gameButtonsActive?: boolean; // can user process game buttons (e.g. swap dice, undo)
25+
multiPointState?: cg.MultiPointState; // state of the multi-point game (e.g. backgammon)
2326
autoCastle?: boolean; // immediately complete the castle by moving the rook after king move
2427
viewOnly?: boolean; // don't bind events: the user will never be able to move pieces around
2528
selectOnly?: boolean; // only allow user to select squares/pieces (multiple selection allowed)
@@ -97,7 +100,7 @@ export interface Config {
97100
select?: (key: cg.Key) => void; // called when a square is selected
98101
insert?: (elements: cg.Elements) => void; // when the board DOM has been (re)inserted
99102
selectDice?: (dice: cg.Dice[]) => void; //when the dice have been selected (to swap order)
100-
undoButton?: () => void; //when the undo button hass been selected for backgammon
103+
buttonClick?: (button: cg.Button) => void; //when a game button has been selected (backgammon only atm)
101104
};
102105
dropmode?: {
103106
active?: boolean;
@@ -135,6 +138,8 @@ export function configure(state: HeadlessState, config: Config): void {
135138
if (config.dropmode?.dropDests) state.dropmode.dropDests = undefined;
136139
if (config.drawable?.autoShapes) state.drawable.autoShapes = [];
137140
if (config.dice) state.dice = [];
141+
if (config.doublingCube) state.doublingCube = undefined;
142+
if (config.cubeActions) state.cubeActions = [];
138143

139144
merge(state, config);
140145

src/events.ts

+76-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ import * as draw from './draw';
44
import { cancelDropMode, drop } from './drop';
55
import { eventPosition, isRightButton, backgammonPosDiff } from './util';
66
import * as cg from './types';
7-
import { areMyDiceAtDomPos, isButtonAtDomPos, userMove, userLift, reorderDice, undoButtonPressed } from './board';
7+
import {
8+
areMyDiceAtDomPos,
9+
isUndoButtonAtDomPos,
10+
isDoubleButtonAtDomPos,
11+
isRollButtonAtDomPos,
12+
isDropButtonAtDomPos,
13+
isTakeButtonAtDomPos,
14+
userMove,
15+
userLift,
16+
reorderDice,
17+
buttonPressed,
18+
} from './board';
819
import { Piece } from './types';
920

1021
type MouchBind = (e: cg.MouchEvent) => void;
@@ -83,23 +94,85 @@ function startDragOrDraw(s: State): MouchBind {
8394
s.myPlayerIndex,
8495
s.dom.bounds(),
8596
s.variant,
97+
s.cubeActions,
8698
)
8799
) {
88100
reorderDice(s);
89101
stopProcessingClick(e);
90102
return;
91103
}
92104
if (
93-
isButtonAtDomPos(
105+
isUndoButtonAtDomPos(
94106
eventPosition(e)!,
95107
s.orientation,
96108
s.turnPlayerIndex,
97109
s.myPlayerIndex,
98110
s.dom.bounds(),
99111
s.variant,
112+
s.cubeActions,
100113
)
101114
) {
102-
undoButtonPressed(s);
115+
buttonPressed(s, 'undo');
116+
stopProcessingClick(e);
117+
return;
118+
}
119+
if (
120+
isDoubleButtonAtDomPos(
121+
eventPosition(e)!,
122+
s.orientation,
123+
s.turnPlayerIndex,
124+
s.myPlayerIndex,
125+
s.dom.bounds(),
126+
s.variant,
127+
s.cubeActions,
128+
)
129+
) {
130+
buttonPressed(s, 'double');
131+
stopProcessingClick(e);
132+
return;
133+
}
134+
if (
135+
isRollButtonAtDomPos(
136+
eventPosition(e)!,
137+
s.orientation,
138+
s.turnPlayerIndex,
139+
s.myPlayerIndex,
140+
s.dom.bounds(),
141+
s.variant,
142+
s.cubeActions,
143+
)
144+
) {
145+
buttonPressed(s, 'roll');
146+
stopProcessingClick(e);
147+
return;
148+
}
149+
if (
150+
isDropButtonAtDomPos(
151+
eventPosition(e)!,
152+
s.orientation,
153+
s.turnPlayerIndex,
154+
s.myPlayerIndex,
155+
s.dom.bounds(),
156+
s.variant,
157+
s.cubeActions,
158+
)
159+
) {
160+
buttonPressed(s, 'drop');
161+
stopProcessingClick(e);
162+
return;
163+
}
164+
if (
165+
isTakeButtonAtDomPos(
166+
eventPosition(e)!,
167+
s.orientation,
168+
s.turnPlayerIndex,
169+
s.myPlayerIndex,
170+
s.dom.bounds(),
171+
s.variant,
172+
s.cubeActions,
173+
)
174+
) {
175+
buttonPressed(s, 'take');
103176
stopProcessingClick(e);
104177
return;
105178
}

src/state.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@ export interface HeadlessState {
2424
coordinates: boolean; // include coords attributes
2525
boardScores: boolean; //include board-scores attributes
2626
dice: cg.Dice[]; // dice to display on the board
27+
doublingCube?: cg.DoublingCube; // doubling cube to display on the board (backgammon)
28+
cubeActions?: cg.CubeAction[]; // actions to display on the doubling cube related options (backgammon)
2729
canUndo: boolean; // can user undo their last action (backgammon)
2830
showUndoButton: boolean; // render the undo button (backgammon)
2931
gameButtonsActive: boolean; // can user process game buttons (e.g. swap dice, undo)
32+
multiPointState?: cg.MultiPointState; // state of the multi-point game (e.g. backgammon)
3033
autoCastle: boolean; // immediately complete the castle by moving the rook after king move
3134
viewOnly: boolean; // don't bind events: the user will never be able to move pieces around
3235
selectOnly: boolean; // only allow user to select squares/pieces (multiple selection allowed)
@@ -128,7 +131,7 @@ export interface HeadlessState {
128131
select?: (key: cg.Key) => void; // called when a square is selected
129132
insert?: (elements: cg.Elements) => void; // when the board DOM has been (re)inserted
130133
selectDice?: (dice: cg.Dice[]) => void; //when the dice have been selected (to swap order)
131-
undoButton?: () => void; //when the undo button hass been selected for backgammon
134+
buttonClick?: (button: cg.Button) => void; //when a game button has been selected (backgammon only atm)
132135
};
133136
drawable: Drawable;
134137
exploding?: cg.Exploding;

src/types.ts

+15
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,15 @@ export interface SimpleGoScores {
314314
p2: number;
315315
}
316316

317+
export interface DoublingCube {
318+
owner: PlayerIndex | 'both';
319+
value: number;
320+
}
321+
322+
export type CubeAction = 'offer' | 'accept' | 'reject';
323+
324+
export type Button = 'undo' | 'double' | 'roll' | 'take' | 'drop';
325+
317326
export interface Dice {
318327
value: number;
319328
isAvailable: boolean;
@@ -324,6 +333,12 @@ export interface BackgammonScores {
324333
p2: number;
325334
}
326335

336+
export interface MultiPointState {
337+
target: number;
338+
p1: number;
339+
p2: number;
340+
}
341+
327342
export const shogiVariants: Variant[] = ['shogi', 'minishogi', 'kyotoshogi', 'dobutsu', 'gorogoro', 'torishogi'];
328343
export const xiangqiVariants: Variant[] = ['xiangqi', 'minixiangqi', 'manchu', 'janggi'];
329344
export const goVariants: Variant[] = ['go9x9', 'go13x13', 'go19x19'];

0 commit comments

Comments
 (0)