renamed some things and snuck in some testing code
This commit is contained in:
parent
a985417f83
commit
483e67bb16
@ -1,7 +1,7 @@
|
||||
package entries
|
||||
|
||||
import simulation.*
|
||||
import simulation.dice.DiceBag
|
||||
import simulation.dice.Dice
|
||||
import simulation.dice.RollType
|
||||
import simulation.fifthEd.AttackResult
|
||||
import simulation.fifthEd.AttackSimulatorModel
|
||||
@ -16,7 +16,8 @@ fun main() {
|
||||
val rounds = 1_000_000
|
||||
val start = System.currentTimeMillis()
|
||||
// val computedRounds = doSimulation(rounds)
|
||||
crunchBarbarian(21)
|
||||
// crunchPally(21)
|
||||
crunchRogue(18)
|
||||
// crunchMonk()
|
||||
val finish = System.currentTimeMillis()
|
||||
// println("Simulation finished $computedRounds rounds in: ${finish - start}ms")
|
||||
@ -34,7 +35,7 @@ fun crunchMonk(ac: Int= 18) {
|
||||
|
||||
val attackBless = MeleeAttackBuilder("1d20", "1d8", ac)
|
||||
.withAtkBonus(11)
|
||||
.withAtkBonus(DiceBag.plainDice("1d4"))
|
||||
.withAtkBonus(Dice.regular("1d4"))
|
||||
.withDmgBonus(7)
|
||||
.build()
|
||||
|
||||
@ -77,6 +78,96 @@ fun crunchBarbarian(defense: Int = 16){
|
||||
val attacks = listOf(Pair("Normal Attack", normalAttack), Pair("GWM Attack", gwmAttack))
|
||||
|
||||
|
||||
generateCombatSuggestions(attacks, rounds, defaultReport())
|
||||
}
|
||||
|
||||
fun crunchPally(defense: Int = 16){
|
||||
|
||||
val rounds = 1_000_000
|
||||
|
||||
val attackDice = "1d20"
|
||||
val weaponDice = "1d10"
|
||||
|
||||
|
||||
val normalAttack = MeleeAttackBuilder(attackDice, weaponDice, defense)
|
||||
//attack
|
||||
.withAtkBonus(5) // str mod
|
||||
.withAtkBonus(4) // proficiency bonus
|
||||
.withAtkBonus(4) // proficiency bonus
|
||||
.withAtkBonus(2) // weapon bonus
|
||||
.withAtkBonus(2) // arming
|
||||
//damage
|
||||
.withDmgBonus(2) // weapon bonus
|
||||
.withDmgBonus(5) // str mod
|
||||
.withDmgBonus(Dice.regular("1d4")) // polearm force
|
||||
.withDmgBonus(Dice.regular("1d8")) // passive smite
|
||||
.build()
|
||||
|
||||
|
||||
val gwmAttack = MeleeAttackBuilder(attackDice, weaponDice, defense)
|
||||
//attack
|
||||
.withAtkBonus(5) // str mod
|
||||
.withAtkBonus(-5) // GWM
|
||||
.withAtkBonus(4) // proficiency bonus
|
||||
.withAtkBonus(4) // proficiency bonus
|
||||
.withAtkBonus(2) // weapon bonus
|
||||
.withAtkBonus(2) // arming
|
||||
//damage
|
||||
.withDmgBonus(2) // weapon bonus
|
||||
.withDmgBonus(5) // str mod
|
||||
.withDmgBonus(10) // GWM
|
||||
.withDmgBonus(Dice.regular("1d4")) // polearm force
|
||||
.withDmgBonus(Dice.regular("1d8")) // passive smite
|
||||
.build()
|
||||
|
||||
val attacks = listOf(Pair("Normal Attack", normalAttack), Pair("GWM Attack", gwmAttack))
|
||||
|
||||
|
||||
generateCombatSuggestions(attacks, rounds, defaultReport())
|
||||
}
|
||||
|
||||
|
||||
fun crunchRogue(defense: Int = 18){
|
||||
val attackDice = "1d20"
|
||||
val bloodthirstDice = "1d20C19"
|
||||
val weaponDice = "1d10"
|
||||
val rounds = 1_000_000
|
||||
|
||||
|
||||
val crimsonMischief = MeleeAttackBuilder(attackDice, weaponDice, defense)
|
||||
//attack
|
||||
.withAtkBonus(16) // bonus total
|
||||
//damage
|
||||
.withDmgBonus(Dice.regular("10d6")) //sneak attack
|
||||
.withDmgBonus(7) //bonus total
|
||||
.withDmgBonus(7) //bonus total
|
||||
|
||||
|
||||
|
||||
|
||||
val bloodthirst = MeleeAttackBuilder(bloodthirstDice, weaponDice, defense)
|
||||
//attack
|
||||
.withAtkBonus(16) // bonus total
|
||||
//damage
|
||||
.withDmgBonus(Dice.regular("10d6")) //sneak attack
|
||||
.withDmgBonus(7) //bonus total
|
||||
|
||||
|
||||
|
||||
|
||||
val attacks = arrayListOf(
|
||||
Pair("Crimson Mischief", crimsonMischief.build()),
|
||||
Pair("Bloodthirst", bloodthirst.build())
|
||||
)
|
||||
|
||||
crimsonMischief.withAtkBonus(-5).withDmgBonus(10)
|
||||
bloodthirst.withAtkBonus(-5).withDmgBonus(10)
|
||||
|
||||
attacks.add(Pair("crimson Mischief sharpshooter", crimsonMischief.build()))
|
||||
attacks.add(Pair("Bloodthirst sharpshooter", bloodthirst.build()))
|
||||
|
||||
|
||||
|
||||
generateCombatSuggestions(attacks, rounds, defaultReport())
|
||||
}
|
||||
|
||||
@ -98,10 +189,12 @@ fun generateCombatSuggestions(
|
||||
|
||||
val report = reportFactory.build(label)
|
||||
|
||||
print("${attackInfo.first} $it\t")
|
||||
|
||||
|
||||
val res = report.computeResults(results)
|
||||
print("${attackInfo.first} $it\t")
|
||||
println(Report.formatReport(res.name, res.results))
|
||||
println()
|
||||
res
|
||||
}.toMap()
|
||||
}
|
||||
@ -128,6 +221,7 @@ fun generateCombatSuggestions(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun defaultReport(): ReportBuilder {
|
||||
return ReportBuilder.getInstance()
|
||||
.addRateMetric("Accuracy") { it.rollSucceeded }
|
||||
|
||||
@ -3,7 +3,7 @@ package simulation.dice
|
||||
/**
|
||||
* Dice with a modifiable crit threshold
|
||||
*/
|
||||
interface CritDice : Dice {
|
||||
interface CritDiceRoller : DiceRoller {
|
||||
val critThreshold: Int
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ interface CritDice : Dice {
|
||||
* for these attack dice.
|
||||
*
|
||||
* The critical hit threshold is determined based on the roll string used to construct
|
||||
* this [CritDice] instance.
|
||||
* this [CritDiceRoller] instance.
|
||||
*
|
||||
* @param result The [RollResult] to check for crit.
|
||||
* @return True if result meets or exceeds the crit threshold.
|
||||
@ -42,7 +42,7 @@ interface CritDice : Dice {
|
||||
internal class CritDiceImpl(
|
||||
override val rollString: String,
|
||||
override val modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
) : CritDice {
|
||||
) : CritDiceRoller {
|
||||
override val nDice: Int
|
||||
override val dieSize: Int
|
||||
|
||||
@ -1,111 +1,19 @@
|
||||
package simulation.dice
|
||||
|
||||
import simulation.dice.RollType.*
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Enumeration of different dice roll types.
|
||||
*
|
||||
* @property Advantage Rolls the dice twice and takes the higher result.
|
||||
* @property Normal Rolls the dice normally once.
|
||||
* @property Disadvantage Rolls the dice twice and takes the lower result.
|
||||
*/
|
||||
enum class RollType {
|
||||
/**
|
||||
* Rolls the dice once normally.
|
||||
*/
|
||||
Normal,
|
||||
|
||||
/**
|
||||
* Rolls the dice twice and returns the higher of the two results.
|
||||
*/
|
||||
Advantage,
|
||||
|
||||
/**
|
||||
* Rolls the dice twice and returns the lower of the two results.
|
||||
*/
|
||||
Disadvantage
|
||||
object Dice {
|
||||
fun regular(rollString: String, modifiers: List<DiceModifier<Int>> = ArrayList()): DiceRoller {
|
||||
return DiceImpl(rollString, modifiers)
|
||||
}
|
||||
|
||||
data class RollResult(val min: Int, val max: Int, val result: Int)
|
||||
|
||||
|
||||
interface Dice {
|
||||
val rollString: String
|
||||
val modifiers: List<DiceModifier<Int>>
|
||||
val nDice: Int
|
||||
val dieSize: Int
|
||||
|
||||
/**
|
||||
* Rolls the dice and returns the result.
|
||||
*
|
||||
* The roll result is determined based on the [rollType].
|
||||
*
|
||||
* The result is also modified by any [modifiers] that have been added to this [Dice].
|
||||
*
|
||||
* @param r The [Random] instance to use for the dice rolls
|
||||
* @return The result of the dice roll with modifiers applied
|
||||
* @see RollType
|
||||
*/
|
||||
fun roll(r: Random, rollType: RollType = Normal): RollResult {
|
||||
val range = (dieSize * nDice) - nDice
|
||||
val result = when (rollType) {
|
||||
Advantage -> advantageRoll(r, nDice, range)
|
||||
Disadvantage -> disadvantageRoll(r, nDice, range)
|
||||
else -> normalRoll(r, nDice, range)
|
||||
}
|
||||
return RollResult(nDice, dieSize * nDice, result)
|
||||
fun critDice(rollString: String, modifiers: List<DiceModifier<Int>> = ArrayList()): CritDiceRoller {
|
||||
return CritDiceImpl(rollString, modifiers)
|
||||
}
|
||||
|
||||
|
||||
private fun advantageRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
val roll1 = r.nextInt(range + 1)
|
||||
val roll2 = r.nextInt(range + 1)
|
||||
|
||||
return max(roll1, roll2) + nDice
|
||||
}
|
||||
|
||||
private fun disadvantageRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
val roll1 = r.nextInt(range + 1)
|
||||
val roll2 = r.nextInt(range + 1)
|
||||
|
||||
return min(roll1, roll2) + nDice
|
||||
}
|
||||
|
||||
private fun normalRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
return r.nextInt(range + 1) + nDice
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates all the modifiers passed to this Dice instance and returns their sum.
|
||||
*
|
||||
* @param r The Random instance to pass to each modifier's getBonus() method
|
||||
* @return The summed bonus values from all modifiers
|
||||
*/
|
||||
fun evaluateModifiers(r: Random, crit: Boolean = false): Int {
|
||||
return modifiers.sumOf { it.getBonus(r, crit) }
|
||||
}
|
||||
|
||||
|
||||
fun defaultParseFn(rollString: String): Pair<Int, Int> {
|
||||
val cleanRollString = rollString.lowercase()
|
||||
val parts = cleanRollString.split('d')
|
||||
return Pair(parts[0].toInt(), parts[1].toInt())
|
||||
}
|
||||
}
|
||||
|
||||
internal class DiceImpl(
|
||||
override val rollString: String,
|
||||
override val modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
) : Dice {
|
||||
override val nDice: Int
|
||||
override val dieSize: Int
|
||||
|
||||
init {
|
||||
val rollPair = defaultParseFn(rollString)
|
||||
nDice = rollPair.first
|
||||
dieSize = rollPair.second
|
||||
fun rerollDice(
|
||||
rollString: String,
|
||||
rerollThreshold: Int,
|
||||
modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
): RerollDiceRoller {
|
||||
return RerollDiceImpl(rollString, rerollThreshold, modifiers)
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
package simulation.dice
|
||||
|
||||
object DiceBag {
|
||||
fun plainDice(rollString: String, modifiers: List<DiceModifier<Int>> = ArrayList()): Dice {
|
||||
return DiceImpl(rollString, modifiers)
|
||||
}
|
||||
|
||||
fun critDice(rollString: String, modifiers: List<DiceModifier<Int>> = ArrayList()): CritDice {
|
||||
return CritDiceImpl(rollString, modifiers)
|
||||
}
|
||||
|
||||
fun rerollDice(
|
||||
rollString: String,
|
||||
rerollThreshold: Int,
|
||||
modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
): RerollDice {
|
||||
return RerollDiceImpl(rollString, rerollThreshold, modifiers)
|
||||
}
|
||||
}
|
||||
@ -21,16 +21,16 @@ interface DiceModifier<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A [DiceModifier] that generates a random bonus integer based on a provided [Dice].
|
||||
* A [DiceModifier] that generates a random bonus integer based on a provided [DiceRoller].
|
||||
*
|
||||
* On each call to [getBonus], it will roll the given [Dice] using the passed [Random]
|
||||
* On each call to [getBonus], it will roll the given [DiceRoller] using the passed [Random]
|
||||
* instance and return the result as a positive bonus amount.
|
||||
*
|
||||
* @param dice The [Dice] instance to use for generating bonus values.
|
||||
* @param dice The [DiceRoller] instance to use for generating bonus values.
|
||||
*/
|
||||
class DiceBonusModifier(private val dice: Dice) : DiceModifier<Int> {
|
||||
class DiceBonusModifier(private val dice: DiceRoller) : DiceModifier<Int> {
|
||||
|
||||
constructor(diceString: String):this(DiceBag.plainDice(diceString))
|
||||
constructor(diceString: String):this(Dice.regular(diceString))
|
||||
|
||||
override fun getBonus(r: Random, crit: Boolean): Int {
|
||||
return if (crit){
|
||||
@ -43,14 +43,14 @@ class DiceBonusModifier(private val dice: Dice) : DiceModifier<Int> {
|
||||
}
|
||||
|
||||
/**
|
||||
* A [DiceModifier] that applies a random penalty based on a [Dice].
|
||||
* A [DiceModifier] that applies a random penalty based on a [DiceRoller].
|
||||
*
|
||||
* On each call to [getBonus], it will roll the provided [Dice] object and return the
|
||||
* On each call to [getBonus], it will roll the provided [DiceRoller] object and return the
|
||||
* result as a negative number.
|
||||
*
|
||||
* @param dice The [Dice] to use for generating penalty values.
|
||||
* @param dice The [DiceRoller] to use for generating penalty values.
|
||||
*/
|
||||
class DicePenaltyModifier(private val dice: Dice): DiceModifier<Int> {
|
||||
class DicePenaltyModifier(private val dice: DiceRoller): DiceModifier<Int> {
|
||||
override fun getBonus(r: Random, crit: Boolean): Int {//can penalties ever crit?
|
||||
return -dice.roll(r).result
|
||||
}
|
||||
|
||||
111
src/main/kotlin/simulation/dice/DiceRoller.kt
Normal file
111
src/main/kotlin/simulation/dice/DiceRoller.kt
Normal file
@ -0,0 +1,111 @@
|
||||
package simulation.dice
|
||||
|
||||
import simulation.dice.RollType.*
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
* Enumeration of different dice roll types.
|
||||
*
|
||||
* @property Advantage Rolls the dice twice and takes the higher result.
|
||||
* @property Normal Rolls the dice normally once.
|
||||
* @property Disadvantage Rolls the dice twice and takes the lower result.
|
||||
*/
|
||||
enum class RollType {
|
||||
/**
|
||||
* Rolls the dice once normally.
|
||||
*/
|
||||
Normal,
|
||||
|
||||
/**
|
||||
* Rolls the dice twice and returns the higher of the two results.
|
||||
*/
|
||||
Advantage,
|
||||
|
||||
/**
|
||||
* Rolls the dice twice and returns the lower of the two results.
|
||||
*/
|
||||
Disadvantage
|
||||
}
|
||||
|
||||
data class RollResult(val min: Int, val max: Int, val result: Int)
|
||||
|
||||
|
||||
interface DiceRoller {
|
||||
val rollString: String
|
||||
val modifiers: List<DiceModifier<Int>>
|
||||
val nDice: Int
|
||||
val dieSize: Int
|
||||
|
||||
/**
|
||||
* Rolls the dice and returns the result.
|
||||
*
|
||||
* The roll result is determined based on the [rollType].
|
||||
*
|
||||
* The result is also modified by any [modifiers] that have been added to this [DiceRoller].
|
||||
*
|
||||
* @param r The [Random] instance to use for the dice rolls
|
||||
* @return The result of the dice roll with modifiers applied
|
||||
* @see RollType
|
||||
*/
|
||||
fun roll(r: Random, rollType: RollType = Normal): RollResult {
|
||||
val range = (dieSize * nDice) - nDice
|
||||
val result = when (rollType) {
|
||||
Advantage -> advantageRoll(r, nDice, range)
|
||||
Disadvantage -> disadvantageRoll(r, nDice, range)
|
||||
else -> normalRoll(r, nDice, range)
|
||||
}
|
||||
return RollResult(nDice, dieSize * nDice, result)
|
||||
}
|
||||
|
||||
|
||||
private fun advantageRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
val roll1 = r.nextInt(range + 1)
|
||||
val roll2 = r.nextInt(range + 1)
|
||||
|
||||
return max(roll1, roll2) + nDice
|
||||
}
|
||||
|
||||
private fun disadvantageRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
val roll1 = r.nextInt(range + 1)
|
||||
val roll2 = r.nextInt(range + 1)
|
||||
|
||||
return min(roll1, roll2) + nDice
|
||||
}
|
||||
|
||||
private fun normalRoll(r: Random, nDice: Int, range: Int): Int {
|
||||
return r.nextInt(range + 1) + nDice
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates all the modifiers passed to this Dice instance and returns their sum.
|
||||
*
|
||||
* @param r The Random instance to pass to each modifier's getBonus() method
|
||||
* @return The summed bonus values from all modifiers
|
||||
*/
|
||||
fun evaluateModifiers(r: Random, crit: Boolean = false): Int {
|
||||
return modifiers.sumOf { it.getBonus(r, crit) }
|
||||
}
|
||||
|
||||
|
||||
fun defaultParseFn(rollString: String): Pair<Int, Int> {
|
||||
val cleanRollString = rollString.lowercase()
|
||||
val parts = cleanRollString.split('d')
|
||||
return Pair(parts[0].toInt(), parts[1].toInt())
|
||||
}
|
||||
}
|
||||
|
||||
internal class DiceImpl(
|
||||
override val rollString: String,
|
||||
override val modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
) : DiceRoller {
|
||||
override val nDice: Int
|
||||
override val dieSize: Int
|
||||
|
||||
init {
|
||||
val rollPair = defaultParseFn(rollString)
|
||||
nDice = rollPair.first
|
||||
dieSize = rollPair.second
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ package simulation.dice
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
interface RerollDice : Dice {
|
||||
interface RerollDiceRoller : DiceRoller {
|
||||
val rollThreshold: Int
|
||||
override fun roll(r: Random, rollType: RollType): RollResult {
|
||||
val result = super.roll(r, rollType)
|
||||
@ -20,7 +20,7 @@ class RerollDiceImpl(
|
||||
override val rollString: String,
|
||||
override val rollThreshold: Int,
|
||||
override val modifiers: List<DiceModifier<Int>> = ArrayList()
|
||||
) : RerollDice{
|
||||
) : RerollDiceRoller{
|
||||
override val nDice: Int
|
||||
override val dieSize: Int
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package simulation.fifthEd
|
||||
|
||||
import simulation.dice.CritDice
|
||||
import simulation.dice.Dice
|
||||
import java.util.*
|
||||
import simulation.dice.CritDiceRoller
|
||||
import simulation.dice.DiceRoller
|
||||
|
||||
data class ActionRollInfo(val actionRoll: CritDice, val damageRoll: Dice)
|
||||
data class ActionRollInfo(val actionRoll: CritDiceRoller, val damageRoll: DiceRoller)
|
||||
|
||||
@ -91,12 +91,12 @@ class MeleeAttackBuilder(
|
||||
return this
|
||||
}
|
||||
|
||||
fun withAtkBonus(dice: Dice): MeleeAttackBuilder {
|
||||
fun withAtkBonus(dice: DiceRoller): MeleeAttackBuilder {
|
||||
attackModifiers.add(DiceBonusModifier(dice))
|
||||
return this
|
||||
}
|
||||
|
||||
fun withAtkPenalty(dice: Dice): MeleeAttackBuilder {
|
||||
fun withAtkPenalty(dice: DiceRoller): MeleeAttackBuilder {
|
||||
attackModifiers.add(DicePenaltyModifier(dice))
|
||||
return this
|
||||
}
|
||||
@ -106,12 +106,12 @@ class MeleeAttackBuilder(
|
||||
return this
|
||||
}
|
||||
|
||||
fun withDmgBonus(dice: Dice): MeleeAttackBuilder {
|
||||
fun withDmgBonus(dice: DiceRoller): MeleeAttackBuilder {
|
||||
damageModifiers.add(DiceBonusModifier(dice))
|
||||
return this
|
||||
}
|
||||
|
||||
fun withDmgPenalty(dice: Dice): MeleeAttackBuilder {
|
||||
fun withDmgPenalty(dice: DiceRoller): MeleeAttackBuilder {
|
||||
damageModifiers.add(DicePenaltyModifier(dice))
|
||||
return this
|
||||
}
|
||||
@ -119,8 +119,8 @@ class MeleeAttackBuilder(
|
||||
fun build(): SimpleMeleeAttackAction {
|
||||
return SimpleMeleeAttackAction(
|
||||
ActionRollInfo(
|
||||
DiceBag.critDice(attackRollString, attackModifiers),
|
||||
DiceBag.plainDice(dmgRollString, damageModifiers)
|
||||
Dice.critDice(attackRollString, attackModifiers),
|
||||
Dice.regular(dmgRollString, damageModifiers)
|
||||
),
|
||||
defense
|
||||
)
|
||||
|
||||
@ -2,7 +2,6 @@ package simulation
|
||||
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import simulation.dice.Dice
|
||||
import simulation.dice.DiceBag
|
||||
import simulation.dice.RollResult
|
||||
import java.util.*
|
||||
import kotlin.test.Test
|
||||
@ -13,7 +12,7 @@ class AttackDiceTest {
|
||||
fun testAttackDiceImplementation() {
|
||||
val r = Random()
|
||||
// Test no crit below threshold
|
||||
val dice = DiceBag.critDice("1d20")
|
||||
val dice = Dice.critDice("1d20")
|
||||
val result = dice.roll(r)
|
||||
if (result.result < 20) {
|
||||
Assertions.assertFalse(dice.isCrit(result))
|
||||
@ -21,7 +20,7 @@ class AttackDiceTest {
|
||||
Assertions.assertTrue(dice.isCrit(result))
|
||||
}
|
||||
// Test no crit below threshold
|
||||
val dice2 = DiceBag.critDice("1d20c10")
|
||||
val dice2 = Dice.critDice("1d20c10")
|
||||
val result2 = dice2.roll(r)
|
||||
if (result2.result < 10) {
|
||||
Assertions.assertFalse(dice2.isCrit(result2))
|
||||
@ -30,7 +29,7 @@ class AttackDiceTest {
|
||||
}
|
||||
|
||||
// Test crit threshold other than max
|
||||
val dice3 = DiceBag.critDice("2d10c8")
|
||||
val dice3 = Dice.critDice("2d10c8")
|
||||
val result3 = dice3.roll(r)
|
||||
if (result3.result >= 8) {
|
||||
Assertions.assertTrue(dice3.isCrit(result3))
|
||||
@ -44,9 +43,9 @@ class AttackDiceTest {
|
||||
val trueCritResult = RollResult(1, 20, 20)
|
||||
val fakeCritResult = RollResult(1, 20, 19)
|
||||
|
||||
val defaultRoll = DiceBag.critDice("1d20")
|
||||
val verboseDefaultCrit = DiceBag.critDice("1d20c20")
|
||||
val normalModifiedCrit = DiceBag.critDice("1d20c19")
|
||||
val defaultRoll = Dice.critDice("1d20")
|
||||
val verboseDefaultCrit = Dice.critDice("1d20c20")
|
||||
val normalModifiedCrit = Dice.critDice("1d20c19")
|
||||
|
||||
Assertions.assertFalse(defaultRoll.isCrit(fakeCritResult))
|
||||
Assertions.assertFalse(verboseDefaultCrit.isCrit(fakeCritResult))
|
||||
|
||||
@ -4,19 +4,18 @@ import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import simulation.dice.Dice
|
||||
import simulation.dice.DiceBag
|
||||
import simulation.dice.FlatModifier
|
||||
import simulation.dice.RollType
|
||||
import java.util.*
|
||||
|
||||
internal class DiceTests {
|
||||
internal class DiceRollerTests {
|
||||
private val random = Random(1)
|
||||
private val d20 = DiceBag.plainDice("1d20")
|
||||
private val d20 = Dice.regular("1d20")
|
||||
|
||||
|
||||
@Test
|
||||
fun roll_normal() {
|
||||
val dice = DiceBag.plainDice("2d6")
|
||||
val dice = Dice.regular("2d6")
|
||||
val result = dice.roll(random, RollType.Normal)
|
||||
val result2 = dice.roll(random)
|
||||
|
||||
@ -30,7 +29,7 @@ internal class DiceTests {
|
||||
|
||||
@Test
|
||||
fun roll_advantage() {
|
||||
val dice = DiceBag.plainDice("2d6")
|
||||
val dice = Dice.regular("2d6")
|
||||
val result = dice.roll(random, RollType.Advantage)
|
||||
|
||||
assertEquals(2, result.min)
|
||||
@ -41,7 +40,7 @@ internal class DiceTests {
|
||||
|
||||
@Test
|
||||
fun roll_disadvantage() {
|
||||
val dice = DiceBag.plainDice("2d6")
|
||||
val dice = Dice.regular("2d6")
|
||||
val result = dice.roll(random, RollType.Disadvantage)
|
||||
|
||||
assertEquals(2, result.min)
|
||||
@ -53,7 +52,7 @@ internal class DiceTests {
|
||||
fun evaluate_modifiers() {
|
||||
val mod1 = FlatModifier(1)
|
||||
val mod2 = FlatModifier(2)
|
||||
val dice = DiceBag.plainDice("1d20", arrayListOf(mod1, mod2))
|
||||
val dice = Dice.regular("1d20", arrayListOf(mod1, mod2))
|
||||
|
||||
val bonus = dice.evaluateModifiers(random)
|
||||
|
||||
@ -67,7 +66,7 @@ internal class DiceTests {
|
||||
|
||||
RollType.entries.parallelStream()
|
||||
.forEach {
|
||||
val dice = DiceBag.plainDice(rollString)
|
||||
val dice = Dice.regular(rollString)
|
||||
val r = Random(1)
|
||||
val rollType = it
|
||||
repeat(iterations) {
|
||||
@ -99,7 +98,7 @@ internal class DiceTests {
|
||||
|
||||
RollType.entries.parallelStream()
|
||||
.forEach {
|
||||
val dice = DiceBag.plainDice(rollString)
|
||||
val dice = Dice.regular(rollString)
|
||||
val r = Random(1)
|
||||
for (i in 0..<iterations) {
|
||||
val res = dice.roll(r, it)
|
||||
@ -129,7 +128,7 @@ internal class DiceTests {
|
||||
val expectedAverageLowerBound = ((n + (n * max)) / 2) * (1 - tolerance)
|
||||
val expectedAverageUpperBound = ((n + (n * max)) / 2) * (1 + tolerance)
|
||||
|
||||
val dice = DiceBag.plainDice(rollString)
|
||||
val dice = Dice.regular(rollString)
|
||||
var total = 0L
|
||||
repeat(iterations) {
|
||||
total += dice.roll(random).result.toLong()
|
||||
@ -153,7 +152,7 @@ internal class DiceTests {
|
||||
|
||||
val expectedAverageUpperBound = ((n + (n * max)) / 2) * tolerance
|
||||
|
||||
val dice = DiceBag.plainDice(rollString)
|
||||
val dice = Dice.regular(rollString)
|
||||
|
||||
var total = 0L
|
||||
repeat(iterations) {
|
||||
@ -177,7 +176,7 @@ internal class DiceTests {
|
||||
|
||||
val expectedAverageLowerBound = ((n + (n * max)) / 2) * tolerance
|
||||
|
||||
val dice = DiceBag.plainDice(rollString)
|
||||
val dice = Dice.regular(rollString)
|
||||
|
||||
|
||||
var total = 0L
|
||||
@ -196,7 +195,7 @@ internal class DiceTests {
|
||||
@Test
|
||||
fun verifyDistribution() {
|
||||
val size = 20
|
||||
val dice = DiceBag.plainDice("1d20")
|
||||
val dice = Dice.regular("1d20")
|
||||
val iterations = 10_000_000
|
||||
val tolerance = 0.05 //5% wiggle on distribution
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package simulation
|
||||
|
||||
import simulation.dice.DiceBag
|
||||
import simulation.dice.Dice
|
||||
import simulation.dice.RollType
|
||||
import simulation.fifthEd.ActionRollInfo
|
||||
import simulation.fifthEd.AttackResult
|
||||
@ -17,7 +17,7 @@ class MeleeAttackTest {
|
||||
val itt = 1_000_000
|
||||
val simulator = Simulator.getInstance<AttackResult>(Runtime.getRuntime().availableProcessors())
|
||||
|
||||
val attackAction = ActionRollInfo(DiceBag.critDice("1d20c19"), DiceBag.plainDice("1d8"))
|
||||
val attackAction = ActionRollInfo(Dice.critDice("1d20c19"), Dice.regular("1d8"))
|
||||
val critAttack = SimpleMeleeAttackAction(
|
||||
attackAction,
|
||||
10
|
||||
|
||||
Loading…
Reference in New Issue
Block a user