|
|
|
@ -121,46 +121,41 @@ result_set_t guess_match(word_t answer_word, word_t guess_word) { |
|
|
|
/* returns whether or not the game was won */ |
|
|
|
typedef struct wordle_game { |
|
|
|
word_t target; |
|
|
|
uint32_t turn_limit; |
|
|
|
uint32_t turn_number, 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; |
|
|
|
}; |
|
|
|
|
|
|
|
/* the guess function returns 0 on success and something else on failure */ |
|
|
|
int term_guess(word_t *word, void *data) { |
|
|
|
struct linebuf *linebuf = data; |
|
|
|
while (true) { |
|
|
|
fputs("guess> ", stdout); |
|
|
|
ssize_t bytes_read = getline(&(linebuf->buffer), &(linebuf->capacity), stdin); |
|
|
|
/* if the input is closed, there's no way to recover. fail out */ |
|
|
|
if (bytes_read == -1) { |
|
|
|
return -1; |
|
|
|
} |
|
|
|
char *buf_end = linebuf->buffer; |
|
|
|
strsep(&buf_end, "\n"); |
|
|
|
if (strchr(linebuf->buffer, '\0') - linebuf->buffer == WORD_LENGTH) { |
|
|
|
size_t length = strchr(linebuf->buffer, '\0') - linebuf->buffer; |
|
|
|
/* some basic error checking around length */ |
|
|
|
if (length == WORD_LENGTH) { |
|
|
|
*word = strtoword(linebuf->buffer); |
|
|
|
return 0; |
|
|
|
} else { |
|
|
|
if (length > WORD_LENGTH) { |
|
|
|
fprintf(stderr, "error: too long\n"); |
|
|
|
} else { |
|
|
|
fprintf(stderr, "error: too short\n"); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -168,6 +163,7 @@ int term_guess(word_t *word, void *data) { |
|
|
|
|
|
|
|
void term_display(result_set_t result_set, void *ignored) { |
|
|
|
(void) ignored; |
|
|
|
fputs("result ", stdout); |
|
|
|
for (size_t i = 0; i < WORD_LENGTH; ++i) { |
|
|
|
switch (rs_get(result_set, i)) { |
|
|
|
case RES_BLACK: |
|
|
|
@ -184,10 +180,25 @@ void term_display(result_set_t result_set, void *ignored) { |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
fputs(" result", stdout); |
|
|
|
fputc('\n', stdout); |
|
|
|
} |
|
|
|
|
|
|
|
bool play_game(wordle_game_t *game) { |
|
|
|
for (game->turn_number = 1; game->turn_number <= game->turn_limit; ++game->turn_number) { |
|
|
|
word_t guess = 0; |
|
|
|
if (game->guess_fn(&guess, game->guess_fn_data) != 0) { |
|
|
|
printf("guesser failure\n"); |
|
|
|
break; |
|
|
|
} |
|
|
|
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; |
|
|
|
} |
|
|
|
|
|
|
|
int main(int argc, char *argv[]) { |
|
|
|
struct linebuf lb = { |
|
|
|
.capacity = 6, |
|
|
|
@ -195,13 +206,18 @@ int main(int argc, char *argv[]) { |
|
|
|
}; |
|
|
|
wordle_game_t game = { |
|
|
|
.target = strtoword("total"), |
|
|
|
.turn_number = 0, |
|
|
|
.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); |
|
|
|
bool won = play_game(&game); |
|
|
|
if (won) { |
|
|
|
fprintf(stdout, "YOU WIN %d/%d\n", game.turn_number, game.turn_limit); |
|
|
|
} else { |
|
|
|
fprintf(stdout, "YOU LOSE\n"); |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |