Skip to content

Instantly share code, notes, and snippets.

@krismuniz
Created January 9, 2021 03:44
Show Gist options
  • Save krismuniz/eaa26ccdb2ee6a524d96a50fe1432feb to your computer and use it in GitHub Desktop.
Save krismuniz/eaa26ccdb2ee6a524d96a50fe1432feb to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// Available variables:
// - Machine
// - interpret
// - assign
// - send
// - sendParent
// - spawn
// - raise
// - actions
// - XState (all XState exports)
const fetchMachine = Machine({
id: 'brisca',
context: {
deck: [],
players: [
// { id: v4(), name: 'pedro', hand: [], tricks: [] },
// { id: v4(), name: 'juana', hand: [], tricks: [] },
// { id: v4(), name: 'jose', hand: [], tricks: [] },
// { id: v4(), name: 'maría', hand: [], tricks: [] },
],
board: [],
turn: -1,
roundWinner: -1,
},
initial: 'welcome',
states: {
welcome: {
on: {
BEGIN_SETUP: {
target: 'setup',
},
},
},
setup: {
on: {
ADD_PLAYER: {
cond: 'canAcceptAnotherPlayer',
actions: ['addPlayer'],
target: 'setup',
},
START_GAME: {
cond: 'hasRightAmountOfPlayers',
target: 'play',
},
},
},
play: {
initial: 'deck',
states: {
deck: {
initial: 'idle',
states: {
idle: {
on: {
CREATE_DECK: {
actions: ['createDeck'],
target: 'created',
},
},
},
created: {
on: {
DEAL: {
actions: ['dealCards'],
target: 'end',
},
},
},
end: {
type: 'final',
},
},
onDone: {
target: 'round',
},
},
round: {
initial: 'round_start',
states: {
round_start: {
entry: ['resetBoard', 'determineFirstTurn'],
always: {
target: 'turn',
},
},
turn: {
on: {
PLAY_CARD: {
cond: 'isPlayerTurn',
actions: ['playCard', 'setNextTurn'],
target: 'turn',
},
},
always: {
cond: 'noTurnsLeft',
target: 'round_end',
},
},
round_end: {
entry: ['setRoundWinner', 'drawCards'],
type: 'final',
},
},
onDone: [
{
cond: 'noRoundsLeft',
target: 'game_end',
},
{
target: 'round',
},
],
},
game_end: {
entry: ['summarizeGame'],
type: 'final',
},
},
},
over: {},
},
},
{
actions: {
addPlayer: assign((context, event) => {
context.players.push({
id: v4(),
name: event.name,
hand: [],
tricks: [],
})
}),
createDeck: assign((context) => {
context.deck = createDeck(true)
}),
dealCards: assign((context) => {
const desiredLength = context.deck.length - context.players.length * 3
while (context.deck.length > desiredLength) {
for (const player of context.players) {
player.hand.push(context.deck.pop())
}
}
const killerSuit = context.deck[context.deck.length - 1].suit
context.killerSuit = killerSuit
}),
resetBoard: assign((context) => {
context.board = []
}),
determineFirstTurn: assign((context) => {
if (context.roundWinner === -1) {
context.turn = 0
} else {
context.turn = context.roundWinner
}
}),
playCard: assign((context, event) => {
const hand = context.players.find((p) => p.id === event.playerId).hand
const cardIndex = hand.findIndex((c) => event.cardId === c.id)
context.board.push({
playerId: event.playerId,
card: hand.splice(cardIndex, 1)[0],
})
}),
setNextTurn: assign((context) => {
context.turn = (context.turn + 1) % context.players.length
}),
setRoundWinner: assign((context) => {
const leadingSuit = context.board[0]?.card.suit
const rankedPlays = context.board.sort(
sortPlaysByCardRank(context.killerSuit, leadingSuit)
)
context.roundWinner = context.players.findIndex(
(p) => p.id === rankedPlays[0].playerId
)
}),
drawCards: assign((context) => {
if (context.deck.length === 0) return
for (const player of context.players) {
player.hand.push(context.deck.pop())
}
}),
},
guards: {
isPlayerTurn: (context, event) =>
context.players.findIndex((p) => event.playerId === p.id) ===
context.turn,
noRoundsLeft: (context) =>
context.players.every((p) => p.hand.length === 0),
noTurnsLeft: (context) => context.board.length === context.players.length,
canAcceptAnotherPlayer: (context) => context.players.length < 4,
hasRightAmountOfPlayers: (context) =>
context.players.length > 1 && context.players.length <= 4,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment