diff --git a/src/wordle.zig b/src/wordle.zig index 901db00..1b40a5a 100644 --- a/src/wordle.zig +++ b/src/wordle.zig @@ -9,6 +9,51 @@ pub const Word = [WordLen]u8; /// The type of string literals representing words. pub const WordLiteral = *const [WordLen:0]u8; +/// The number of rounds in a single Wordle game. +pub const GameLen = 6; + +/// An error reported when a move cannot be played since the game is over. +pub const GameOver = error{GameOver}; + +/// A structure for a single Wordle game. +pub const Game = struct { + /// The hidden word to guess. + solution: Word, + + /// The round number (starts with 0). + round: u32 = 0, + + /// The current (and future) word guesses. + /// + /// The values of guessBuf[self.round..] are undefined. + guessBuf: [GameLen]Word = @splat(@splat(0)), + + /// Fetches the current guesses. + pub fn guesses(self: *const Game) []const Word { + return self.guessBuf[0..self.round]; + } + + /// Tests if the game is won. + pub fn isWon(self: Game) bool { + for (self.guesses()) |guess| + if (std.mem.eql(u8, &guess, &self.solution)) return true; + + return false; + } + + /// Tests if the game is over. + pub fn isOver(self: Game) bool { + return self.round >= GameLen or self.isWon(); + } + + /// Guesses a word unless the game is over. + pub fn addGuess(self: *Game, guess: Word) GameOver!void { + if (self.isOver()) return error.GameOver; + self.guessBuf[self.round] = guess; + self.round += 1; + } +}; + /// A clue for a spot given a guess. pub const Clue = enum { Gray, @@ -98,3 +143,20 @@ test "anagram" { test "duplicate letters" { try expectGuessClues("fuzzy", "zesty", " Y G"); } + +test "game" { + // default state + var game: Game = .{ .solution = strToWord("poise") }; + try std.testing.expect(!game.isWon()); + try std.testing.expect(!game.isOver()); + + // first guess + try game.addGuess(strToWord("brown")); + try std.testing.expect(!game.isWon()); + try std.testing.expect(!game.isOver()); + + // second guess + try game.addGuess(strToWord("poise")); + try std.testing.expect(game.isWon()); + try std.testing.expect(game.isOver()); +}