# tags: mastermind, bulls & cows, game, puzzle, awk, code # # awk mastermind codebreaking game # Michael Sanders 2023 # https://busybox.neocities.org/notes/mastermind.txt # # First appearing as a traditional pencil & paper game known as # Bulls and Cows, this game probably dates back to the 1900s. # The earliest known computer program, called MOO, was written # by Dr. Frank King in 1968 at Cambridge University. # # You'll need awk plus an ANSI capable terminal... # # Unix invocation: awk -v SEED=$RANDOM -f mastermind.txt # Windows invocation: awk -v SEED=%RANDOM% -f mastermind.txt BEGIN { if (!SEED) SEED = 9351 srand(SEED) mastermind() } function mastermind( s, x, y, secret, digit, key, code, attempts, stack) { s = sprintf("\033[H\033[2J") s = s sprintf("\033[4;3HOverview...") s = s sprintf("\033[6;3H8 chances to guess the 4-digit key") s = s sprintf("\033[7;3Hx = digit & its position exact") s = s sprintf("\033[8;3Hy = digit exact, position invalid") s = s sprintf("\033[9;3Hz = digit & position invalid") s = s sprintf("\033[11;3HStack...") printf s while (1) { secret = "" while (length(secret) < 4) { digit = int(rand() * 10) if (index(secret, digit) == 0) secret = secret digit } status(SEED, "NULL", "----", 0) attempts = 0 delete stack while (attempts < 8) { for (x = 8; x >= 1; x--) { printf "\033[" (21 - x) ";3H" if (x <= attempts) printf "%d/8 %s\n", x, stack[x] else printf "%d/8 ----\n", x } printf "\033[22;3H\033[KEnter your 4-digit key: " getline key key = trim(tolower(key)) y = length(key) if (substr(key, 1, 1) ~ /^q/) { printf "\033[H\033[2J" exit } if (y != 4 || key !~ /^[0-9]+$/) continue attempts++ code = update(key, secret) stack[attempts] = code status(SEED, key, code, attempts) if (code == "xxxx") { printf "\033[22;3H\033[2KCongratulations! You've guessed the key: %s", secret break } if (attempts == 8) printf "\033[22;3H\033[2KGame over. The correct key was: %s", secret } printf "\033[" (21 - attempts) ";3H%d/8 %s", attempts, stack[attempts] printf "\033[23;3HPlay another round? [y/n]:" getline key if (substr(key, 1, 1) !~ /^y/) { printf "\033[H\033[2J" exit } else printf "\033[23;3H\033[2K" } } function roundup(num) { if (num == int(num)) return int(num) else return (num > 0 ? int(num) + 1 : int(num)) } function update(k, s, c, d, x, y) { c = "zzzz" for (x = 1; x <= 4; x++) { if (substr(k, x, 1) == substr(s, x, 1)) c = substr(c, 1, x-1) "x" substr(c, x+1) } for (x = 1; x <= 4; x++) { d = substr(k, x, 1) y = (substr(c, x, 1) != "x" ? 0 : 1) y += (index(s, d) > 0 ? 0 : 1) y += (substr(c, index(s, d), 1) != "x" ? 0 : 1) y += (substr(c, x, 1) != "y" ? 0 : 1) if (y == 0) c = substr(c, 1, x-1) "y" substr(c, x+1) } return c } function status(s, x, y, z) { s = sprintf("Seed: %-4s", s) x = sprintf("Key: %-4s", x) y = sprintf("Stack: %-4s", y) z = sprintf("Anxiety: %d%% ", roundup(z / 8 * 100)) printf "\033[2;3HMastermind: Q=Quit | %s | %s | %s | %s", s, x, y, z } function trim(str) { sub(/^[[:space:]]+/, "", str) # strip leading sub(/[[:space:]]+$/, "", str) # strip trailing return str } # eof