picking apart a few models

This commit is contained in:
dtookey 2023-09-05 08:57:09 -04:00
parent d0f7c3bd11
commit 07f76b2e1d
2 changed files with 53 additions and 18 deletions

View File

@ -1,6 +1,7 @@
package entries package entries
import simulation.* import simulation.*
import simulation.dice.DiceBag
import simulation.dice.RollType import simulation.dice.RollType
import simulation.fifthEd.AttackResult import simulation.fifthEd.AttackResult
import simulation.fifthEd.AttackSimulatorModel import simulation.fifthEd.AttackSimulatorModel
@ -10,17 +11,39 @@ import simulation.fifthEd.SimpleMeleeAttackAction
fun main() { fun main() {
val rounds = 1_000_000 val rounds = 1_000_000
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
val computedRounds = doSimulation(rounds) // val computedRounds = doSimulation(rounds)
crunchBarbarian(21)
// crunchMonk()
val finish = System.currentTimeMillis() val finish = System.currentTimeMillis()
println("Simulation finished $computedRounds rounds in: ${finish - start}ms") // println("Simulation finished $computedRounds rounds in: ${finish - start}ms")
println("Simulation finished in: ${finish - start}ms")
} }
const val avgDamage = "Avg Dmg" const val avgDamage = "Avg Dmg"
fun doSimulation(rounds: Int): Long {
fun crunchMonk(ac: Int= 18) {
val attackRoll = MeleeAttackBuilder("1d20", "1d8", ac)
.withAtkBonus(11)
.withDmgBonus(7)
.build()
val attackBless = MeleeAttackBuilder("1d20", "1d8", ac)
.withAtkBonus(11)
.withAtkBonus(DiceBag.plainDice("1d4"))
.withDmgBonus(7)
.build()
val attacks = listOf(Pair("Normal Attack", attackRoll), Pair("Bless Attack", attackBless))
val defense = 18
generateCombatSuggestions(attacks, 1000000, defaultReport())
}
fun crunchBarbarian(defense: Int = 16){
val rounds = 1_000_000
val attackDice = "1d20" val attackDice = "1d20"
val weaponDice = "2d6" val weaponDice = "2d6"
@ -46,14 +69,9 @@ fun doSimulation(rounds: Int): Long {
.build() .build()
val attacks = listOf(Pair("Normal Attack", normalAttack), Pair("GWM Attack", gwmAttack)) val attacks = listOf(Pair("Normal Attack", normalAttack), Pair("GWM Attack", gwmAttack))
val reportFactory = ReportBuilder.getInstance()
.addRateMetric("Accuracy") { it.rollSucceeded }
.addRateMetric("Crit Rate") { it.rollSucceeded }
.addAverageMetric(avgDamage) { it.resultingDamage.toLong() }
generateCombatSuggestions(attacks, rounds, reportFactory)
return rounds.toLong() * attacks.size.toLong() generateCombatSuggestions(attacks, rounds, defaultReport())
} }
fun generateCombatSuggestions( fun generateCombatSuggestions(
@ -65,7 +83,7 @@ fun generateCombatSuggestions(
val results = attacks val results = attacks
.associateWith { attackInfo -> .associateWith { attackInfo ->
val label = "${attackInfo.first}" val label = attackInfo.first
val attack = attackInfo.second val attack = attackInfo.second
RollType.entries.associateWith { RollType.entries.associateWith {
@ -74,7 +92,11 @@ fun generateCombatSuggestions(
val report = reportFactory.build(label) val report = reportFactory.build(label)
report.computeResults(results) print("${attackInfo.first} $it\t")
val res = report.computeResults(results)
println(Report.formatReport(res.name, res.results))
res
}.toMap() }.toMap()
} }
@ -86,10 +108,10 @@ fun generateCombatSuggestions(
results.forEach { attackAction -> results.forEach { attackAction ->
val current = attackAction.value[rollType] val current = attackAction.value[rollType]
if(choice == null){ if (choice == null) {
choice = current choice = current
}else{ } else {
if(current?.results?.getDamage()!!.metricValue > choice!!.results.getDamage()!!.metricValue){ if (current?.results?.getDamage()!!.metricValue > choice!!.results.getDamage()!!.metricValue) {
choice = current choice = current
} }
} }
@ -100,6 +122,14 @@ fun generateCombatSuggestions(
} }
} }
fun defaultReport(): ReportBuilder{
return ReportBuilder.getInstance()
.addRateMetric("Accuracy") { it.rollSucceeded }
.addRateMetric("Crit Rate") { it.rollSucceeded }
.addStdDevMetric("Dmg std") { it.resultingDamage.toLong() }
.addAverageMetric(avgDamage) { it.resultingDamage.toLong() }
}
fun List<MetricResult>.getDamage(): MetricResult? { fun List<MetricResult>.getDamage(): MetricResult? {

View File

@ -10,7 +10,7 @@ interface Report {
val name: String val name: String
val metrics: List<Metric<Double>> val metrics: List<Metric<Double>>
companion object{ companion object {
fun formatReport(name: String, results: List<MetricResult>): String { fun formatReport(name: String, results: List<MetricResult>): String {
val builder = StringBuilder() val builder = StringBuilder()
results.forEach { results.forEach {
@ -23,7 +23,7 @@ interface Report {
} }
fun computeResults(results: List<AttackResult>): MetricReport{ fun computeResults(results: List<AttackResult>): MetricReport {
val m = ArrayList<MetricResult>(metrics.size) val m = ArrayList<MetricResult>(metrics.size)
metrics.forEach { metrics.forEach {
val value = it.mapToMetric(results) val value = it.mapToMetric(results)
@ -59,6 +59,11 @@ interface ReportBuilder {
metrics.add(RateMetric(metricName, fieldMapFn)) metrics.add(RateMetric(metricName, fieldMapFn))
return this return this
} }
fun addStdDevMetric(metricName: String, fieldMapFn: (AttackResult) -> Long): ReportBuilder {
metrics.add(StdDevMetric(metricName, fieldMapFn))
return this
}
} }
class ReportBuilderImpl : ReportBuilder { class ReportBuilderImpl : ReportBuilder {