97 lines
2.2 KiB
Nim
97 lines
2.2 KiB
Nim
import algorithm, random, sugar
|
|
import fixedseq, game
|
|
|
|
|
|
proc nextPermutation(x: var FixedSeq): bool =
|
|
# copied shamelessly from std/algorithm.nim
|
|
if x.len < 2:
|
|
return false
|
|
|
|
var i = x.high
|
|
while i > 0 and x[i - 1] >= x[i]:
|
|
dec i
|
|
|
|
if i == 0:
|
|
return false
|
|
|
|
var j = x.high
|
|
while j >= i and x[j] <= x[i - 1]:
|
|
dec j
|
|
|
|
swap x[j], x[i - 1]
|
|
x.reverse(i, x.high)
|
|
|
|
result = true
|
|
|
|
|
|
proc prevPermutation(x: var FixedSeq): bool =
|
|
# copied shamelessly from std/algorithm.nim
|
|
if x.len < 2:
|
|
return false
|
|
|
|
var i = x.high
|
|
while i > 0 and x[i - 1] <= x[i]:
|
|
dec i
|
|
|
|
if i == 0:
|
|
return false
|
|
|
|
x.reverse(i, x.high)
|
|
|
|
var j = x.high
|
|
while j >= i and x[j - 1] < x[i - 1]:
|
|
dec j
|
|
|
|
swap x[i - 1], x[j]
|
|
|
|
result = true
|
|
|
|
|
|
iterator allPermutations*(x: FixedSeq): FixedSeq =
|
|
# returns all permutations of a given seq. Order is wonky but we don't care.
|
|
var workingCopy = x
|
|
yield workingCopy
|
|
while workingCopy.nextPermutation: # this mutates workingCopy
|
|
yield workingCopy
|
|
workingCopy = x
|
|
while workingCopy.prevPermutation:
|
|
yield workingCopy
|
|
|
|
|
|
iterator allDigits*(lo, hi, size: Natural): auto =
|
|
if size > 0: # otherwise we get an infinite loop
|
|
var digits: FixedSeq[5, int, int8]
|
|
digits.initFixedSeq
|
|
for i in 0 ..< size:
|
|
digits.add(lo)
|
|
|
|
var complete = false
|
|
while not complete:
|
|
yield digits
|
|
for i in countdown(digits.high, 0):
|
|
if digits[i] < hi:
|
|
inc digits[i]
|
|
break
|
|
elif i == 0: # since this is the last digit to be incremented, we must be done
|
|
complete = true
|
|
else:
|
|
digits[i] = lo
|
|
|
|
|
|
iterator possibleFutures*(dice: FixedSeq): auto =
|
|
# iterate over all possible sequences of die rolls. Each outcome
|
|
# is returned as a 5-sequence of (color, number) tuples.
|
|
for perm in dice.allPermutations:
|
|
for digits in allDigits(1, 3, dice.len):
|
|
var f = initFixedSeq(5, Die, int8)
|
|
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)))
|