diff --git a/combinators.nim b/combinators.nim index 57d9233..e86fc65 100644 --- a/combinators.nim +++ b/combinators.nim @@ -60,8 +60,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, int, int8] - digits.initFixedSeq + var digits: FixedSeq[5, int] for i in 0 ..< size: digits.add(lo) @@ -78,12 +77,12 @@ iterator allDigits*(lo, hi, size: Natural): auto = digits[i] = lo -iterator possibleFutures*(dice: FixedSeq): auto = +iterator possibleFutures*(dice: ColorStack): 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])) + var f: FixedSeq[5, Die] + for i in 0'u8 .. dice.high: + f.add((color: perm[i], value: digits[i])) yield f diff --git a/cup.nim b/cup.nim index 3c9c12e..db70baf 100644 --- a/cup.nim +++ b/cup.nim @@ -4,7 +4,6 @@ import game, simulation, ui when isMainModule: let config = parseArgs() var b: Board - b.init b.setState(config.state) let legScores = b.getLegScores diff --git a/fixedseq.nim b/fixedseq.nim index fa5ed1b..e994cf8 100644 --- a/fixedseq.nim +++ b/fixedseq.nim @@ -2,18 +2,9 @@ import random type - FixedSeq*[Idx: static int; Contents; Pointer: SomeSignedInt] = object - data: array[Idx, Contents] - last: Pointer - - -proc initFixedSeq*(size: static Natural; cType: typedesc; pType: typedesc[SomeSignedInt]): auto = - var s: FixedSeq[size, cType, pType] - s.last = -1 - result = s - -proc initFixedSeq*(s: var FixedSeq) = - s.last = -1 + FixedSeq*[Size: static range[0..255], Content] = object + data: array[Size, Content] + len*: uint8 proc `$`*(s: FixedSeq): string = @@ -25,55 +16,51 @@ proc `$`*(s: FixedSeq): string = result.add("]") -proc `[]`*(s: FixedSeq, i: Natural): FixedSeq.Contents = +proc `[]`*(s: FixedSeq, idx: Natural): FixedSeq.Content = when not defined(danger): - if i > s.last: - raise newException(IndexDefect, "index " & $i & " is out of bounds.") - s.data[i] + if idx.uint8 >= s.len: + raise newException(IndexDefect, "index " & $idx & " is out of bounds.") + s.data[idx] -proc `[]`*(s: var FixedSeq, i: Natural): var FixedSeq.Contents = +proc `[]`*(s: var FixedSeq, idx: Natural): var FixedSeq.Content = when not defined(danger): - if i > s.last: - raise newException(IndexDefect, "index " & $i & " is out of bounds.") - s.data[i] + if idx.uint8 >= s.len: + raise newException(IndexDefect, "index " & $idx & " is out of bounds.") + s.data[idx] -proc `[]`*(s: FixedSeq, i: BackwardsIndex): auto = +proc `[]`*(s: FixedSeq, idx: BackwardsIndex): auto = when not defined(danger): - if s.last == -1: + if s.len == 0: raise newException(IndexDefect, "index out of bounds, the container is empty.") # matching stdlib again - s.data[s.last - typeof(s.last)(i) + 1] + s.data[s.len - idx.uint8] -proc `[]=`*(s: var FixedSeq, i: Natural, v: FixedSeq.Contents) = +proc `[]=`*(s: var FixedSeq, idx: Natural, v: FixedSeq.Content) = when not defined(danger): - if i > s.last: - raise newException(IndexDefect, "index " & $i & " is out of bounds.") - s.data[i] = v + if idx.uint8 >= s.len: + raise newException(IndexDefect, "index " & $idx & " is out of bounds.") + s.data[idx] = v proc high*(s: FixedSeq): auto = - result = s.last + result = s.len - 1 proc low*(s: FixedSeq): auto = - result = case s.last - of -1: 0 # a bit weird but it's how the stdlib seq works - else: s.last - - -proc len*(s: FixedSeq): auto = - result = s.last + 1 + result = case s.len + of 0: 0 # a bit weird but it's how the stdlib seq works + else: s.len - 1 iterator items*(s: FixedSeq): auto = - for i in 0 .. s.last: + for i in 0'u8 ..< s.len: yield s.data[i] iterator asInt*(s: FixedSeq): int8 = - for i in 0 .. s.last: + for i in 0'u8 ..< s.len: yield int8(s.data[i]) # now we do have to convert @@ -84,34 +71,32 @@ iterator pairs*(s: FixedSeq): auto = inc count -proc add*(s: var FixedSeq, v: FixedSeq.Contents) = - let i = s.last + 1 - s.data[i] = v # will raise exception if out of bounds - s.last = i +proc add*(s: var FixedSeq, v: FixedSeq.Content) = + s.data[s.len] = v # will raise exception if out of bounds + inc s.len -proc insert*(s: var FixedSeq, v: FixedSeq.Contents, idx: Natural = 0) = - for i in countdown(s.last, typeof(s.last)(idx)): +proc insert*(s: var FixedSeq, v: FixedSeq.Content, idx: Natural = 0) = + for i in countdown(s.len - 1, idx.uint8): swap(s.data[i], s.data[i + 1]) # will also raise exception if out of bounds s.data[idx] = v - inc s.last + inc s.len proc delete*(s: var FixedSeq, idx: Natural) = when not defined(danger): - if idx > s.last: + if idx.uint8 >= s.len: raise newException(IndexDefect, "index " & $idx & " is out of bounds.") - s.data[idx] = -1 # do we even need this? - dec s.last - for i in typeof(s.last)(idx) .. s.last: + dec s.len + for i in idx.uint8 ..< s.len: swap(s.data[i], s.data[i + 1]) proc clear*(s: var FixedSeq) = - s.last = -1 + s.len = 0 -proc find*(s: FixedSeq, needle: FixedSeq.Contents): FixedSeq.Pointer = +proc find*(s: FixedSeq, needle: FixedSeq.Content): int = for i, v in s.data: if v == needle: return i @@ -129,30 +114,36 @@ proc reverse*(s: var FixedSeq; first, last: Natural) = proc shuffle*(s: var FixedSeq, r: var Rand) = + when not defined(danger): + if s.len < s.data.len.uint8: + raise newException(IndexDefect, "Cannot shuffle a partially-full FixedSeq") r.shuffle(s.data) proc shuffle*(s: var FixedSeq) = + when not defined(danger): + if s.len < s.data.len.uint8: + raise newException(IndexDefect, "Cannot shuffle a partially-full FixedSeq") shuffle(s.data) proc moveSubstack*(src, dst: var FixedSeq; start: Natural) = - var count: typeof(src.last) = 0 # have to track this separately apparently - for idx in start .. src.last: - swap(src.data[idx], dst.data[dst.last + 1 + count]) + var count = 0'u8 # have to track this separately apparently + for idx in start ..< src.len: + swap(src.data[idx], dst.data[dst.len + count]) inc count - dst.last += count - src.last -= count + dst.len += count + src.len -= count proc moveSubstackPre*(src, dst: var FixedSeq; start: Natural) = - let ssLen = typeof(src.last)(src.last - start + 1) # length of substack - for i in countdown(dst.last, 0): + let ssLen = src.len - start.uint8 # length of substack + for i in countdown(dst.len - 1, 0): swap(dst.data[i], dst.data[i + ssLen]) var count = 0 - for i in start .. src.last: + for i in start ..< src.len: swap(src.data[i], dst.data[count]) inc count - dst.last += ssLen - src.last -= ssLen + dst.len += ssLen + src.len -= ssLen diff --git a/game.nim b/game.nim index f879ce7..0ad9659 100644 --- a/game.nim +++ b/game.nim @@ -6,20 +6,9 @@ type Color* = enum cRed, cGreen, cBlue, cYellow, cPurple - ColorStack* = FixedSeq[5, Color, int8] + ColorStack* = FixedSeq[5, Color] - -proc initColorStack*: ColorStack = - result.initFixedSeq - - -proc getAllColors: ColorStack = - var i = 0 - for c in Color.low .. Color.high: - result[i] = c - -const - allColors* = getAllColors() +const colorNames: array[Color, string] = ["Red", "Green", "Blue", "Yellow", "Purple"] colorAbbrevs: array[Color, char] = ['R', 'G', 'B', 'Y', 'P'] @@ -37,7 +26,7 @@ proc `$`*(s: ColorStack): string = result.add("St@[") for i, color in s: result.add($color) - if i < s.high: + if i.uint8 < s.high: result.add(", ") result.add("]") @@ -55,8 +44,8 @@ type GameState* = object dice*: array[Color, bool] - camels*: FixedSeq[5, tuple[c: Color, p: range[1..16]], int8] - tiles*: FixedSeq[8, tuple[t: Tile, p: range[1..16]], int8] # max 8 players, so max 8 tiles + camels*: FixedSeq[5, tuple[c: Color, p: range[1..16]]] + tiles*: FixedSeq[8, tuple[t: Tile, p: range[1..16]]] # max 8 players, so max 8 tiles Board* = object squares*: array[1..16, Square] @@ -64,15 +53,6 @@ type diceRolled*: array[Color, bool] winner*: Option[Color] gameOver*: bool - initialized: bool - - -proc init*(state: var GameState) = - state.camels.initFixedSeq - state.tiles.initFixedSeq - -proc newGameState*(): GameState = - result.init # use a template here for better inlining @@ -98,12 +78,6 @@ proc hash*(b: Board): Hash = result = !$h -proc init*(b: var Board) = - for sq in b.squares.mitems: - sq.camels.initFixedSeq - b.initialized = true - - proc leader*(b: Board): Color = let leadSquare = max(b.camels) result = b[leadSquare].camels[^1] @@ -138,7 +112,6 @@ proc setState*(b: var Board; state: GameState) = proc getState*(b: Board): GameState = - result.init var camelCount = 0 let start = min(b.camels) for pos in start .. b.squares.high: @@ -156,7 +129,6 @@ proc getState*(b: Board): GameState = proc diceRemaining*(b: Board): ColorStack = - result.initFixedSeq for color, isRolled in b.diceRolled: if not isRolled: result.add(color) @@ -183,11 +155,11 @@ proc advance*(b: var Board, die: Die) = endPos += int(t) if t == tBackward: prepend = true - let stackStart = b[startPos].camels.find(color) + let stackStart = cast[uint8](b[startPos].camels.find(color)) # cast is safe here, as long as b.camels is valid if prepend: b[startPos].camels.moveSubstackPre(b[endPos].camels, stackStart) let stackLen = b[startPos].camels.len - stackStart - for i in 0 ..< stackLen: + for i in 0'u8 ..< stackLen: # we know how many camels we added to the bottom, so set the position for each of those b.camels[b[endPos].camels[i]] = endPos else: diff --git a/simulation.nim b/simulation.nim index 425d718..aabd709 100644 --- a/simulation.nim +++ b/simulation.nim @@ -39,7 +39,6 @@ proc percents*(scores: ScoreSet): WinPercents = iterator legEndStates(b: Board): Board = var diceRemaining: ColorStack - diceRemaining.initFixedSeq for i, c in b.diceRolled: if not c: diceRemaining.add(i) diff --git a/test.nim b/test.nim index 8b2b73f..4b442cc 100644 --- a/test.nim +++ b/test.nim @@ -32,16 +32,10 @@ proc summarize(tr: TestResults, opname = "operations") = stdout.flushFile() -# proc getRand(): Rand = -# randomize() -# result = initRand(rand(int64)) - - proc newRandomGame(): Board = randomize() - result.init - var state = newGameState() + var state: GameState for i in 0 .. 4: let pos = rand(1..3) state.camels.add((c: Color(i), p: pos)) diff --git a/test.nims b/test.nims index ada9020..fe599ae 100644 --- a/test.nims +++ b/test.nims @@ -1,4 +1,3 @@ --threads: on --d: danger --d: lto ---opt: speed diff --git a/ui.nim b/ui.nim index 81b105f..47807d0 100644 --- a/ui.nim +++ b/ui.nim @@ -38,7 +38,6 @@ proc parseColor(c: char): Color = proc parseArgs*(): CmdConfig = - result.state.init() for p in os.commandLineParams(): if p == "-h": echo help