Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package hs
- import java.util.HashMap
- import java.util.Random
- import java.util.TreeMap
- import java.util.concurrent.Executors
- import java.util.concurrent.TimeUnit
- class PlayerState(initRank: Int = 5, initStars: Int = 1) {
- init {
- if (initRank < 1 || initRank > 20)
- throw IllegalArgumentException("The initial rank must be between 1 and 20!")
- if (initStars < 0)
- throw IllegalArgumentException("The initial stars must not be negative!")
- if (initStars > 5)
- throw IllegalArgumentException("The initial stars must not be over 5!")
- }
- private var currentRank = initRank
- private var currentStars = initStars
- private var winStreak = 0
- private var amountOfGames = 0
- val rank: Int
- get() = currentRank
- val stars: Int
- get() = currentStars
- val gamesPlayed: Int
- get() = amountOfGames
- fun addWin() {
- amountOfGames++
- winStreak++
- if (currentRank > 5 && winStreak > 2) {
- currentStars += 2
- } else {
- currentStars++
- }
- rankCheckWin()
- }
- fun addLoss() {
- amountOfGames++
- winStreak = 0
- currentStars--
- rankCheckLoss()
- //rankCheckLossNew()
- }
- private fun rankCheckWin() {
- if (currentRank <= 10 && currentStars > 5) {
- currentRank--
- currentStars -= 5
- } else if (currentRank > 10 && currentRank <= 15 && currentStars > 4) {
- currentRank--
- currentStars -= 4
- } else if (currentRank > 15 && currentRank <= 20 && currentStars > 3) {
- currentRank--
- currentStars -= 3
- }
- }
- private fun rankCheckLoss() {
- if (currentStars < 0) {
- currentRank++
- when {
- currentRank <= 10 -> currentStars = 4
- currentRank <= 15 -> currentStars = 3
- currentRank <= 20 -> currentStars = 2
- else -> {
- currentRank = 20
- currentStars = 0
- }
- }
- }
- }
- private fun rankCheckLossNew() {
- if (currentStars < 0) {
- if (currentRank == 5 || currentRank == 10 || currentRank == 15) {
- currentStars = 0
- return
- }
- currentRank++
- when {
- currentRank <= 10 -> currentStars = 4
- currentRank <= 15 -> currentStars = 3
- currentRank <= 20 -> currentStars = 2
- else -> {
- currentRank = 20
- currentStars = 0
- }
- }
- }
- }
- }
- object GameCalc {
- fun simulateLegendClimbs(n: Int, winRate: Int): IntArray {
- val results = IntArray(n)
- val rng = Random()
- for (i in 0..(n - 1)) {
- val player = PlayerState()
- while (player.rank > 0) {
- if (rng.nextInt(100) < winRate) {
- player.addWin()
- } else {
- player.addLoss()
- }
- }
- results[i] = player.gamesPlayed
- }
- return results
- }
- fun simulateLegendClimbsThreaded(n: Int, winRate: Int): IntArray {
- val cpus = Runtime.getRuntime().availableProcessors()
- val executor = Executors.newFixedThreadPool(cpus)
- val partialResults = Array(cpus, { IntArray(1) })
- val partialResultAmount = n / cpus
- for (x in 1..cpus) {
- executor.execute {
- partialResults[x - 1] = simulateLegendClimbs(partialResultAmount, winRate)
- }
- }
- executor.shutdown()
- executor.awaitTermination(java.lang.Long.MAX_VALUE, TimeUnit.SECONDS)
- val results = IntArray(partialResultAmount * cpus)
- var index = 0
- for (array in partialResults) {
- for (i in 0..(array.size - 1)) {
- results[index++] = array[i]
- }
- }
- return results
- }
- fun calculateLegendClimbsMap(n: Int, winRate: Int, initRank: Int, rankGoal: Int): Map<Int, Int> {
- val results = HashMap<Int, Int>(2000)
- val rng = Random()
- for (i in 0..(n - 1)) {
- val player = PlayerState(initRank)
- while (player.rank > rankGoal) {
- if (rng.nextInt(100) < winRate) {
- player.addWin()
- } else {
- player.addLoss()
- }
- }
- results[player.gamesPlayed] = results.getOrDefault(player.gamesPlayed, 0) + 1
- }
- return results
- }
- fun calculateAverageTimeToRank(n: Int, winRate: Int, initRank: Int, rankGoal: Int): Pair<Double, Int> {
- val cpus = Runtime.getRuntime().availableProcessors()
- val executor = Executors.newFixedThreadPool(cpus)
- val partialResults = Array<Map<Int, Int>>(cpus, { emptyMap() })
- val partialResultAmount = n / cpus
- for (x in 1..cpus) {
- executor.execute {
- partialResults[x - 1] = calculateLegendClimbsMap(partialResultAmount, winRate, initRank, rankGoal)
- }
- }
- executor.shutdown()
- executor.awaitTermination(java.lang.Long.MAX_VALUE, TimeUnit.SECONDS)
- val results = TreeMap<Int, Int>()
- for (map in partialResults)
- map.forEach { results[it.key] = results.getOrElse(it.key, { 0 }) + it.value }
- val mean = results.map { it.key.toLong() * it.value }.sum().toDouble() / n
- val median: Int = {
- var x = 0
- var i = 0
- val index = results.iterator()
- while (i < n / 2 && index.hasNext()) {
- val tmp = index.next()
- x = tmp.key
- i += tmp.value
- }
- x
- }()
- return Pair(mean, median)
- }
- }
- fun main(args: Array<String>) {
- val rolls = 10000000
- println("Number of rolls: $rolls\n\n")
- for (rate in 50..60) {
- val winRate = rate
- val (mean, median) = GameCalc.calculateAverageTimeToRank(rolls, winRate, 20, 5)
- println("Win rate: $winRate%")
- println("Mean amount of games to reach legend: $mean")
- println("Median amount of games to reach legend: $median")
- println()
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement