Browse Source

makin me a wordle clone

trunk
Shanti Chellaram 4 years ago
commit
5ed51b7e9c
  1. 1
      README.md
  2. 207
      wordle.c

1
README.md

@ -0,0 +1 @@
Proof that wordle is solvable in 6 moves.

207
wordle.c

@ -0,0 +1,207 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#define WORD_LENGTH 5
/* represents a 5-bit letter */
typedef uint8_t let_t;
/* represents a 5-bit letter + 3-bit position */
typedef uint8_t lpos_t;
/* represents a set of possible letters (technically, 26-bits) */
typedef uint32_t let_set_t;
/* represents 5 5-bit letters, a word */
typedef uint32_t word_t;
#define let_from_char(c) (((c) - 'a') & 0x1F)
#define let_to_char(c) ((c) + 'a')
lpos_t cptolp(char c, uint8_t pos) {
return (let_from_char(c) << 3) | pos;
}
let_set_t ls_add(let_set_t set, let_t letter) {
return set | (1 << letter);
}
let_set_t ls_test(let_set_t set, let_t letter) {
return (set & (1 << letter)) != 0;
}
uint8_t lp_pos(lpos_t lp) {
return 0x07 & lp;
}
char lp_char(lpos_t lp) {
return let_to_char(lp >> 3);
}
/* result is a 2-bit value: */
typedef enum result {
RES_BLACK = 0x01,
RES_YELLOW = 0x02,
RES_GREEN = 0x03
} result_t;
/* represents a wordle result: 5 2-bit result codes */
typedef uint16_t result_set_t;
result_set_t rs_set(result_t res, size_t index, result_t value) {
return res | ((value & 0x3) << (2 * index));
}
result_t rs_get(result_t res, size_t index) {
return (res >> (2 * index)) & 0x3;
}
char word_charat(word_t word, size_t index) {
return (char) ((word >> (index * 5)) & 0x1F) + 'a';
}
/* converts a 5-letter word to its compacted representation */
word_t strtoword(char *str) {
word_t word = 0;
for (size_t i = 0; i < WORD_LENGTH; ++i) {
word |= (str[i] - 'a') << (5 * i);
}
return word;
}
void wordtostr(char *out, word_t word) {
for (size_t i = 0; i < WORD_LENGTH; ++i) {
out[i] = word_charat(word, i);
}
}
result_set_t guess_match_werd(char *answer, char *guess) {
bool guess_consumed[WORD_LENGTH] = {false};
bool answer_consumed[WORD_LENGTH] = {false};
result_set_t result_set = 0;
for (size_t i = 0; i < WORD_LENGTH; ++i) {
if (answer[i] == guess[i]) {
answer_consumed[i] = true;
guess_consumed[i] = true;
result_set = rs_set(result_set, i, RES_GREEN);
}
}
for (size_t i = 0; i < WORD_LENGTH; ++i) {
if (guess_consumed[i]) { continue; }
bool found = false;
for (size_t j = 0; j < WORD_LENGTH; ++j) {
if (answer_consumed[j]) { continue; }
if (answer[j] == guess[i]) {
answer_consumed[j] = true;
found = true;
break;
}
}
if (found) {
result_set = rs_set(result_set, i, RES_YELLOW);
} else {
result_set = rs_set(result_set, i, RES_BLACK);
}
}
return result_set;
}
result_set_t guess_match(word_t answer_word, word_t guess_word) {
char answer[6] = {0},
guess[6] = {0};
wordtostr(answer, answer_word);
wordtostr(guess, guess_word);
return guess_match_werd(answer, guess);
}
/* returns whether or not the game was won */
typedef struct wordle_game {
word_t target;
uint32_t turn_limit;
int (*guess_fn)(word_t *, void *);
void *guess_fn_data;
void (*display_fn)(result_set_t, void *);
void *display_fn_data;
} wordle_game_t;
bool play_game(wordle_game_t *game) {
for (uint32_t turn = 1; turn <= game->turn_limit; ++turn) {
word_t guess = 0;
if (game->guess_fn(&guess, game->guess_fn_data) != 0) {
printf("guesser failure\n");
}
result_set_t result_set = guess_match(game->target, guess);
game->display_fn(result_set, game->display_fn_data);
if (guess == game->target) {
return true;
}
}
return false;
}
struct linebuf {
char *buffer;
size_t capacity;
};
int term_guess(word_t *word, void *data) {
struct linebuf *linebuf = data;
while (true) {
ssize_t bytes_read = getline(&(linebuf->buffer), &(linebuf->capacity), stdin);
if (bytes_read == -1) {
return -1;
}
char *buf_end = linebuf->buffer;
strsep(&buf_end, "\n");
if (strchr(linebuf->buffer, '\0') - linebuf->buffer == WORD_LENGTH) {
*word = strtoword(linebuf->buffer);
return 0;
} else {
continue;
}
}
}
void term_display(result_set_t result_set, void *ignored) {
(void) ignored;
for (size_t i = 0; i < WORD_LENGTH; ++i) {
switch (rs_get(result_set, i)) {
case RES_BLACK:
fputc(' ', stdout);
break;
case RES_YELLOW:
fputc('Y', stdout);
break;
case RES_GREEN:
fputc('G', stdout);
break;
default:
fputc('X', stdout);
break;
}
}
fputs(" result", stdout);
fputc('\n', stdout);
}
int main(int argc, char *argv[]) {
struct linebuf lb = {
.capacity = 6,
.buffer = (char *) malloc(lb.capacity),
};
wordle_game_t game = {
.target = strtoword("total"),
.turn_limit = 6,
.guess_fn = term_guess,
.guess_fn_data = &lb,
.display_fn = term_display,
.display_fn_data = NULL,
};
int x = play_game(&game);
printf("endgame %d\n", x);
return 0;
}
Loading…
Cancel
Save