diff --git a/src/lib/dict.ts b/src/lib/dict.ts index 50603a6..cb679c9 100644 --- a/src/lib/dict.ts +++ b/src/lib/dict.ts @@ -25,6 +25,13 @@ export class Dict { return Dict.from_lines(content.split("\n"), length); } + constraint(at: number, letter: string) { + const to_delete = new Set(); + for (const word of this.words.values()) if (word[at] !== letter) to_delete.add(word); + for (const item of to_delete) this.words.delete(item); + return to_delete.size; + } + [Symbol.for("Deno.customInspect")]() { return `Dict { ${this.words.size} words, ${this.letters.size} letters }`; } diff --git a/src/lib/game/proxy.ts b/src/lib/game/proxy.ts index 1e55085..ced5f21 100644 --- a/src/lib/game/proxy.ts +++ b/src/lib/game/proxy.ts @@ -12,7 +12,9 @@ export class ManualProxy implements Gaming { guess(guess: string, _known: string): Awaitable { console.log(" Guessing:", guess); - return read_until_correct(this.word_length); + const result = read_until_correct(this.word_length); + console.log(); + return result; } length(): number { @@ -25,7 +27,10 @@ function read_until_correct(length: number): GuessResult { const input = prompt(" Result:"); assertExists(input); const informations = parse_input(input, length); - if (informations === null) continue; + if (informations === null) { + console.log(" incorrect input, try again"); + continue; + } if (informations.every((i) => i.kind === "there")) return { kind: "success" }; return { kind: "failure", informations }; } @@ -34,9 +39,9 @@ function read_until_correct(length: number): GuessResult { function parse_input(input: string, length: number) { const parsed = [] as Info[]; for (const character of input.trim()) { - if (character === "n") parsed.push({ kind: "abscent" }); - if (character === "i") parsed.push({ kind: "somewhere" }); - if (character === "y") parsed.push({ kind: "there" }); + if (character === ".") parsed.push({ kind: "abscent" }); + if (character === "-") parsed.push({ kind: "somewhere" }); + if (character === "+") parsed.push({ kind: "there" }); } if (parsed.length !== length) return null; else return parsed; diff --git a/src/lib/guesser.ts b/src/lib/guesser.ts index c0afca6..841dc88 100644 --- a/src/lib/guesser.ts +++ b/src/lib/guesser.ts @@ -53,13 +53,13 @@ export class Guesser implements Guessing { return null; } - learn_does_not_exist(letter: string) { + public learn_does_not_exist(letter: string) { const letter_info = this.informations.get(letter); assertExists(letter_info); letter_info.exists = false; } - learn_does_exist(letter: string) { + public learn_does_exist(letter: string) { const letter_info = this.informations.get(letter); assertExists(letter_info); letter_info.exists = true; @@ -68,7 +68,8 @@ export class Guesser implements Guessing { for (const info of this.informations.values()) if (info.exists === "unknown") info.exists = false; } - learn_letter_at(letter: string, at: number) { + public learn_letter_at(letter: string, at: number) { + this.learn_does_exist(letter); const letter_info = this.informations.get(letter); assertExists(letter_info); letter_info.at.add(at); @@ -78,7 +79,7 @@ export class Guesser implements Guessing { } } - learn_letter_not_at(letter: string, at: number) { + public learn_letter_not_at(letter: string, at: number) { const letter_info = this.informations.get(letter); assertExists(letter_info); letter_info.not_at.add(at); diff --git a/src/lib/prompt.ts b/src/lib/prompt.ts new file mode 100644 index 0000000..01f42a8 --- /dev/null +++ b/src/lib/prompt.ts @@ -0,0 +1,46 @@ +import { assertExists } from "https://deno.land/std@0.224.0/assert/assert_exists.ts"; + +import { enumerate } from "./utils.ts"; + +export function initialize_prompt() { + console.log("Please input initial state of the game. Format is :"); + console.log(" letter [a-z] known letter"); + console.log(" dot . unknown letter"); + console.log("example : .rb.."); + console.log(""); + const inputted = parse_initialization_until_correct(); + console.log(""); + console.log("From now on, please try the following guesses and report results. Format is :"); + console.log(" plus + correct"); + console.log(" minus - wrong placement"); + console.log(" dot . incorrect"); + console.log("example : -++.."); + console.log(); + return inputted; +} + +function parse_initialization_until_correct() { + let input = prompt("initial :"); + while (true) { + assertExists(input); + const parsed = parse_initialization(input); + if (parsed === null) input = prompt("Invalid, please try again :"); + else return parsed; + } +} + +function parse_initialization(input: string) { + const code_a = "a".charCodeAt(0); + const code_z = "z".charCodeAt(0); + let length = 0; + const constraints = [] as [number, string][]; + for (const [index, char] of enumerate(input.trim().toLowerCase())) { + length += 1; + if (char === ".") continue; + const code = char.charCodeAt(0); + if (code < code_a) return null; + if (code > code_z) return null; + constraints.push([index, char]); + } + return { length, constraints }; +} diff --git a/src/manual_proxy.ts b/src/manual_proxy.ts old mode 100644 new mode 100755 index c0a80b7..4ffaf87 --- a/src/manual_proxy.ts +++ b/src/manual_proxy.ts @@ -3,6 +3,7 @@ import { Command } from "https://deno.land/x/cliffy@v1.0.0-rc.4/command/mod.ts"; import { Dict, Guesser, ManualProxy, Runner } from "./lib/lib.ts"; +import { initialize_prompt } from "./lib/prompt.ts"; import { VerboseLogging } from "./lib/runner.ts"; import { francais } from "../data/data.ts"; @@ -15,23 +16,18 @@ async function main() { .option( "-f, --file ", "Sets dictionnary to use words from (defaults to internal french dict).", - ).option( - "-n, --length ", - "Length of the word to use from the dictionnary.", - { default: 6 }, - ).option( - "-w, --wait ", - "Time to wait between guesses, in ms.", - { default: 0 }, ).parse(Deno.args); - let dict = Dict.from_lines(francais, args.options.length); - if (args.options.file !== undefined) dict = await Dict.from_text_file(args.options.file, args.options.length); + const init = initialize_prompt(); + + let dict = Dict.from_lines(francais, init.length); + if (args.options.file !== undefined) dict = await Dict.from_text_file(args.options.file, init.length); + for (const [index, letter] of init.constraints) dict.constraint(index, letter); const guesser = new Guesser(dict); - const game = new ManualProxy(args.options.length); + const game = new ManualProxy(init.length); - const runner = new Runner(game, guesser, new VerboseLogging(), args.options.wait); + const runner = new Runner(game, guesser, new VerboseLogging()); await runner.play_all(); }