UNPKG

binmat

Version:
170 lines (169 loc) 6.19 kB
import { shuffle } from "@samual/lib/shuffle" import { Role, CardModifier, StatusCode } from "./shared.js" const PowersOfTwo = [2, 4, 8, 16, 32, 64, 128, 256] function doCombat(state, lane) { const roleTurn = (state.turn % 2) + 1, laneDeck = state.laneDecks[lane], laneDiscardPile = state.laneDiscardPiles[lane], defenderStack = state.defenderStacks[lane].cards, attackerStack = state.attackerStacks[lane], defenderStackWasFaceUp = state.defenderStacks[lane].isFaceUp, defenderStackBeforeCombat = [...defenderStack], attackerStackBeforeCombat = [...attackerStack], attackerCardsTrapped = [], defenderCardsTrapped = [] roleTurn == Role.Defender ? (flipDefenderStack(), flipAttackerStack()) : (flipAttackerStack(), flipDefenderStack()) let cardsDrawnToDiscard, defenderSum = 0, defenderWildCards = 0, breakPresent = !1 const defenderBounceIndexes = [] for (const [index, card] of defenderStack.entries()) switch (card[0]) { case CardModifier.Trap: break case CardModifier.Wild: defenderWildCards++ break case CardModifier.Bounce: defenderBounceIndexes.push(index) break case CardModifier.Break: breakPresent = !0 break case "a": defenderSum += 10 break default: defenderSum += Number(card[0]) } const attackerBounceIndexes = [] let attackerSum = 0, attackerWildCards = 0 for (const [index, card] of attackerStack.entries()) switch (card[0]) { case CardModifier.Trap: break case CardModifier.Wild: attackerWildCards++ break case CardModifier.Bounce: attackerBounceIndexes.push(index) break case CardModifier.Break: breakPresent = !0 break case "a": attackerSum += 10 break default: attackerSum += Number(card[0]) } let attackerAttackPower = 0 if (attackerWildCards) { for (; attackerSum >= PowersOfTwo[attackerAttackPower]; ) attackerAttackPower++ attackerAttackPower += attackerWildCards } else attackerAttackPower = PowersOfTwo.indexOf(attackerSum) + 1 let cardsDrawn, defenderAttackPower = 0 if (defenderWildCards) { for (; defenderSum >= PowersOfTwo[defenderAttackPower]; ) defenderAttackPower++ defenderAttackPower += defenderWildCards } else defenderAttackPower = PowersOfTwo.indexOf(defenderSum) + 1 let attackerStackDiscarded, damageValue = 0 const defenderBouncesDiscarded = [], attackerBouncesDiscarded = [] if ( attackerBounceIndexes.length || defenderBounceIndexes.length || (!attackerAttackPower && !defenderAttackPower) ) { for (const index of defenderBounceIndexes.reverse()) { const bounceDiscarded = defenderStack.splice(index, 1)[0] defenderBouncesDiscarded.push(bounceDiscarded), state.attackerDiscardPile.push(bounceDiscarded) } for (const index of attackerBounceIndexes.reverse()) { const bounceDiscarded = attackerStack.splice(index, 1)[0] attackerBouncesDiscarded.push(bounceDiscarded), laneDiscardPile.push(bounceDiscarded) } ;(attackerStackDiscarded = [...attackerStack]), (cardsDrawnToDiscard = []), (cardsDrawn = []) } else if (defenderAttackPower > attackerAttackPower) (attackerStackDiscarded = [...attackerStack]), laneDiscardPile.push(...attackerStack.splice(0)), (cardsDrawnToDiscard = []), (cardsDrawn = []) else if ( ((attackerStackDiscarded = [...attackerStack]), (damageValue = breakPresent ? Math.max(attackerAttackPower, defenderStack.length) : attackerAttackPower - defenderAttackPower + 1), damageValue > defenderStack.length) ) { const cardsToDraw = damageValue - defenderStack.length if (cardsToDraw > laneDeck.length + laneDiscardPile.length) return { status: StatusCode.AttackerWin, attackerStack: attackerStackBeforeCombat, defenderStack: defenderStackBeforeCombat, attackerAttackPower: attackerAttackPower, defenderAttackPower: defenderAttackPower, damageValue: damageValue, cardsDrawn: [...laneDeck, ...laneDiscardPile], attackerCardsTrapped: attackerCardsTrapped, defenderCardsTrapped: defenderCardsTrapped, attackerBouncesDiscarded: attackerBouncesDiscarded, defenderBouncesDiscarded: defenderBouncesDiscarded, attackerStackDiscarded: attackerStackDiscarded, defenderStackWasFaceUp: defenderStackWasFaceUp, cardsDrawnToDiscard: [...defenderStack].reverse() } ;(cardsDrawnToDiscard = defenderStack.splice(0).reverse()), state.attackerDiscardPile.push(...cardsDrawnToDiscard), cardsToDraw > laneDeck.length && laneDeck.push(...shuffle(laneDiscardPile.splice(0))), (cardsDrawn = laneDeck.splice(-cardsToDraw)), state.attackerHand.push(...cardsDrawn) } else (cardsDrawnToDiscard = defenderStack.splice(-damageValue).reverse()), state.attackerDiscardPile.push(...cardsDrawnToDiscard), (cardsDrawn = []) return ( state.attackerDiscardPile.push(...attackerStack.splice(0)), (state.defenderStacks[lane].isFaceUp = Boolean(defenderStack.length)), { status: StatusCode.Ok, attackerStack: attackerStackBeforeCombat, defenderStack: defenderStackBeforeCombat, attackerAttackPower: attackerAttackPower, defenderAttackPower: defenderAttackPower, damageValue: damageValue, cardsDrawn: cardsDrawn, attackerBouncesDiscarded: attackerBouncesDiscarded, attackerCardsTrapped: attackerCardsTrapped, attackerStackDiscarded: attackerStackDiscarded, defenderBouncesDiscarded: defenderBouncesDiscarded, defenderCardsTrapped: defenderCardsTrapped, defenderStackWasFaceUp: defenderStackWasFaceUp, cardsDrawnToDiscard: cardsDrawnToDiscard } ) function flipDefenderStack() { if (!state.defenderStacks[lane].isFaceUp) for (const card of defenderStack) { if (!attackerStack.length) break if (card[0] != CardModifier.Trap) continue const trappedCard = attackerStack.pop() attackerCardsTrapped.push(trappedCard), laneDiscardPile.push(trappedCard) } } function flipAttackerStack() { for (const card of attackerStack) { if (!defenderStack.length) break if (card[0] != CardModifier.Trap) continue const trappedCard = defenderStack.pop() defenderCardsTrapped.push(trappedCard), state.attackerDiscardPile.push(trappedCard) } } } export { PowersOfTwo, doCombat }