Skip to content

Commit

Permalink
Synchronize dice
Browse files Browse the repository at this point in the history
  • Loading branch information
ProLoser committed Sep 15, 2024
1 parent 35f4eb0 commit ce3fce9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 33 deletions.
1 change: 0 additions & 1 deletion 404.html

This file was deleted.

7 changes: 5 additions & 2 deletions src/Game/Dice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ type DiceProps = {
onClick: MouseEventHandler,
values: [number?, number?]
}
type ImageKey = keyof typeof IMAGES

export default function Dice({ onClick, values }: DiceProps) {
const left: ImageKey = `black${values[0] || 6}`
const right: ImageKey = `white${values[1] || 6}`
return <div className="dice" onClick={onClick}>
<img src={IMAGES[`black${values[0] || 6}`]} />
<img src={IMAGES[`white${values[1] || 6}`]} />
<img src={IMAGES[left]} />
<img src={IMAGES[right]} />
</div>
}
78 changes: 48 additions & 30 deletions src/Game/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ function rollDie() {
return Math.floor(Math.random() * 6) + 1
}

function vibrate() {
navigator.vibrate?.([50, 50, 60, 30, 90, 20, 110, 10, 150])
}

export default function Game() {
const [blackHome, setBlackHome] = useState(0)
const [whiteHome, setWhiteHome] = useState(0)
Expand All @@ -29,11 +33,20 @@ export default function Game() {
const game = useContext(GameContext);
const { move: sendMove } = useContext(MultiplayerContext);

// Subscribe to Game
useEffect(() => {
if (game?.exists()) {
setBoard(game.val().state)
const subscriber = (snapshot: firebase.database.DataSnapshot) => {
setBoard(snapshot.val().state)
const value = snapshot.val()
setBoard(value.state)
if (value.dice)
setDice(oldDice => {
const newDice = value.dice.split('-').map(Number)
if (oldDice[0] === newDice[0] && oldDice[1] === newDice[1]) return oldDice;
vibrate()
return newDice;
})
}
game.ref.on('value', subscriber)
return () => {
Expand All @@ -44,81 +57,86 @@ export default function Game() {
}
}, [game])

const onSelect = useCallback((position:number|null) => {
if (position === null || selected === position) {
setSelected(null);
} else if (selected === null) {
setSelected(position);
} else {
move(selected, position);
setSelected(null);
}
}, [selected])
const roll = useCallback(() => {
vibrate()
const newDice = [rollDie(), rollDie()]
game?.ref.update({ dice: newDice.join('-') })
setDice(newDice)
}, [game])

// TODO: Validate moves against dice
const move = useCallback((from: number | "white" | "black", to: number) => {
if (from == to) return; // no move
const nextBoard = [...board];
const moveLabel = from + "/" + to;
// @TODO Make the moveLabel more descriptive https://en.wikipedia.org/wiki/Backgammon_notation
let moveLabel; // @see https://en.wikipedia.org/wiki/Backgammon_notation
if (from == "white") { // white re-enter
if (board[to] == -1) { // hit
moveLabel = `bar/${to}*`
setBlackBar(bar => bar + 1)
nextBoard[to] = 0
}
if (board[to] >= -1) { // move
setWhiteBar(bar => bar - 1)
nextBoard[to] = 1
} else if (board[to] >= -1) { // move
moveLabel = `bar/${to}`
setWhiteBar(bar => bar - 1)
nextBoard[to]++
}
} else { return; } // blocked
} else if (from == 'black') { // black re-enter
if (board[to] == 1) { // hit
moveLabel = `bar/${to}*`
setWhiteBar(bar => bar + 1)
nextBoard[to] = 0
}
if (board[to] <= 1) { // move
setBlackBar(bar => bar - 1)
nextBoard[to] = -1
} else if (board[to] <= 1) { // move
moveLabel = `bar/${to}`
setBlackBar(bar => bar - 1)
nextBoard[to]--
}
} else { return; } // blocked
} else {
const offense = board[from];
const defense = board[to];

if (defense === undefined) { // bear off
moveLabel = `${from}/off`
if (offense > 0) {
setWhiteHome(count => count + 1)
} else {
setBlackHome(count => count + 1)
}
} else if (!defense || Math.sign(defense) === Math.sign(offense)) { // move
moveLabel = `${from}/${to}`
nextBoard[to] += Math.sign(offense)
} else if (Math.abs(defense) === 1) { // hit
moveLabel = `${from}/${to}*`
nextBoard[to] = -Math.sign(defense);
if (offense > 0)
setBlackBar(bar => bar + 1)
else
setWhiteBar(bar => bar + 1)
} else { // stalemate
return
}
} else { return; } // blocked

nextBoard[from] -= Math.sign(offense)
}

setBoard(nextBoard);
sendMove(nextBoard, moveLabel);
}, [board, game])

const roll = useCallback(() => {
navigator.vibrate?.([50,50,60,30,90,20,110,10,150])
setDice([rollDie(), rollDie()])
}, [])
}, [board, game, sendMove])

const onDragOver: DragEventHandler = useCallback((event) => { event.preventDefault(); }, [])
const onDrop: DragEventHandler = useCallback((event) => {
event.preventDefault();
let from = parseInt(event.dataTransfer?.getData("text")!)
return move(from, -1,)
}, [move])
const onSelect = useCallback((position: number | null) => {
if (position === null || selected === position) {
setSelected(null);
} else if (selected === null) {
setSelected(position);
} else {
move(selected, position);
setSelected(null);
}
}, [selected, move])

return <div id="board">
<Toolbar />
Expand Down

0 comments on commit ce3fce9

Please sign in to comment.