mirror of
https://github.com/yairm210/Unciv.git
synced 2025-09-24 03:53:12 -04:00
Simulation: More Robust Stats (#12675)
* More robust Simulation Stats * Some code cleanup * Enum
This commit is contained in:
parent
c7fb6fb525
commit
b948770c51
@ -29,7 +29,7 @@ class Simulation(
|
||||
private var startTime: Long = 0
|
||||
var steps = ArrayList<SimulationStep>()
|
||||
var numWins = mutableMapOf<String, MutableInt>()
|
||||
var sumStat = mutableMapOf<String, MutableMap<Int, MutableInt>>()
|
||||
private var summaryStats = HashMap<String, HashMap<Int, HashMap<Stat, MutableInt>>>() // [civ][turn][stat]=value
|
||||
private var winRateByVictory = HashMap<String, MutableMap<String, MutableInt>>()
|
||||
private var winTurnByVictory = HashMap<String, MutableMap<String, MutableInt>>()
|
||||
private var avgSpeed = 0f
|
||||
@ -37,13 +37,22 @@ class Simulation(
|
||||
private var totalTurns = 0
|
||||
private var totalDuration: Duration = Duration.ZERO
|
||||
private var stepCounter: Int = 0
|
||||
enum class Stat {
|
||||
SUM,
|
||||
NUM
|
||||
}
|
||||
|
||||
|
||||
init{
|
||||
for (civ in civilizations) {
|
||||
this.numWins[civ] = MutableInt(0)
|
||||
for (turn in statTurns)
|
||||
this.sumStat.getOrPut(civ) { mutableMapOf() }[turn] = MutableInt(0)
|
||||
for (turn in statTurns) {
|
||||
this.summaryStats.getOrPut(civ) { hashMapOf() }.getOrPut(turn){hashMapOf()}[Stat.SUM] = MutableInt(0)
|
||||
this.summaryStats.getOrPut(civ) { hashMapOf() }.getOrPut(turn){hashMapOf()}[Stat.NUM] = MutableInt(0)
|
||||
}
|
||||
val turn = -1 // end of game
|
||||
this.summaryStats.getOrPut(civ) { hashMapOf() }.getOrPut(turn){hashMapOf()}[Stat.SUM] = MutableInt(0)
|
||||
this.summaryStats.getOrPut(civ) { hashMapOf() }.getOrPut(turn){hashMapOf()}[Stat.NUM] = MutableInt(0)
|
||||
winRateByVictory[civ] = mutableMapOf()
|
||||
for (victory in UncivGame.Current.gameInfo!!.ruleset.victories.keys)
|
||||
winRateByVictory[civ]!![victory] = MutableInt(0)
|
||||
@ -63,26 +72,28 @@ class Simulation(
|
||||
for (threadId in 1..threadsNumber) {
|
||||
jobs.add(launch(CoroutineName("simulation-${threadId}")) {
|
||||
repeat(simulationsPerThread) {
|
||||
val step = SimulationStep(newGameInfo, statTurns)
|
||||
val gameInfo = GameStarter.startNewGame(GameSetupInfo(newGameInfo))
|
||||
gameInfo.simulateUntilWin = true
|
||||
for (turn in statTurns) {
|
||||
gameInfo.simulateMaxTurns = turn
|
||||
gameInfo.nextTurn()
|
||||
val step = SimulationStep(gameInfo)
|
||||
step.update(gameInfo)
|
||||
if (step.victoryType != null)
|
||||
break
|
||||
saveStat(gameInfo)
|
||||
step.saveTurnStats(gameInfo)
|
||||
}
|
||||
// check if Victory
|
||||
var step = SimulationStep(gameInfo)
|
||||
step.update(gameInfo)
|
||||
if (step.victoryType == null) {
|
||||
gameInfo.simulateMaxTurns = maxTurns
|
||||
gameInfo.nextTurn()
|
||||
}
|
||||
|
||||
step = SimulationStep(gameInfo) // final game state
|
||||
step.update(gameInfo) // final game state
|
||||
|
||||
if (step.victoryType != null) {
|
||||
step.saveTurnStats(gameInfo)
|
||||
step.winner = step.currentPlayer
|
||||
println("${step.winner} won ${step.victoryType} victory on turn ${step.turns}")
|
||||
}
|
||||
@ -109,16 +120,6 @@ class Simulation(
|
||||
println("Simulation step ($stepCounter/$maxSimulations)")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun saveStat(gameInfo: GameInfo) {
|
||||
val turn = gameInfo.turns
|
||||
for (civ in gameInfo.civilizations.filter { it.civName != Constants.spectator }) {
|
||||
val popsum = civ.cities.sumOf { it.population.population }
|
||||
//println("$civ $popsum")
|
||||
sumStat[civ.civName]!![turn]!!.add(popsum)
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun print(){
|
||||
getStats()
|
||||
@ -130,12 +131,27 @@ class Simulation(
|
||||
numWins.values.forEach { it.value = 0 }
|
||||
winRateByVictory.flatMap { it.value.values }.forEach { it.value = 0 }
|
||||
winTurnByVictory.flatMap { it.value.values }.forEach { it.value = 0 }
|
||||
summaryStats.flatMap { it.value.values }.forEach {
|
||||
it.values.forEach { it.value = 0 }
|
||||
}
|
||||
steps.forEach {
|
||||
if (it.winner != null) {
|
||||
numWins[it.winner!!]!!.inc()
|
||||
winRateByVictory[it.winner!!]!![it.victoryType]!!.inc()
|
||||
winTurnByVictory[it.winner!!]!![it.victoryType]!!.add(it.turns)
|
||||
}
|
||||
for (civ in civilizations) {
|
||||
for (turn in statTurns) {
|
||||
if (it.turnStats[civ]!![turn]!!.value != -1) {
|
||||
summaryStats[civ]!![turn]!![Stat.SUM]!!.add(it.turnStats[civ]!![turn]!!.value)
|
||||
summaryStats[civ]!![turn]!![Stat.NUM]!!.inc()
|
||||
//println("civ ${civ} @ ${turn} value ${it.turnStats[civ]!![turn]!!.value} avg ${summaryStats[civ]!![turn]!!["avg"]!!.value} numAvg ${summaryStats[civ]!![turn]!!["numAvg"]!!.value}")
|
||||
}
|
||||
}
|
||||
val turn = -1 // end of game
|
||||
summaryStats[civ]!![turn]!![Stat.SUM]!!.add(it.turnStats[civ]!![turn]!!.value)
|
||||
summaryStats[civ]!![turn]!![Stat.NUM]!!.inc()
|
||||
}
|
||||
}
|
||||
totalTurns = steps.sumOf { it.turns }
|
||||
totalDuration = (System.currentTimeMillis() - startTime).milliseconds
|
||||
@ -176,8 +192,13 @@ class Simulation(
|
||||
outString += "$victory: $winsTurns "
|
||||
}
|
||||
outString += "avg turns\n"
|
||||
for (turn in statTurns)
|
||||
outString += "avgStat (@$turn): ${sumStat[civ]!![turn]!!.value.toFloat()/numSteps}\n"
|
||||
for (turn in statTurns) {
|
||||
val turnStats = summaryStats[civ]!![turn]!!
|
||||
outString += "@$turn: popsum avg=${turnStats[Stat.SUM]!!.value.toFloat() / turnStats[Stat.NUM]!!.value.toFloat()} cnt=${turnStats[Stat.NUM]!!.value}\n"
|
||||
}
|
||||
val turn = -1 // end of match
|
||||
val turnStats = summaryStats[civ]!![turn]!!
|
||||
outString += "@END: popsum avg=${turnStats[Stat.SUM]!!.value.toFloat()/turnStats[Stat.NUM]!!.value.toFloat()} cnt=${turnStats[Stat.NUM]!!.value}\n"
|
||||
}
|
||||
outString += "\nAverage speed: %.1f turns/s \n".format(avgSpeed)
|
||||
outString += "Average game duration: $avgDuration\n"
|
||||
|
@ -1,12 +1,40 @@
|
||||
package com.unciv.logic.simulation
|
||||
|
||||
import com.unciv.Constants
|
||||
import com.unciv.logic.GameInfo
|
||||
|
||||
class SimulationStep (gameInfo: GameInfo) {
|
||||
class SimulationStep (gameInfo: GameInfo, statTurns: List<Int> = listOf()) {
|
||||
val civilizations = gameInfo.civilizations.filter { it.civName != Constants.spectator }.map { it.civName }
|
||||
var turns = gameInfo.turns
|
||||
var victoryType = gameInfo.getCurrentPlayerCivilization().victoryManager.getVictoryTypeAchieved()
|
||||
var winner: String? = null
|
||||
val currentPlayer = gameInfo.currentPlayer
|
||||
var currentPlayer = gameInfo.currentPlayer
|
||||
val turnStats = mutableMapOf<String, MutableMap<Int, MutableInt>>() // [civ][turn][stat]
|
||||
|
||||
init {
|
||||
for (civ in civilizations) {
|
||||
for (turn in statTurns)
|
||||
this.turnStats.getOrPut(civ) { mutableMapOf() }[turn] = MutableInt(-1)
|
||||
this.turnStats.getOrPut(civ) { mutableMapOf() }[-1] = MutableInt(-1) // end of game
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun saveTurnStats(gameInfo: GameInfo) {
|
||||
victoryType = gameInfo.getCurrentPlayerCivilization().victoryManager.getVictoryTypeAchieved()
|
||||
val turn = if (victoryType != null) -1 else gameInfo.turns
|
||||
for (civ in gameInfo.civilizations.filter { it.civName != Constants.spectator }) {
|
||||
val popsum = civ.cities.sumOf { it.population.population }
|
||||
//println("$civ $popsum")
|
||||
turnStats[civ.civName]!![turn]!!.set(popsum)
|
||||
}
|
||||
}
|
||||
|
||||
fun update(gameInfo: GameInfo) {
|
||||
turns = gameInfo.turns
|
||||
victoryType = gameInfo.getCurrentPlayerCivilization().victoryManager.getVictoryTypeAchieved()
|
||||
currentPlayer = gameInfo.currentPlayer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user