# tags: boogle, game, puzzle, words, ANSI, REPL, awk, code # # boogle word grid game # Michael Sanders 2023 # https://busybox.neocities.org/notes/boogle.txt # # requires awk, an ANSI capable terminal & the sleep command # # usage example: awk -f boogle.txt BEGIN { ROW = 3; COL = 62 srand() boogle() } function random_letter() { return sprintf("%c", int(rand() * 26) + 65) } function trim(str) { sub(/^[[:space:]]+/, "", str) # strip leading sub(/[[:space:]]+$/, "", str) # strip trailing return str } function statusBar() { printf "\033[%d;%dH\033[K", 2, 50 printf "\033[%d;%dHBOOGLE | Q=Quit | Word: %03d/100 | Guess: %d/3 | %s", 2, 3, COUNT, ATTEMPTS, MSG } function boogle( x, y, n, ndx, m) { COUNT = ATTEMPTS = 1 printf "\033]0;Boogle\007" # system("cmd /c @title Boogle") # <- windows m[1] = "Boogle is a fun little word game. There are 100 words and" m[2] = "you have 3 attempts to guess the word hidden in the grid." m[3] = "Look for words: horizontally, vertically, or diagonally." printf "\033[H\033[2J\033[?25l" # clear screen & hide cursor MSG = "Ready..."; statusBar() for(x = 1; x <= 3; x++) printf "\033[%d;%dH%s", 3 + x, 3, m[x] y = n = load_words() while(y > 0) { ndx = int(rand() * y) + 1 WORD = w[ndx] # remove selected word from array & shift other elements for (x = ndx; x < y; x++) w[x] = w[x+1] delete w[y] y-- COUNT = n - y jumble() inject() guess() } printf "\033[H\033[2JGameover!\n" exit } function jumble( x, y, z, b) { b = "" while (++z < 6) { for (x = 1; x <= 4; x++) { for (y = 1; y <= 4; y++) { GRID[x, y] = random_letter() b = b sprintf("\033[%d;%dH%s", ROW + x, COL + (2 * y - 1), GRID[x, y]) if (y < 4) b = b " " } b = b sprintf("\n") } printf "%s", b system("sleep 0.00001") } } function inject( d, r, c, v, x, y, b) { # choose a valid starting position & word direction do { d = int(rand() * 4) # direction: 0 horizontal, 1 diagonal right-down, 2 vertical, 3 diagonal left-down r = int(rand() * 4) + 1 # row c = int(rand() * 4) + 1 # column v = 1 # check validity of position for(x = 0; x < length(WORD) && v; x++) { if(d == 0 && (c + x > 4)) v = 0 else if(d == 1 && (r + x > 4 || c + x > 4)) v = 0 else if(d == 2 && (r + x > 4)) v = 0 else if(d == 3 && (r + x > 4 || c - x < 1)) v = 0 } } while (!v) for(x = 0; x < length(WORD); x++) { if(d == 0) GRID[r, c + x] = substr(WORD, x + 1, 1) else if(d == 1) GRID[r + x, c + x] = substr(WORD, x + 1, 1) else if(d == 2) GRID[r + x, c] = substr(WORD, x + 1, 1) else GRID[r + x, c - x] = substr(WORD, x + 1, 1) } b = "" for(x = 1; x <= 4; x++) { for(y = 1; y <= 4; y++) { b = b sprintf("\033[%d;%dH%s", ROW + x, COL + (2 * y - 1), GRID[x, y]) if (y < 4) b = b " " } b = b sprintf("\n") } printf b } function guess() { for(ATTEMPTS = 1; ATTEMPTS <= 3; ATTEMPTS++) { statusBar() printf("\033[%d;%dH\033[KGuess %d: ", ROW + 5, 3, ATTEMPTS) getline userGuess userGuess = toupper(trim(userGuess)) if (userGuess == "Q") { printf "\033[H\033[2JGoodbye!\n" exit } if (userGuess == WORD) MSG = "Correct! Next word ready..." else if(ATTEMPTS == 3) MSG = "Sorry! Correct word was " WORD else MSG = "Try again!" if (userGuess == WORD) break } } function load_words() { w[ 1] = "ABLY"; w[ 2] = "ACID"; w[ 3] = "AGES"; w[ 4] = "ALOE"; w[ 5] = "BARK" w[ 6] = "BOLT"; w[ 7] = "BULK"; w[ 8] = "CALM"; w[ 9] = "CLAD"; w[10] = "DAZE" w[11] = "DEAF"; w[12] = "EASE"; w[13] = "ECHO"; w[14] = "EDGE"; w[15] = "FAME" w[16] = "FAWN"; w[17] = "FLOW"; w[18] = "GAZE"; w[19] = "GEAR"; w[20] = "HALT" w[21] = "HEAP"; w[22] = "ICED"; w[23] = "JADE"; w[24] = "JOIN"; w[25] = "KNIT" w[26] = "KEEL"; w[27] = "KITE"; w[28] = "LACE"; w[29] = "LOAD"; w[30] = "LASH" w[31] = "MACE"; w[32] = "MILD"; w[33] = "MINT"; w[34] = "MOAT"; w[35] = "NAIL" w[36] = "NODE"; w[37] = "OARS"; w[38] = "PACE"; w[39] = "PINE"; w[40] = "QUAD" w[41] = "QUIZ"; w[42] = "RACE"; w[43] = "RANK"; w[44] = "RIME"; w[45] = "ROVE" w[46] = "SALE"; w[47] = "SALT"; w[48] = "SEAM"; w[49] = "SHIM"; w[50] = "SLIP" w[51] = "SLOT"; w[52] = "SLOW"; w[53] = "SMUG"; w[54] = "SNIP"; w[55] = "SOAP" w[56] = "TAPE"; w[57] = "TALE"; w[58] = "TAME"; w[59] = "TANK"; w[60] = "TILE" w[61] = "TILT"; w[62] = "TIME"; w[63] = "TINT"; w[64] = "TOIL"; w[65] = "TOLL" w[66] = "TOME"; w[67] = "TONE"; w[68] = "TORN"; w[69] = "TRIM"; w[70] = "VAIN" w[71] = "VASE"; w[72] = "VEAL"; w[73] = "VEIL"; w[74] = "WAIL"; w[75] = "WANE" w[76] = "WARM"; w[77] = "WASP"; w[78] = "WAVE"; w[79] = "WEAK"; w[80] = "WEAR" w[81] = "WELT"; w[82] = "WHIM"; w[83] = "WILD"; w[84] = "WILT"; w[85] = "WINE" w[86] = "WING"; w[87] = "WIPE"; w[88] = "WIRE"; w[89] = "WISP"; w[90] = "WOVE" w[91] = "YARN"; w[92] = "YAWN"; w[93] = "ZEST"; w[94] = "ZINC"; w[95] = "ZONE" w[96] = "ZOOM"; w[97] = "PURE"; w[98] = "LUSH"; w[99] = "PUSH"; w[100] = "MUSH" return 100 } # eof