// Number Guessing Game // The computer picks a random number, you try to guess it! // Game configuration using ADTs type Difficulty = | Easy // 1-50, unlimited guesses | Medium // 1-100, 10 guesses | Hard // 1-200, 7 guesses // GameConfig: minNum, maxNum, maxGuesses type GameConfig = | GameConfig(Int, Int, Option) // GameState: secret, guesses, config type GameState = | GameState(Int, Int, GameConfig) type GuessResult = | TooLow | TooHigh | Correct // Config helpers fn getMinNum(config: GameConfig): Int = match config { GameConfig(min, _, _) => min } fn getMaxNum(config: GameConfig): Int = match config { GameConfig(_, max, _) => max } fn getMaxGuesses(config: GameConfig): Option = match config { GameConfig(_, _, maxG) => maxG } // State helpers fn getSecret(state: GameState): Int = match state { GameState(s, _, _) => s } fn getGuessCount(state: GameState): Int = match state { GameState(_, g, _) => g } fn getConfig(state: GameState): GameConfig = match state { GameState(_, _, c) => c } fn difficultyConfig(d: Difficulty): GameConfig = match d { Easy => GameConfig(1, 50, None), Medium => GameConfig(1, 100, Some(10)), Hard => GameConfig(1, 200, Some(7)) } fn difficultyName(d: Difficulty): String = match d { Easy => "Easy (1-50, unlimited guesses)", Medium => "Medium (1-100, 10 guesses)", Hard => "Hard (1-200, 7 guesses)" } // Core game logic (pure functions) fn checkGuess(guess: Int, secret: Int): GuessResult = if guess < secret then TooLow else if guess > secret then TooHigh else Correct fn isGameOver(state: GameState, result: GuessResult): Bool = match result { Correct => true, _ => match getMaxGuesses(getConfig(state)) { Some(max) => getGuessCount(state) >= max, None => false } } fn guessesRemaining(state: GameState): Option = match getMaxGuesses(getConfig(state)) { Some(max) => Some(max - getGuessCount(state)), None => None } // Game effects fn printWelcome(): Unit with {Console} = { Console.print("") Console.print("========================================") Console.print(" NUMBER GUESSING GAME") Console.print("========================================") Console.print("") } fn chooseDifficulty(): Difficulty with {Console} = { Console.print("Choose difficulty:") Console.print(" 1. " + difficultyName(Easy)) Console.print(" 2. " + difficultyName(Medium)) Console.print(" 3. " + difficultyName(Hard)) Console.print("") Console.print("Enter choice (1-3): ") let choice = Console.readInt() match choice { 1 => Easy, 2 => Medium, 3 => Hard, _ => { Console.print("Invalid choice, defaulting to Medium") Medium } } } fn initGame(difficulty: Difficulty): GameState with {Random} = { let config = difficultyConfig(difficulty) let secret = Random.int(getMinNum(config), getMaxNum(config)) GameState(secret, 0, config) } fn printGameStart(state: GameState): Unit with {Console} = { let config = getConfig(state) Console.print("") Console.print("I'm thinking of a number between " + toString(getMinNum(config)) + " and " + toString(getMaxNum(config)) + "...") match getMaxGuesses(config) { Some(max) => Console.print("You have " + toString(max) + " guesses."), None => Console.print("You have unlimited guesses.") } Console.print("") } fn getGuess(state: GameState): Int with {Console} = { match guessesRemaining(state) { Some(remaining) => Console.print("Guesses remaining: " + toString(remaining)), None => () } Console.print("Enter your guess: ") Console.readInt() } fn printResult(result: GuessResult): Unit with {Console} = match result { TooLow => Console.print("Too low! Try higher."), TooHigh => Console.print("Too high! Try lower."), Correct => Console.print("") } fn printVictory(state: GameState): Unit with {Console} = { Console.print("========================================") Console.print(" CONGRATULATIONS! You got it!") Console.print(" The number was: " + toString(getSecret(state))) Console.print(" Guesses used: " + toString(getGuessCount(state))) Console.print("========================================") } fn printDefeat(state: GameState): Unit with {Console} = { Console.print("========================================") Console.print(" GAME OVER - Out of guesses!") Console.print(" The number was: " + toString(getSecret(state))) Console.print("========================================") } // Main game loop fn gameLoop(state: GameState): GameState with {Console} = { let guess = getGuess(state) let result = checkGuess(guess, getSecret(state)) let newState = GameState(getSecret(state), getGuessCount(state) + 1, getConfig(state)) printResult(result) if isGameOver(newState, result) then { match result { Correct => printVictory(newState), _ => printDefeat(newState) } newState } else { gameLoop(newState) } } fn askPlayAgain(): Bool with {Console} = { Console.print("") Console.print("Play again? (1 = yes, 2 = no): ") let choice = Console.readInt() choice == 1 } fn playGame(): Unit with {Console, Random} = { let difficulty = chooseDifficulty() let state = initGame(difficulty) printGameStart(state) let finalState = gameLoop(state) () } fn mainLoop(): Unit with {Console, Random} = { playGame() if askPlayAgain() then mainLoop() else Console.print("Thanks for playing! Goodbye!") } fn main(): Unit with {Console, Random} = { printWelcome() mainLoop() } let output = run main() with {}