diff --git a/src/lib/runner.ts b/src/lib/runner.ts new file mode 100644 index 0000000..cf01559 --- /dev/null +++ b/src/lib/runner.ts @@ -0,0 +1,91 @@ +import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; + +import { Guessing } from "./guesser.ts"; +import { Gaming, GuessResult } from "./game/game.ts"; +import { last, wait } from "./utils.ts"; + +export class Runner { + game; + guesser; + delay_ms; + turns; + logging; + + constructor(game: Ga, guesser: Gu, logging: LoggingStrategy, delay_ms = 0) { + this.game = game; + this.guesser = guesser; + this.delay_ms = delay_ms; + this.turns = [] as Turn[]; + this.logging = logging; + } + + async play_all() { + this.logging.on_start(this.game.length()); + while (true) { + const result = await this.guesser.guess(async (guess, known) => { + const result = await this.game.guess(guess, known); + this.turns.push({ guess, result }); + this.logging.on_guess(known, guess, result); + return result; + }); + if (result !== null) break; + await wait(this.delay_ms); + } + this.logging.on_finish(this.turns); + } +} + +type Turn = { guess: string; result: GuessResult }; + +function format_result(result: GuessResult) { + if (result.kind === "success") return "success"; + let line = ""; + for (const info of result.informations) { + if (info.kind === "abscent") line += "."; + if (info.kind === "somewhere") line += "*"; + if (info.kind === "there") line += "#"; + } + return line; +} + +interface LoggingStrategy { + on_start(length: number): void; + on_guess(known: string, guess: string, result: GuessResult): void; + on_finish(turns: Turn[]): void; +} + +export class VerboseLogging implements LoggingStrategy { + on_start(length: number) {} + + on_guess(known: string, guess: string, result: GuessResult): void { + console.log(" Knows:", known); + console.log("Guessing:", guess); + console.log(" Got:", format_result(result)); + console.log(); + } + + on_finish(turns: Turn[]): void { + const last_ = last(turns); + assertExists(last_); + console.log("Stopped on", last_.guess, "."); + console.log("With", last_.result.kind, "."); + console.log("In", turns.length, "steps"); + } +} + +export class TableLogging implements LoggingStrategy { + on_start(length: number): void { + const pad = (title: string) => title.padEnd(length); + console.log(`${pad("known")}\t${pad("guess")}\t${pad("result")}`); + console.log(); + } + on_guess(known: string, guess: string, result: GuessResult): void { + console.log(`${known}\t${guess}\t${format_result(result)}`); + } + on_finish(turns: Turn[]): void { + const last_ = last(turns); + assertExists(last_); + console.log(); + console.log(last_.result.kind, "in", turns.length, "steps"); + } +}