Skip to content

Commit

Permalink
allow shuffl e function to be dependency injected
Browse files Browse the repository at this point in the history
  • Loading branch information
samualtnorman committed Dec 31, 2024
1 parent ef70865 commit 82dba00
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export const CardStringSuits: CardStringSuit[] = [
CardStringSuit.Choice
]

export type ShuffleFunction = (cards: CardString[]) => CardString[]

export { MoveTag } from "./MoveTag"
export { Role } from "./Role"
export { StatusCode } from "./StatusCode"
13 changes: 9 additions & 4 deletions src/doCombat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { shuffle } from "@samual/lib/shuffle"
import type { CardString, CardStringSuit, CardStringFace, Lane, State } from "./common"
import type { LaxPartial } from "@samual/lib"
import { shuffle as defaultShuffleFunction } from "@samual/lib/shuffle"
import type { CardString, CardStringFace, CardStringSuit, Lane, ShuffleFunction, State } from "./common"
import { CardStringFaceModifier, Role, StatusCode } from "./common"

export type CombatData = {
Expand All @@ -20,7 +21,11 @@ export type CombatData = {

export const PowersOfTwo = [ 2, 4, 8, 16, 32, 64, 128, 256 ]

export function doCombat(state: State, lane: Lane): { status: StatusCode.Okay | StatusCode.AttackerWin } & CombatData {
export function doCombat(
state: State,
lane: Lane,
{ shuffleFunction: shuffle = defaultShuffleFunction }: LaxPartial<{ shuffleFunction: ShuffleFunction }> = {}
): { status: StatusCode.Okay | StatusCode.AttackerWin } & CombatData {
const roleTurn: Role = (state.turn % 2) + 1
const laneDeck = state.laneDecks[lane]
const laneDiscardPile = state.laneDiscardPiles[lane]
Expand Down Expand Up @@ -129,7 +134,7 @@ export function doCombat(state: State, lane: Lane): { status: StatusCode.Okay |
const attackerBouncesDiscarded: `?${CardStringSuit}`[] = []

if (
attackerBounceIndexes.length || defenderBounceIndexes.length || (!attackerAttackPower && !defenderAttackPower)
attackerBounceIndexes.length || defenderBounceIndexes.length || !(attackerAttackPower || defenderAttackPower)
) {
for (const index of defenderBounceIndexes.reverse()) {
const bounceDiscarded = defenderStack.splice(index, 1)[0]!
Expand Down
15 changes: 8 additions & 7 deletions src/doMove.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { LaxPartial } from "@samual/lib"
import type { CardString, Lane, Move, ShuffleFunction, State } from "./common"
import { AttackerDeck, MoveTag, StatusCode } from "./common"
import type { CombatData } from "./doCombat"
import { doMoveCombat } from "./doMoveCombat"
import { doMoveDiscard } from "./doMoveDiscard"
import { doMoveDraw } from "./doMoveDraw"
import { doMovePass } from "./doMovePass"
import { doMovePlay } from "./doMovePlay"
import { doMovePlayFaceUp } from "./doMovePlayFaceUp"
import type { CardString, Lane, Move, State } from "./common"
import { AttackerDeck, MoveTag, StatusCode } from "./common"

export function doMove(state: State, move: Move): {
export function doMove(state: State, move: Move, options?: LaxPartial<{ shuffleFunction: ShuffleFunction }>): {
status: StatusCode.Okay | StatusCode.AttackerWin | StatusCode.DefenderWin
binlog: string[]
} | { status: Exclude<StatusCode, StatusCode.Okay | StatusCode.AttackerWin | StatusCode.DefenderWin> } {
Expand All @@ -18,7 +19,7 @@ export function doMove(state: State, move: Move): {
switch (move.tag) {
case MoveTag.Draw: {
const deckIsEmpty = !(move.deck == AttackerDeck ? state.attackerDeck : state.laneDecks[move.deck]).length
const result = doMoveDraw(state, move.deck)
const result = doMoveDraw(state, move.deck, options)
const deck = move.deck == AttackerDeck ? `a` : move.deck

if (result.status == StatusCode.AttackerWin) {
Expand Down Expand Up @@ -63,7 +64,7 @@ export function doMove(state: State, move: Move): {
}

case MoveTag.PlayFaceUp: {
const result = doMovePlayFaceUp(state, move.card, move.lane)
const result = doMovePlayFaceUp(state, move.card, move.lane, options)

if (result.status == StatusCode.Okay || result.status == StatusCode.AttackerWin || result.status == StatusCode.DefenderWin) {
const binlog = [
Expand All @@ -84,7 +85,7 @@ export function doMove(state: State, move: Move): {
}

case MoveTag.Combat: {
const result = doMoveCombat(state, move.lane)
const result = doMoveCombat(state, move.lane, options)

if (result.status == StatusCode.Okay || result.status == StatusCode.DefenderWin || result.status == StatusCode.AttackerWin) {
const binlog = [
Expand All @@ -104,7 +105,7 @@ export function doMove(state: State, move: Move): {
}

case MoveTag.Discard: {
const result = doMoveDiscard(state, move.card, move.discardPile)
const result = doMoveDiscard(state, move.card, move.discardPile, options)

if (result.status == StatusCode.Okay || result.status == StatusCode.DefenderWin) {
const discardPile = move.discardPile == AttackerDeck ? `a` : move.discardPile
Expand Down
9 changes: 5 additions & 4 deletions src/doMoveCombat.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type { LaxPartial } from "@samual/lib"
import type { Lane, ShuffleFunction, State } from "./common"
import { Role, StatusCode } from "./common"
import type { CombatData } from "./doCombat"
import { doCombat } from "./doCombat"
import type { Lane, State } from "./common"
import { Role, StatusCode } from "./common"

export function doMoveCombat(state: State, lane: Lane): (
export function doMoveCombat(state: State, lane: Lane, options?: LaxPartial<{ shuffleFunction: ShuffleFunction }>): (
{ status: StatusCode.Okay | StatusCode.DefenderWin | StatusCode.AttackerWin } & CombatData
) | {
status:
Expand All @@ -22,7 +23,7 @@ export function doMoveCombat(state: State, lane: Lane): (
if (!state.attackerStacks[lane].length)
return { status: StatusCode.AttackerInitiatedCombatWithEmptyStack }

const combatResult = doCombat(state, lane)
const combatResult = doCombat(state, lane, options)

if (combatResult.status == StatusCode.AttackerWin)
return combatResult
Expand Down
12 changes: 9 additions & 3 deletions src/doMoveDiscard.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { shuffle } from "@samual/lib/shuffle"
import type { CardString, CardStringFace, Lane, State } from "./common"
import type { LaxPartial } from "@samual/lib"
import { shuffle as defaultShuffleFunction } from "@samual/lib/shuffle"
import type { CardString, CardStringFace, Lane, ShuffleFunction, State } from "./common"
import { AttackerDiscardPile, Role, StatusCode } from "./common"

export function doMoveDiscard(state: State, card: CardString | CardStringFace, discardPile: Lane | AttackerDiscardPile): {
export function doMoveDiscard(
state: State,
card: CardString | CardStringFace,
discardPile: Lane | AttackerDiscardPile,
{ shuffleFunction: shuffle = defaultShuffleFunction }: LaxPartial<{ shuffleFunction: ShuffleFunction }> = {}
): {
status: StatusCode.Okay | StatusCode.DefenderWin
cardDiscarded: CardString
cardsDrawn: [ CardString, CardString ] | undefined
Expand Down
11 changes: 8 additions & 3 deletions src/doMoveDraw.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { shuffle } from "@samual/lib/shuffle"
import type { CardString, Lane, State } from "./common"
import type { LaxPartial } from "@samual/lib"
import { shuffle as defaultShuffleFunction } from "@samual/lib/shuffle"
import type { CardString, Lane, ShuffleFunction, State } from "./common"
import { AttackerDeck, AttackerDiscardPile, Role, StatusCode } from "./common"

export function doMoveDraw(state: State, deckToDrawFrom: Lane | AttackerDeck): {
export function doMoveDraw(
state: State,
deckToDrawFrom: Lane | AttackerDeck,
{ shuffleFunction: shuffle = defaultShuffleFunction }: LaxPartial<{ shuffleFunction: ShuffleFunction }> = {}
): {
status: StatusCode.Okay | StatusCode.DefenderWin
cardDrawn: CardString
} | {
Expand Down
18 changes: 12 additions & 6 deletions src/doMovePlayFaceUp.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { LaxPartial } from "@samual/lib"
import { assert } from "@samual/lib/assert"
import type { CardString, CardStringFace, Lane, ShuffleFunction, State } from "./common"
import { CardStringFaceModifier, Role, StatusCode } from "./common"
import type { CombatData } from "./doCombat"
import { doCombat } from "./doCombat"
import type { CardString, CardStringFace, Lane, State } from "./common"
import { CardStringFaceModifier, Role, StatusCode } from "./common"

export function doMovePlayFaceUp(state: State, card: CardString | CardStringFace, lane: Lane): {
export function doMovePlayFaceUp(
state: State,
card: CardString | CardStringFace,
lane: Lane,
options?: LaxPartial<{ shuffleFunction: ShuffleFunction }>
): {
status: StatusCode.Okay | StatusCode.DefenderWin | StatusCode.AttackerWin
cardPlayed: CardString
combat: CombatData | undefined
Expand Down Expand Up @@ -43,7 +49,7 @@ export function doMovePlayFaceUp(state: State, card: CardString | CardStringFace

let status

({ status, ...combat } = doCombat(state, lane))
({ status, ...combat } = doCombat(state, lane, options))

if (status == StatusCode.AttackerWin)
return { status, cardPlayed, combat }
Expand Down Expand Up @@ -71,7 +77,7 @@ export function doMovePlayFaceUp(state: State, card: CardString | CardStringFace

let status

({ status, ...combat } = doCombat(state, lane))
({ status, ...combat } = doCombat(state, lane, options))

if (status == StatusCode.AttackerWin)
return { status, cardPlayed, combat }
Expand All @@ -81,7 +87,7 @@ export function doMovePlayFaceUp(state: State, card: CardString | CardStringFace

let status

({ status, ...combat } = doCombat(state, lane))
({ status, ...combat } = doCombat(state, lane, options))
assert(status != StatusCode.AttackerWin, `attacker won when playing a face up bounce`)
} else
return { status: StatusCode.PlayedCardFacedWrongWay }
Expand Down
11 changes: 7 additions & 4 deletions src/simulateGame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { BinmatArgs } from "./generateArgs"
import { generateArgsForAttacker, generateArgsForDefender } from "./generateArgs"
import { makeState } from "./makeState"
import { parseMove } from "./parseMove"
import type { MoveString, State } from "./common"
import type { MoveString, ShuffleFunction, State } from "./common"
import { MoveTag, Role, StatusCode, StatusCodeMessages } from "./common"

export type SimulateGameOptions = {
Expand All @@ -23,6 +23,8 @@ export type SimulateGameOptions = {

/** Intial state of binlog from attacker's last turn (should be odd numbered turn) @default [] */
attackerBinlog: string[]

shuffleFunction: ShuffleFunction
}

export type CLIContext = {
Expand Down Expand Up @@ -56,7 +58,8 @@ export function simulateGame(
onMove,
state = makeState(),
defenderBinlog = [],
attackerBinlog = []
attackerBinlog = [],
shuffleFunction
}: LaxPartial<SimulateGameOptions> = {}
): Role {
let endTime: number
Expand Down Expand Up @@ -157,7 +160,7 @@ export function simulateGame(
throw error
}

const result = doMove(state, move)
const result = doMove(state, move, { shuffleFunction })

switch (result.status) {
case StatusCode.Okay: break
Expand Down Expand Up @@ -187,7 +190,7 @@ export function simulateGame(
}

function doDefaultMove() {
const result = doMove(state, { tag: MoveTag.Pass })
const result = doMove(state, { tag: MoveTag.Pass }, { shuffleFunction })

switch (result.status) {
case StatusCode.Okay: break
Expand Down

0 comments on commit 82dba00

Please sign in to comment.