|
import scala.util.Random |
|
|
|
object ScalaJSExample extends js.JSApp{ |
|
def main()={ |
|
val warriorStarts = Simulation("Warrior, starting, looks for a Fiery War Axe", targetCards = 2, otherMulligans = 15, keep = true) |
|
val warrior = Seq(warriorStarts, warriorStarts.copy(name = "Warrior, coin, looks for a Fiery War Axe", starts = false)) |
|
|
|
val warrior2Starts = Simulation("Warrior, starting, looks desperately for a Fiery War Axe", targetCards = 2, otherMulligans = 28, keep = true) |
|
val warrior2 = Seq(warrior2Starts, warrior2Starts.copy(name = "Warrior, coin, looks desperately for a Fiery War Axe", starts = false)) |
|
|
|
val warlockStarts = Simulation("Warlock, starting, chance of Doomguard", targetCards = 2, otherMulligans = 15, keep = false) |
|
val warlock = Seq(warlockStarts, warlockStarts.copy(name = "Warlock, coin, chance of Doomguard", starts = false)) |
|
|
|
val druidStarts = Simulation("Druid, starting, chance of acceleration", targetCards = 4, otherMulligans = 26, keep = true) |
|
val druid = Seq(druidStarts, druidStarts.copy(name = "Druid, coin, chance of acceleration", starts = false)) |
|
|
|
|
|
for { |
|
s <- druid |
|
} { |
|
println(s.name) |
|
for { |
|
i <- 0 to 10 |
|
p = s.copy(turn = i).simulate |
|
} println(f"turn $i : $p%.1f") |
|
} |
|
} |
|
|
|
|
|
case class Simulation( |
|
name: String, |
|
starts: Boolean = true, |
|
targetCards: Int = 2, |
|
turn: Int = 2, |
|
otherMulligans: Int = 20, |
|
keep: Boolean = true, |
|
size: Int = 5000) { |
|
|
|
def initialSize = if (starts) 3 else 4 |
|
|
|
val keyCards = List.fill(targetCards)(KeyCard) |
|
val mulliganedCards = List.fill(otherMulligans)(EndCard) |
|
val keepCards = List.fill(30 - keyCards.size - mulliganedCards.size)(StartCard) |
|
val deck = keyCards ::: mulliganedCards ::: keepCards |
|
|
|
def details = { |
|
val key = deck.count(_ == KeyCard) |
|
val mull = deck.count(_ == EndCard) |
|
val keep = deck.count(_ == StartCard) |
|
s"$key key cards, $mull cards to mull, $keep cards to keep" |
|
} |
|
|
|
def simulate: Float = { |
|
val results = List.fill(size)(simulateOnce) |
|
results.count(identity) * 100F / size |
|
} |
|
|
|
def simulateOnce: Boolean = { |
|
val initial = Situation(Random.shuffle(deck)) |
|
val initialHand = initial.draw(initialSize) |
|
//println(s"hand : ${initialHand.hand}") |
|
val mulligans = initialHand.mulligan |
|
//println(s"after mull : ${mulligans.hand}") |
|
val end = mulligans.draw(turn) |
|
end.hand.find(_ == KeyCard).nonEmpty |
|
} |
|
|
|
trait Card { |
|
def shouldMulligan: Boolean |
|
} |
|
object KeyCard extends Card { |
|
val shouldMulligan = !keep |
|
override val toString="key" |
|
} |
|
object StartCard extends Card { |
|
val shouldMulligan = false |
|
override val toString="start" |
|
} |
|
object EndCard extends Card { |
|
val shouldMulligan = true |
|
override val toString="end" |
|
} |
|
|
|
case class Situation(deck: List[Card], hand: List[Card] = Nil) { |
|
def draw: Situation = { |
|
val (h, t) = (deck.head, deck.tail) |
|
Situation(deck = t, hand = h :: hand) |
|
} |
|
|
|
def mulligan: Situation= { |
|
val discard = hand.filter(_.shouldMulligan) |
|
//println(s"discard $discard") |
|
val Situation(deck, h)=draw(discard.size) |
|
Situation(deck, h.diff(discard)) |
|
} |
|
|
|
def replace: Situation = { |
|
val (h, t) = (hand.head, hand.tail) |
|
Situation(hand = t, deck = Random.shuffle(h :: deck)) |
|
} |
|
|
|
final def replace(n: Int): Situation = |
|
if (n == 0) this |
|
else replace.replace(n - 1) |
|
|
|
final def draw(n: Int): Situation = |
|
if (n == 0) this |
|
else draw.draw(n - 1) |
|
|
|
} |
|
} |
|
|
|
} |