I realized having to host this potentially indefinitely might not be the best idea, so I am going to shut down this gitea instance eventually.
You’ll have time, at least until the end of 2022, probably longer, but please just get all your stuff somewhere safe in case we ever disappear.
If any of your build scripts rely on my (kageru’s) projects hosted here, check my Github or IEW on Github for encoding projects. If you can’t find what you’re looking there, tell me to migrate it.

review feedback

master
kageru 2 years ago
parent 5237cad9a4
commit 10d70c6f84
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
  1. 29
      src/main/kotlin/rps/Game.kt
  2. 3
      src/test/kotlin/rps/GameTest.kt

@ -1,18 +1,15 @@
package rps
import kotlin.random.Random
const val TURNS = 100
val PLAYER_TWO_CHOICE = Move.ROCK
fun main() {
println("Outcome from Player 1’s perspective: ${playGame(TURNS)}")
}
/** Determine the [Outcome] of [first] vs [second] from the perspective of [first]. */
fun determineOutcome(first: Move, second: Move): Outcome = when {
first.strongAgainst() == second -> Outcome.WIN
first == second -> Outcome.DRAW
fun determineOutcome(first: Move, second: Move): Outcome = when(second) {
in first.strongAgainst() -> Outcome.WIN
first -> Outcome.DRAW
else -> Outcome.LOSS
}
@ -24,15 +21,13 @@ fun List<Outcome>.calculateGameSummary() = GameSummary(
losses = count { it == Outcome.LOSS },
)
fun playGame(turns: Int): GameSummary = generateSequence { randomMove() }
fun playGame(turns: Int): GameSummary = generateSequence { randomMove() to randomMove() }
.take(turns)
.map { determineOutcome(it, PLAYER_TWO_CHOICE) }
.map { (p1, p2) -> determineOutcome(p1, p2) }
.toList()
.calculateGameSummary()
fun randomMove(): Move = Move.values().let { allMoves ->
allMoves[Random.nextInt(allMoves.size)]
}
fun randomMove(): Move = Move.values().random()
/*
* Classes and named tuples below this point.
@ -43,13 +38,13 @@ fun randomMove(): Move = Move.values().let { allMoves ->
* A possible move in a game of rock-paper-scissors.
*
* [strongAgainst] is a function for lazy evaluation because otherwise we cant access SCISSORS before its been defined.
* If the game needs to be expanded (e.g. the somewhat common rock, paper, scissors, salamander, spock),
* this argument could be a List<Move> instead.
*/
enum class Move(val strongAgainst: () -> Move) {
ROCK({ SCISSORS }),
PAPER({ ROCK }),
SCISSORS({ PAPER })
enum class Move(val strongAgainst: () -> Set<Move>) {
ROCK({ setOf(SCISSORS, LIZARD) }),
PAPER({ setOf(ROCK, SPOCK) }),
SCISSORS({ setOf(PAPER, LIZARD) }),
LIZARD({ setOf(SPOCK, PAPER) }),
SPOCK({ setOf(SCISSORS, ROCK) }),
}
// purposely not calling this Result to avoid confusion with kotlin.Result and similar

@ -13,6 +13,9 @@ class GameTest {
Triple(ROCK, PAPER, LOSS),
Triple(PAPER, SCISSORS, LOSS),
Triple(ROCK, ROCK, DRAW),
Triple(ROCK, LIZARD, WIN),
Triple(LIZARD, SPOCK, WIN),
Triple(SPOCK, PAPER, LOSS),
)
for ((first, second, expected) in games) {
assertEquals(determineOutcome(first, second), expected)

Loading…
Cancel
Save