)
}
-suspend fun performTrials(numTrialsPerPairing: Int, instincts: Set<Instincts>, validBattleSizes: Set<BattleSize> = BattleSize.values().toSet(), validFactions: Set<Faction> = Faction.values().toSet()): Map<Instincts, Int> {
+data class InstinctGamePairing(
+ val host: Instincts,
+ val guest: Instincts
+)
+
+suspend fun performTrials(numTrialsPerPairing: Int, instincts: Set<Instincts>, validBattleSizes: Set<BattleSize> = BattleSize.values().toSet(), validFactions: Set<Faction> = Faction.values().toSet()): Map<InstinctGamePairing, Int> {
return coroutineScope {
instincts.associateWith { host ->
async {
val guestFaction = validFactions.random()
val gameState = generateOptimizationInitialState(hostFaction, guestFaction, BattleInfo(battleSize, BattleBackground.BLUE_BROWN))
- val winner = withTimeoutOrNull(150_000L) {
+ val winner = withTimeoutOrNull(30_000L * numTrialsPerPairing) {
performTestSession(gameState, host, guest)
}
else -> 0
}
}
- }.sumOf { it.await() }
+ }.map { guest to it.await() }
}
- }.sumOf { it.await() }
+ }.flatMap { it.await() }.toMap()
}
- }.mapValues { (_, it) -> it.await() }
+ }.mapValues { (_, it) -> it.await() }.flatten().mapKeys { (k, _) ->
+ InstinctGamePairing(k.first, k.second)
+ }
}
}
+
+data class InstinctVictoryPairing(
+ val winner: Instincts,
+ val loser: Instincts
+)
+
+fun Map<InstinctGamePairing, Int>.victoriesFor(instincts: Instincts) = filterKeys { (host, _) -> host == instincts }.values.sum() - filterKeys { (_, guest) -> guest == instincts }.values.sum()
+
+fun Map<InstinctGamePairing, Int>.toVictoryMap() = keys.associate { (host, _) -> host to victoriesFor(host) }
+
+fun Map<InstinctGamePairing, Int>.toVictoryPairingMap() = keys.associate { (host, guest) ->
+ InstinctVictoryPairing(host, guest) to ((get(InstinctGamePairing(host, guest)) ?: 0) - (get(InstinctGamePairing(guest, host)) ?: 0))
+}
else null
}
+fun <T, U, V> Map<T, Map<U, V>>.flatten(): Map<Pair<T, U>, V> =
+ toList().flatMap { (k, v) ->
+ v.map { (l, w) ->
+ (k to l) to w
+ }
+ }.toMap()
+
fun <T, U> Map<T, Set<U>>.transpose(): Map<U, Set<T>> =
flatMap { (k, v) -> v.map { it to k } }
.groupBy(Pair<U, T>::first, Pair<U, T>::second)
val allowedFactions = allowedFactionChoices[allowedFactionIndex]
- val instinctSuccessRate = runBlocking {
+ val instinctPairingSuccessRate = runBlocking {
performTrials(numTrials, instinctVectors, allowedBattleSizes, allowedFactions)
}
+ val instinctVictories = instinctPairingSuccessRate.toVictoryPairingMap()
+
+ val instinctSuccessRate = instinctPairingSuccessRate.toVictoryMap()
+
val indexedInstincts = instinctSuccessRate
.toList()
.sortedBy { (_, v) -> v }
p { +"Battle Sizes Allowed: ${allowedBattleSizes.singleOrNull()?.displayName ?: "All"}" }
p { +"Factions Allowed: ${allowedFactions.singleOrNull()?.polityName ?: "All"}" }
h2 { +"Instincts Vectors and Battle Results" }
+ val cellStyle = "border: 1px solid rgba(0, 0, 0, 0.6)"
table {
- val cellStyle = "border: 1px solid rgba(0, 0, 0, 0.6)"
thead {
tr {
th(scope = ThScope.row) {
}
th(scope = ThScope.col) {
style = cellStyle
- +"Battles Won as Host"
+ +"Battles Won"
}
- allInstincts.forEach {
+ for (it in allInstincts)
th(scope = ThScope.col) {
style = cellStyle
+it.key
}
- }
}
}
tbody {
- indexedInstincts.forEach { (i, pair) ->
+ for ((i, pair) in indexedInstincts) {
val (instincts, successRate) = pair
tr {
th(scope = ThScope.row) {
style = cellStyle
+"$successRate"
}
- allInstincts.forEach { key ->
+ for (key in allInstincts)
td {
style = cellStyle
+"${instincts[key]}"
}
- }
}
}
}
}
+ h2 { +"Instincts Pairing Battle Results" }
+ table {
+ tr {
+ th {
+ style = cellStyle
+ +"Winner \\ Loser"
+ }
+ for ((i, _) in indexedInstincts)
+ th(scope = ThScope.col) {
+ style = cellStyle
+ +"Instincts $i"
+ }
+ }
+ for ((i, v) in indexedInstincts)
+ tr {
+ th(scope = ThScope.row) {
+ style = cellStyle
+ +"Instincts $i"
+ }
+ for ((_, w) in indexedInstincts)
+ td {
+ val pairing = InstinctVictoryPairing(v.first, w.first)
+ val victories = instinctVictories[pairing] ?: 0
+
+ style = cellStyle
+ +"$victories"
+ }
+ }
+ }
}
}