Face compares the values correctly now and does a dict lookup first
This commit is contained in:
parent
0c86be4a40
commit
8ea779874f
@ -33,9 +33,8 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
TODO:
|
TODO:
|
||||||
* Add quick iteration (8x freq to get to the letter we want)
|
|
||||||
* Fix the word matching (if answer is AAAAA and we put in AACAA, the C blinks)
|
|
||||||
* Add a way to recount previous attempts
|
* Add a way to recount previous attempts
|
||||||
|
* Only allow dictionary attempts - Show "nodict" otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -106,6 +105,41 @@ static uint32_t get_random(uint32_t max) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t get_first_pos(WordleLetterResult *word_elements_result) {
|
||||||
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
|
if (word_elements_result[i] != WORDLE_LETTER_CORRECT)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t get_next_pos(uint8_t curr_pos, WordleLetterResult *word_elements_result) {
|
||||||
|
for (size_t pos = curr_pos+1; pos < WORDLE_LENGTH; pos++) {
|
||||||
|
if (word_elements_result[pos] != WORDLE_LETTER_CORRECT)
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
return WORDLE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t get_prev_pos(uint8_t curr_pos, WordleLetterResult *word_elements_result) {
|
||||||
|
if (curr_pos == 0) return 0;
|
||||||
|
for (size_t pos = curr_pos-1; pos > 0; pos--) {
|
||||||
|
if (word_elements_result[pos] != WORDLE_LETTER_CORRECT)
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
return curr_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_next_letter(uint8_t curr_pos, uint8_t *word_elements) {
|
||||||
|
if (word_elements[curr_pos] >= _num_valid_letters) word_elements[curr_pos] = 0;
|
||||||
|
else word_elements[curr_pos] = (word_elements[curr_pos] + 1) % _num_valid_letters;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_prev_letter(uint8_t curr_pos, uint8_t *word_elements) {
|
||||||
|
if (word_elements[curr_pos] >= _num_valid_letters) word_elements[curr_pos] = _num_valid_letters - 1;
|
||||||
|
else word_elements[curr_pos] = (word_elements[curr_pos] + _num_valid_letters - 1) % _num_valid_letters;
|
||||||
|
}
|
||||||
|
|
||||||
static void display_letter(wordle_state_t *state, bool display_dash) {
|
static void display_letter(wordle_state_t *state, bool display_dash) {
|
||||||
char buf[1 + 1];
|
char buf[1 + 1];
|
||||||
if (state->word_elements[state->position] >= _num_valid_letters) {
|
if (state->word_elements[state->position] >= _num_valid_letters) {
|
||||||
@ -121,6 +155,7 @@ static void display_letter(wordle_state_t *state, bool display_dash) {
|
|||||||
|
|
||||||
static void display_all_letters(wordle_state_t *state) {
|
static void display_all_letters(wordle_state_t *state) {
|
||||||
uint8_t prev_pos = state->position;
|
uint8_t prev_pos = state->position;
|
||||||
|
watch_display_string(" ", 4);
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
state->position = i;
|
state->position = i;
|
||||||
display_letter(state, false);
|
display_letter(state, false);
|
||||||
@ -128,31 +163,47 @@ static void display_all_letters(wordle_state_t *state) {
|
|||||||
state->position = prev_pos;
|
state->position = prev_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool check_word_in_dict(uint8_t *word_elements) {
|
||||||
|
bool is_exact_match;
|
||||||
|
for (uint16_t i = 0; i < _num_words; i++) {
|
||||||
|
is_exact_match = true;
|
||||||
|
for (size_t j = 0; j < WORDLE_LENGTH; j++) {
|
||||||
|
if (_valid_letters[word_elements[j]] != _legal_words[i][j]) {
|
||||||
|
is_exact_match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_exact_match) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static bool check_word(wordle_state_t *state) {
|
static bool check_word(wordle_state_t *state) {
|
||||||
WordleLetterResult checked_letter_in_answer[WORDLE_LENGTH] = {WORDLE_LETTER_WRONG};
|
|
||||||
// Exact
|
// Exact
|
||||||
bool is_exact_match = true;
|
bool is_exact_match = true;
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
if (_valid_letters[state->word_elements[i]] == _legal_words[state->curr_answer][i]) {
|
if (_valid_letters[state->word_elements[i]] == _legal_words[state->curr_answer][i])
|
||||||
state->word_elements_result[i] = checked_letter_in_answer[i] = WORDLE_LETTER_CORRECT;
|
state->word_elements_result[i] = WORDLE_LETTER_CORRECT;
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
state->word_elements_result[i] = WORDLE_LETTER_WRONG;
|
state->word_elements_result[i] = WORDLE_LETTER_WRONG;
|
||||||
is_exact_match = false;
|
is_exact_match = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_exact_match) return true;
|
||||||
// Wrong Location
|
// Wrong Location
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
bool answer_found_wrong_loc[WORDLE_LENGTH] = { false };
|
||||||
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
|
if (state->word_elements_result[i] != WORDLE_LETTER_WRONG) continue;
|
||||||
for (size_t j = 0; j < WORDLE_LENGTH; j++) {
|
for (size_t j = 0; j < WORDLE_LENGTH; j++) {
|
||||||
if (checked_letter_in_answer[j] != WORDLE_LETTER_WRONG) continue;
|
if (answer_found_wrong_loc[j]) continue;
|
||||||
if (_valid_letters[state->word_elements[i]] == _legal_words[state->curr_answer][j]) {
|
if (_valid_letters[state->word_elements[i]] == _legal_words[state->curr_answer][j]) {
|
||||||
state->word_elements_result[i] = checked_letter_in_answer[j] = WORDLE_LETTER_WRONG_LOC;
|
state->word_elements_result[i] = WORDLE_LETTER_WRONG_LOC;
|
||||||
|
answer_found_wrong_loc[j] = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return is_exact_match;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_attempt(uint8_t attempt) {
|
static void display_attempt(uint8_t attempt) {
|
||||||
@ -161,19 +212,27 @@ static void display_attempt(uint8_t attempt) {
|
|||||||
watch_display_string(buf, 3);
|
watch_display_string(buf, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_start_of_attempt(wordle_state_t *state) {
|
||||||
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
|
if (state->word_elements_result[i] != WORDLE_LETTER_CORRECT)
|
||||||
|
state->word_elements[i] = _num_valid_letters;
|
||||||
|
}
|
||||||
|
display_attempt(state->attempt);
|
||||||
|
display_all_letters(state);
|
||||||
|
state->position = get_first_pos(state->word_elements_result);
|
||||||
|
state->curr_screen = SCREEN_PLAYING;
|
||||||
|
}
|
||||||
|
|
||||||
static void reset_board(wordle_state_t *state) {
|
static void reset_board(wordle_state_t *state) {
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
||||||
state->word_elements[i] = _num_valid_letters;
|
state->word_elements[i] = _num_valid_letters;
|
||||||
state->word_elements_result[i] = WORDLE_LETTER_WRONG;
|
state->word_elements_result[i] = WORDLE_LETTER_WRONG;
|
||||||
}
|
}
|
||||||
state->curr_answer = get_random(_num_words);
|
state->curr_answer = get_random(_num_words);
|
||||||
state->position = 0;
|
|
||||||
state->attempt = 1;
|
state->attempt = 1;
|
||||||
state->curr_screen = SCREEN_PLAYING;
|
|
||||||
watch_clear_colon();
|
watch_clear_colon();
|
||||||
watch_display_string(" ", 4);
|
watch_display_string(" ", 4);
|
||||||
display_attempt(state->attempt);
|
show_start_of_attempt(state);
|
||||||
display_all_letters(state);
|
|
||||||
watch_display_string("-", 5);
|
watch_display_string("-", 5);
|
||||||
#if __EMSCRIPTEN__
|
#if __EMSCRIPTEN__
|
||||||
printf("ANSWER: %s\r\n", _legal_words[state->curr_answer]);
|
printf("ANSWER: %s\r\n", _legal_words[state->curr_answer]);
|
||||||
@ -182,7 +241,7 @@ static void reset_board(wordle_state_t *state) {
|
|||||||
|
|
||||||
static void display_title(wordle_state_t *state) {
|
static void display_title(wordle_state_t *state) {
|
||||||
state->curr_screen = SCREEN_TITLE;
|
state->curr_screen = SCREEN_TITLE;
|
||||||
watch_display_string("WO WORDLE", 0);
|
watch_display_string("WO WordLE", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void display_streak(wordle_state_t *state) {
|
static void display_streak(wordle_state_t *state) {
|
||||||
@ -211,6 +270,11 @@ static void display_wait(wordle_state_t *state) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static void display_not_in_dict(wordle_state_t *state) {
|
||||||
|
state->curr_screen = SCREEN_NO_DICT;
|
||||||
|
watch_display_string("WO nodict", 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void display_lose(wordle_state_t *state, uint8_t subsecond) {
|
static void display_lose(wordle_state_t *state, uint8_t subsecond) {
|
||||||
char buf[WORDLE_LENGTH + 6];
|
char buf[WORDLE_LENGTH + 6];
|
||||||
sprintf(buf," L %s", subsecond % 2 ? _legal_words[state->curr_answer] : " ");
|
sprintf(buf," L %s", subsecond % 2 ? _legal_words[state->curr_answer] : " ");
|
||||||
@ -224,41 +288,6 @@ static void display_win(wordle_state_t *state, uint8_t subsecond) {
|
|||||||
watch_display_string(buf, 0);
|
watch_display_string(buf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_first_pos(WordleLetterResult *word_elements_result) {
|
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
|
||||||
if (word_elements_result[i] != WORDLE_LETTER_CORRECT)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t get_next_pos(uint8_t curr_pos, WordleLetterResult *word_elements_result) {
|
|
||||||
for (size_t pos = curr_pos+1; pos < WORDLE_LENGTH; pos++) {
|
|
||||||
if (word_elements_result[pos] != WORDLE_LETTER_CORRECT)
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
return WORDLE_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t get_prev_pos(uint8_t curr_pos, WordleLetterResult *word_elements_result) {
|
|
||||||
if (curr_pos == 0) return 0;
|
|
||||||
for (int8_t pos = curr_pos-1; pos >= 0; pos--) {
|
|
||||||
if (word_elements_result[pos] != WORDLE_LETTER_CORRECT)
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
return curr_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_next_letter(uint8_t curr_pos, uint8_t *word_elements) {
|
|
||||||
if (word_elements[curr_pos] >= _num_valid_letters) word_elements[curr_pos] = 0;
|
|
||||||
else word_elements[curr_pos] = (word_elements[curr_pos] + 1) % _num_valid_letters;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void get_prev_letter(uint8_t curr_pos, uint8_t *word_elements) {
|
|
||||||
if (word_elements[curr_pos] >= _num_valid_letters) word_elements[curr_pos] = _num_valid_letters - 1;
|
|
||||||
else word_elements[curr_pos] = (word_elements[curr_pos] + _num_valid_letters - 1) % _num_valid_letters;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
static uint32_t get_day_unix_time(void) {
|
static uint32_t get_day_unix_time(void) {
|
||||||
watch_date_time now = watch_rtc_get_date_time();
|
watch_date_time now = watch_rtc_get_date_time();
|
||||||
@ -295,14 +324,7 @@ static bool act_on_btn(wordle_state_t *state) {
|
|||||||
switch (state->curr_screen)
|
switch (state->curr_screen)
|
||||||
{
|
{
|
||||||
case SCREEN_RESULT:
|
case SCREEN_RESULT:
|
||||||
for (size_t i = 0; i < WORDLE_LENGTH; i++) {
|
show_start_of_attempt(state);
|
||||||
if (state->word_elements_result[i] != WORDLE_LETTER_CORRECT)
|
|
||||||
state->word_elements[i] = _num_valid_letters;
|
|
||||||
}
|
|
||||||
display_attempt(state->attempt);
|
|
||||||
display_all_letters(state);
|
|
||||||
state->position = get_first_pos(state->word_elements_result);
|
|
||||||
state->curr_screen = SCREEN_PLAYING;
|
|
||||||
return true;
|
return true;
|
||||||
case SCREEN_TITLE:
|
case SCREEN_TITLE:
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
@ -311,15 +333,24 @@ static bool act_on_btn(wordle_state_t *state) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
display_streak(state);
|
if (state->playing)
|
||||||
|
show_start_of_attempt(state);
|
||||||
|
else
|
||||||
|
display_streak(state);
|
||||||
return true;
|
return true;
|
||||||
case SCREEN_STREAK:
|
case SCREEN_STREAK:
|
||||||
|
#if USE_DAILY_STREAK
|
||||||
|
state->curr_day = get_day_unix_time();
|
||||||
|
#endif
|
||||||
reset_board(state);
|
reset_board(state);
|
||||||
return true;
|
return true;
|
||||||
case SCREEN_WIN:
|
case SCREEN_WIN:
|
||||||
case SCREEN_LOSE:
|
case SCREEN_LOSE:
|
||||||
display_title(state);
|
display_title(state);
|
||||||
return true;
|
return true;
|
||||||
|
case SCREEN_NO_DICT:
|
||||||
|
show_start_of_attempt(state);
|
||||||
|
return true;
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
case SCREEN_WAIT:
|
case SCREEN_WAIT:
|
||||||
display_title(state);
|
display_title(state);
|
||||||
@ -346,22 +377,19 @@ void wordle_face_setup(movement_settings_t *settings, uint8_t watch_face_index,
|
|||||||
void wordle_face_activate(movement_settings_t *settings, void *context) {
|
void wordle_face_activate(movement_settings_t *settings, void *context) {
|
||||||
(void) settings;
|
(void) settings;
|
||||||
wordle_state_t *state = (wordle_state_t *)context;
|
wordle_state_t *state = (wordle_state_t *)context;
|
||||||
movement_request_tick_frequency(FREQ);
|
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
if (state->prev_day <= (get_day_unix_time() + (60 *60 * 24))) state->streak = 0;
|
uint32_t now = get_day_unix_time() ;
|
||||||
|
if (state->prev_day <= (now + (60 *60 * 24))) state->streak = 0;
|
||||||
|
if (state->curr_day != now) state->playing = false;
|
||||||
#endif
|
#endif
|
||||||
if (state->curr_screen == SCREEN_TITLE)
|
movement_request_tick_frequency(FREQ);
|
||||||
display_title(state);
|
display_title(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||||
wordle_state_t *state = (wordle_state_t *)context;
|
wordle_state_t *state = (wordle_state_t *)context;
|
||||||
|
|
||||||
switch (event.event_type) {
|
switch (event.event_type) {
|
||||||
case EVENT_ACTIVATE:
|
|
||||||
if (state->curr_screen == SCREEN_PLAYING)
|
|
||||||
display_all_letters(state);
|
|
||||||
break;
|
|
||||||
case EVENT_TICK:
|
case EVENT_TICK:
|
||||||
switch (state->curr_screen)
|
switch (state->curr_screen)
|
||||||
{
|
{
|
||||||
@ -399,10 +427,17 @@ bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, voi
|
|||||||
if (act_on_btn(state)) break;
|
if (act_on_btn(state)) break;
|
||||||
display_letter(state, true);
|
display_letter(state, true);
|
||||||
if (state->word_elements[state->position] == _num_valid_letters) break;
|
if (state->word_elements[state->position] == _num_valid_letters) break;
|
||||||
|
state->playing = true;
|
||||||
state->position = get_next_pos(state->position, state->word_elements_result);
|
state->position = get_next_pos(state->position, state->word_elements_result);
|
||||||
if (state->position >= WORDLE_LENGTH) {
|
if (state->position >= WORDLE_LENGTH) {
|
||||||
|
bool in_dict = check_word_in_dict(state->word_elements);
|
||||||
|
if (!in_dict) {
|
||||||
|
display_not_in_dict(state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
bool exact_match = check_word(state);
|
bool exact_match = check_word(state);
|
||||||
if (exact_match) {
|
if (exact_match) {
|
||||||
|
state->playing = false;
|
||||||
state->curr_screen = SCREEN_WIN;
|
state->curr_screen = SCREEN_WIN;
|
||||||
state->streak++;
|
state->streak++;
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
@ -411,6 +446,7 @@ bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, voi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (state->attempt++ >= WORDLE_MAX_ATTEMPTS) {
|
if (state->attempt++ >= WORDLE_MAX_ATTEMPTS) {
|
||||||
|
state->playing = false;
|
||||||
state->curr_screen = SCREEN_LOSE;
|
state->curr_screen = SCREEN_LOSE;
|
||||||
state->streak = 0;
|
state->streak = 0;
|
||||||
break;
|
break;
|
||||||
@ -425,9 +461,12 @@ bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, voi
|
|||||||
state->position = get_prev_pos(state->position, state->word_elements_result);
|
state->position = get_prev_pos(state->position, state->word_elements_result);
|
||||||
break;
|
break;
|
||||||
case EVENT_LIGHT_BUTTON_DOWN:
|
case EVENT_LIGHT_BUTTON_DOWN:
|
||||||
break;
|
case EVENT_ACTIVATE:
|
||||||
case EVENT_TIMEOUT:
|
case EVENT_TIMEOUT:
|
||||||
|
break;
|
||||||
case EVENT_LOW_ENERGY_UPDATE:
|
case EVENT_LOW_ENERGY_UPDATE:
|
||||||
|
if (state->curr_screen == SCREEN_TITLE)
|
||||||
|
display_title(state);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return movement_default_loop_handler(event, settings);
|
return movement_default_loop_handler(event, settings);
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define WORDLE_LENGTH 5
|
#define WORDLE_LENGTH 5
|
||||||
#define WORDLE_MAX_ATTEMPTS 5
|
#define WORDLE_MAX_ATTEMPTS 6
|
||||||
#define USE_DAILY_STREAK true
|
#define USE_DAILY_STREAK true
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -55,6 +55,7 @@ typedef enum {
|
|||||||
#endif
|
#endif
|
||||||
SCREEN_WIN,
|
SCREEN_WIN,
|
||||||
SCREEN_LOSE,
|
SCREEN_LOSE,
|
||||||
|
SCREEN_NO_DICT,
|
||||||
SCREEN_COUNT
|
SCREEN_COUNT
|
||||||
} WordleScreen;
|
} WordleScreen;
|
||||||
|
|
||||||
@ -64,12 +65,14 @@ typedef struct {
|
|||||||
WordleLetterResult word_elements_result[WORDLE_LENGTH];
|
WordleLetterResult word_elements_result[WORDLE_LENGTH];
|
||||||
uint8_t attempt : 3;
|
uint8_t attempt : 3;
|
||||||
uint8_t position : 3;
|
uint8_t position : 3;
|
||||||
uint8_t unused : 2;
|
bool playing : 1;
|
||||||
|
bool unused : 1;
|
||||||
uint16_t curr_answer;
|
uint16_t curr_answer;
|
||||||
uint8_t streak;
|
uint8_t streak;
|
||||||
WordleScreen curr_screen;
|
WordleScreen curr_screen;
|
||||||
#if USE_DAILY_STREAK
|
#if USE_DAILY_STREAK
|
||||||
uint32_t prev_day;
|
uint32_t prev_day;
|
||||||
|
uint32_t curr_day;
|
||||||
#endif
|
#endif
|
||||||
} wordle_state_t;
|
} wordle_state_t;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user