import algorithm, random, sugar import faststack, 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)))