@dumpster-fire/game
Advanced tools
Comparing version 1.6.0 to 1.7.0
{ | ||
"name": "@dumpster-fire/game", | ||
"version": "1.6.0", | ||
"version": "1.7.0", | ||
"main": "src/index", | ||
@@ -23,3 +23,3 @@ "dependencies": { | ||
}, | ||
"gitHead": "1b826d06df7293a9b43f58f104ebdaac290124ee" | ||
"gitHead": "3ba02ac7b211bc4048e1c9f0cb7a3db30697d484" | ||
} |
236
src/index.js
@@ -48,2 +48,21 @@ import { Game, PlayerView } from "boardgame.io/core"; | ||
const hasGameWinner = (G, ctx) => { | ||
const playersInGame = Object.entries(G.incidents).filter( | ||
([, incidents]) => incidents.length < 3 | ||
); | ||
if (playersInGame.length === 1) { | ||
console.log(playersInGame[0][0], " has won the game!"); | ||
return { winner: playersInGame[0][0] }; | ||
} | ||
return false; | ||
}; | ||
const setError = (G, ctx, error) => { | ||
G.players[ctx.currentPlayer].errors = [error]; | ||
// ctx.events.endPhase({ next: ctx.phase }); | ||
}; | ||
const game = Game({ | ||
@@ -75,2 +94,3 @@ name: "dumpster-fire", | ||
preview: [], | ||
errors: [], | ||
}; | ||
@@ -135,26 +155,37 @@ | ||
skipDraw: (G, ctx) => { | ||
// can player skip draw? | ||
if (!G.phaseState.canSkipDraw) { | ||
throw new Error("You need to draw a card."); | ||
} | ||
try { | ||
// can player skip draw? | ||
if (!G.phaseState.canSkipDraw) { | ||
throw new Error("You need to draw a card."); | ||
} | ||
G.gameLog.push(`Player #${ctx.currentPlayer} has skipped drawing a card`); | ||
G.gameLog.push( | ||
`Player #${ctx.currentPlayer} has skipped drawing a card` | ||
); | ||
ctx.events.endPhase(); | ||
ctx.events.endPhase(); | ||
} catch (err) { | ||
setError(G, ctx, err.message); | ||
} | ||
}, | ||
discard: (G, ctx, card) => { | ||
if (card.type === CardType.INCIDENT) { | ||
throw new Error("You can't discard an Incident, cheater."); | ||
} | ||
try { | ||
if (card.type === CardType.INCIDENT) { | ||
throw new Error("You can't discard an Incident, cheater."); | ||
} | ||
checkPlayerHasCard(G, ctx, card); | ||
checkPlayerHasCard(G, ctx, card); | ||
// TODO: make sure player owns card and that it is not an incident | ||
discardCard(G, ctx, card, ctx.currentPlayer); | ||
// TODO: make sure player owns card and that it is not an incident | ||
discardCard(G, ctx, card, ctx.currentPlayer); | ||
G.gameLog.push(`Player #${ctx.currentPlayer} has discarded a card`); | ||
G.gameLog.push(`Player #${ctx.currentPlayer} has discarded a card`); | ||
} catch (err) { | ||
setError(G, ctx, err.message); | ||
} | ||
}, | ||
finishAction: (G, ctx) => { | ||
console.log("finish action"); | ||
// finish playing cards, go to draw phase | ||
@@ -240,90 +271,96 @@ ctx.events.endPhase(); | ||
playCard: (G, ctx, card, ...args) => { | ||
const msg = `Player #${ctx.playerID} played: ${card.type}`; | ||
console.log(msg); | ||
try { | ||
checkPlayerHasCard(G, ctx, card); | ||
G.gameLog.push(msg); | ||
// Card gets added to `phaseState.played` at the end of the function | ||
// so check here if card has been played this turn already | ||
checkHasPlayedCard(G, ctx, card); | ||
checkPlayerHasCard(G, ctx, card); | ||
// Check validation logic first | ||
if (typeof validators[card.type] === "function") { | ||
validators[card.type](G, ctx, card, ...args); | ||
} | ||
const msg = `Player #${ctx.playerID} played: ${card.type}`; | ||
console.log(msg); | ||
// Card gets added to `phaseState.played` at the end of the function | ||
// so check here if card has been played this turn already | ||
checkHasPlayedCard(G, ctx, card); | ||
G.gameLog.push(msg); | ||
// Check validation logic first | ||
if (typeof validators[card.type] === "function") { | ||
validators[card.type](G, ctx, card, ...args); | ||
} | ||
// card logic | ||
const logic = { | ||
[CardType.RETRO]: (G, ctx, card) => { | ||
G.phaseState.canDrawFromDiscard = true; | ||
G.phaseState.retro = true; | ||
// card logic | ||
const logic = { | ||
[CardType.RETRO]: (G, ctx, card) => { | ||
G.phaseState.canDrawFromDiscard = true; | ||
G.phaseState.retro = true; | ||
}, | ||
// Draw card from discard pile immediately | ||
drawCard(G, ctx); | ||
}, | ||
[CardType.REPRIORITIZE]: (G, ctx, card) => { | ||
G.turnDirection = G.turnDirection * -1; | ||
ctx.events.endTurn(); | ||
}, | ||
[CardType.REPRIORITIZE]: (G, ctx, card) => { | ||
G.turnDirection = G.turnDirection * -1; | ||
ctx.events.endTurn(); | ||
}, | ||
[CardType.PULL_REQUEST]: (G, ctx, card) => { | ||
G.pullRequests.push([ | ||
ctx.playerID, | ||
card, | ||
G.incidents[ctx.playerID].shift(), | ||
0, | ||
]); | ||
G.phaseState.canSkipDraw = true; | ||
}, | ||
[CardType.PULL_REQUEST]: (G, ctx, card) => { | ||
G.pullRequests.push([ | ||
ctx.playerID, | ||
card, | ||
G.incidents[ctx.playerID].shift(), | ||
0, | ||
]); | ||
G.phaseState.canSkipDraw = true; | ||
}, | ||
[CardType.CODE_REVIEW]: (G, ctx, card) => { | ||
G.phaseState.activeCard = card; | ||
ctx.events.endPhase({ next: CardType.CODE_REVIEW }); | ||
}, | ||
[CardType.CODE_REVIEW]: (G, ctx, card) => { | ||
G.phaseState.activeCard = card; | ||
ctx.events.endPhase({ next: CardType.CODE_REVIEW }); | ||
}, | ||
[CardType.BLAME]: (G, ctx, card, target) => { | ||
ctx.events.endPhase({ next: CardType.BLAME }); | ||
}, | ||
[CardType.BLAME]: (G, ctx, card, target) => { | ||
ctx.events.endPhase({ next: CardType.BLAME }); | ||
}, | ||
[CardType.QUICK_MEETING]: (G, ctx, card) => { | ||
const nextCard = G.deck[0]; | ||
// TODO handle security with card (e.g. player can see card id and trace | ||
// the card throughout future turns) | ||
G.players[ctx.currentPlayer].preview = [nextCard]; | ||
G.phaseState.canSkipDraw = true; | ||
ctx.events.endPhase({ next: CardType.QUICK_MEETING }); | ||
}, | ||
[CardType.QUICK_MEETING]: (G, ctx, card) => { | ||
const nextCard = G.deck[0]; | ||
// TODO handle security with card (e.g. player can see card id and trace | ||
// the card throughout future turns) | ||
G.players[ctx.currentPlayer].preview = [nextCard]; | ||
G.phaseState.canSkipDraw = true; | ||
ctx.events.endPhase({ next: CardType.QUICK_MEETING }); | ||
}, | ||
[CardType.MONITOR]: (G, ctx, card) => { | ||
// TODO handle security with card (e.g. player can see card id and trace | ||
// the card throughout future turns) | ||
// Prob just needs new ids when we preview | ||
[CardType.MONITOR]: (G, ctx, card) => { | ||
// TODO handle security with card (e.g. player can see card id and trace | ||
// the card throughout future turns) | ||
// Prob just needs new ids when we preview | ||
G.players[ctx.currentPlayer].preview = G.deck.splice(0, 3); | ||
G.phaseState.reshuffle = true; | ||
ctx.events.endPhase({ next: "monitor" }); | ||
}, | ||
G.players[ctx.currentPlayer].preview = G.deck.splice(0, 3); | ||
G.phaseState.reshuffle = true; | ||
ctx.events.endPhase({ next: "monitor" }); | ||
}, | ||
[CardType.FORCE_PUSH]: (G, ctx, card) => { | ||
// Collect every Incident with a Pull Request on top. | ||
// Shuffle those Incidents into the deck and discard the Pull Requests | ||
[CardType.FORCE_PUSH]: (G, ctx, card) => { | ||
// Collect every Incident with a Pull Request on top. | ||
// Shuffle those Incidents into the deck and discard the Pull Requests | ||
G.pullRequests | ||
.filter(([, , , turn]) => turn > 0) | ||
.forEach(([, card, incident]) => { | ||
// Discard incident | ||
discardCard(G, ctx, card, ctx.currentPlayer); | ||
G.pullRequests | ||
.filter(([, , , turn]) => turn > 0) | ||
.forEach(([, card, incident]) => { | ||
// Discard incident | ||
discardCard(G, ctx, card, ctx.currentPlayer); | ||
// Insert incident back into the deck | ||
// TODO handle security with card (e.g. player can see card id and trace the card throughout future turns) | ||
insertRandomlyIntoDeck(G, ctx, incident); | ||
}); | ||
// Insert incident back into the deck | ||
// TODO handle security with card (e.g. player can see card id and trace the card throughout future turns) | ||
insertRandomlyIntoDeck(G, ctx, incident); | ||
}); | ||
G.pullRequests = | ||
G.pullRequests.filter(([, , , turn]) => turn === 0) || []; | ||
}, | ||
}; | ||
G.pullRequests = | ||
G.pullRequests.filter(([, , , turn]) => turn === 0) || []; | ||
}, | ||
}; | ||
G.phaseState.played.push(card); | ||
logic[card.type](G, ctx, card, ...args); | ||
G.phaseState.played.push(card); | ||
logic[card.type](G, ctx, card, ...args); | ||
} catch (err) { | ||
setError(G, ctx, err.message); | ||
} | ||
}, | ||
@@ -438,9 +475,20 @@ }, | ||
onPhaseBegin: (G, ctx) => { | ||
if (G.incidents[`${ctx.currentPlayer}`].length >= 3) { | ||
console.log("too many incidents....ending turn"); | ||
ctx.events.endTurn(); | ||
// Check for winner | ||
const result = hasGameWinner(G, ctx); | ||
if (result) { | ||
ctx.events.endGame(result); | ||
} else { | ||
if (G.incidents[ctx.currentPlayer].length >= 3) { | ||
console.log("too many incidents....ending turn"); | ||
ctx.events.endTurn(); | ||
} | ||
checkForEmptyDeck(G, ctx); | ||
} | ||
checkForEmptyDeck(G, ctx); | ||
}, | ||
onPhaseEnd: (G, ctx) => { | ||
console.log("on phase end"); | ||
G.players[ctx.currentPlayer].errors = []; | ||
}, | ||
}, | ||
@@ -488,9 +536,5 @@ | ||
endGameIf: (G, ctx) => { | ||
const playersInGame = Object.entries(G.incidents).filter( | ||
([playerID, incidents]) => incidents.length < 3 | ||
); | ||
if (playersInGame === 1) { | ||
console.log(playersInGame[0][0], " has won the game!"); | ||
return { winner: playersInGame[0][0] }; | ||
const result = hasGameWinner(G, ctx); | ||
if (result) { | ||
return result; | ||
} | ||
@@ -497,0 +541,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25894
632