stochastic modeling for full games
This commit is contained in:
parent
2256b6d9bf
commit
f05ab2cfa2
@ -1,4 +1,4 @@
|
||||
import sequtils
|
||||
import random, sugar
|
||||
import fixedseq, game
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ iterator allPermutations*(x: FixedSeq): FixedSeq =
|
||||
|
||||
iterator allDigits*(lo, hi, size: Natural): auto =
|
||||
if size > 0: # otherwise we get an infinite loop
|
||||
var digits: FixedSeq[5, int8, int8]
|
||||
var digits: FixedSeq[5, int, int8]
|
||||
digits.initFixedSeq
|
||||
for i in 0 ..< size:
|
||||
digits.add(lo)
|
||||
@ -42,3 +42,10 @@ iterator possibleFutures*(dice: FixedSeq): auto =
|
||||
for i in 0 .. dice.high:
|
||||
f.add((perm[i], digits[i]))
|
||||
yield f
|
||||
|
||||
|
||||
proc randomFuture*(dice: FixedSeq, r: var Rand): FixedSeq[5, Die, int8] =
|
||||
result.initFixedSeq
|
||||
let order = dice.dup(shuffle(r))
|
||||
for i, color in order:
|
||||
result.add((color, r.rand(1..3)))
|
||||
|
10
fixedseq.nim
10
fixedseq.nim
@ -1,4 +1,4 @@
|
||||
import algorithm
|
||||
import algorithm, random
|
||||
|
||||
|
||||
type
|
||||
@ -16,6 +16,11 @@ proc initFixedSeq*(s: var FixedSeq) =
|
||||
s.last = -1
|
||||
|
||||
|
||||
proc `[]`*(s: FixedSeq, i: Natural): FixedSeq.Contents =
|
||||
if i > s.last:
|
||||
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
||||
s.data[i]
|
||||
|
||||
proc `[]`*(s: var FixedSeq, i: Natural): var FixedSeq.Contents =
|
||||
if i > s.last:
|
||||
raise newException(IndexDefect, "index " & $i & " is out of bounds.")
|
||||
@ -98,7 +103,8 @@ proc nextPermutation*(s: var FixedSeq): bool = s.data.nextPermutation
|
||||
|
||||
proc prevPermutation*(s: var FixedSeq): bool = s.data.prevPermutation
|
||||
|
||||
proc maxSize*(s: FixedSeq): FixedSeq.Pointer = s.data.len
|
||||
proc shuffle*(s: var FixedSeq, r: var Rand) =
|
||||
r.shuffle(s.data)
|
||||
|
||||
|
||||
proc moveSubstack*(src, dst: var FixedSeq; start: Natural) =
|
||||
|
21
game.nim
21
game.nim
@ -9,6 +9,18 @@ type
|
||||
ColorStack* = FixedSeq[5, Color, int8]
|
||||
|
||||
|
||||
proc initColorStack: ColorStack =
|
||||
result.initFixedSeq
|
||||
|
||||
|
||||
proc getAllColors: ColorStack =
|
||||
var i = 0
|
||||
for c in Color.low .. Color.high:
|
||||
result[i] = c
|
||||
|
||||
const allColors = getAllColors() # compile-time evaluation
|
||||
|
||||
|
||||
proc `$`*(s: ColorStack): string =
|
||||
result.add("St@[")
|
||||
for i, color in s:
|
||||
@ -38,9 +50,6 @@ type
|
||||
initialized: bool
|
||||
|
||||
|
||||
const allDice = @[cRed, cGreen, cBlue, cYellow, cPurple]
|
||||
|
||||
|
||||
proc `[]`*[T](b: var Board, idx: T): var Square =
|
||||
b.squares[idx]
|
||||
|
||||
@ -90,6 +99,12 @@ proc setState*(b: var Board;
|
||||
b.leader = some(leadCamel)
|
||||
|
||||
|
||||
proc diceRemaining*(b: Board): ColorStack =
|
||||
result.initFixedSeq
|
||||
for color, isRolled in b.diceRolled:
|
||||
if not isRolled: result.add(color)
|
||||
|
||||
|
||||
proc resetDice*(b: var Board) =
|
||||
var d: array[Color, bool]
|
||||
b.diceRolled = d
|
||||
|
28
main.nim
28
main.nim
@ -1,4 +1,4 @@
|
||||
import math, options, sequtils, sets, sugar
|
||||
import math, options, sequtils, random, sets
|
||||
import combinators, game, fixedseq
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@ proc projectOutcomes(b: Board, maxDepth = 1): ScoreSet =
|
||||
|
||||
for o in outcomeStack[^1]:
|
||||
var o = o # make it mutable
|
||||
if outcomeStack.len > 1:
|
||||
o.resetDice # o was describina an end-of-leg state, so dice were exhausted
|
||||
|
||||
let projection = o.projectLeg
|
||||
@ -52,11 +53,32 @@ proc projectOutcomes(b: Board, maxDepth = 1): ScoreSet =
|
||||
echo "\nDistinct end states: ", outcomeStack.mapIt(it.len).sum
|
||||
|
||||
|
||||
proc randomGame(b: Board, r: var Rand): Color =
|
||||
var projection = b
|
||||
while true:
|
||||
for roll in randomFuture(projection.diceRemaining, r):
|
||||
projection.advance(roll)
|
||||
if projection.gameOver:
|
||||
return projection.leader.get
|
||||
projection.resetDice
|
||||
|
||||
|
||||
proc randomGames(b: Board, count: SomeInteger): ScoreSet =
|
||||
randomize()
|
||||
var r = initRand(rand(int64))
|
||||
for i in 0 ..< count:
|
||||
let winner = b.randomGame(r)
|
||||
inc result[winner]
|
||||
if i mod 100_000 == 0:
|
||||
stdout.write("simulated: " & $i & "\r")
|
||||
echo ""
|
||||
|
||||
|
||||
var b: Board
|
||||
b.init
|
||||
b.display(1, 5)
|
||||
|
||||
b.setState({cGreen: 4, cYellow: 3, cPurple: 4, cBlue: 3, cRed: 4}, @[])
|
||||
b.setState({cGreen: 4, cYellow: 3, cPurple: 4, cBlue: 3, cRed: 5}, @[])
|
||||
b.display(1, 5)
|
||||
|
||||
# b.advance((cRed, 1))
|
||||
@ -70,7 +92,7 @@ b.display(1, 5)
|
||||
# echo s
|
||||
# echo s[2]
|
||||
|
||||
let r = b.projectOutcomes(2)
|
||||
let r = b.randomGames(10_000_000)
|
||||
let total = r.sum
|
||||
for i, c in r:
|
||||
echo Color(i), ": ", (100 * c / total).round(2), "% (", c, " / ", total, ")"
|
||||
|
Loading…
x
Reference in New Issue
Block a user