From 29d7d5bd409d1292049aaa7ceabb9186895bd968 Mon Sep 17 00:00:00 2001 From: Jeremy O'Brien Date: Thu, 12 Jan 2023 21:49:04 -0500 Subject: tarot: add full tarot deck as an option --- movement/watch_faces/complication/tarot_face.c | 85 ++++++++++++++++++++------ movement/watch_faces/complication/tarot_face.h | 20 ++++-- 2 files changed, 84 insertions(+), 21 deletions(-) diff --git a/movement/watch_faces/complication/tarot_face.c b/movement/watch_faces/complication/tarot_face.c index e583763c..04fcddef 100644 --- a/movement/watch_faces/complication/tarot_face.c +++ b/movement/watch_faces/complication/tarot_face.c @@ -65,9 +65,19 @@ static char *major_arcana[] = { "Jdgmnt", " World", }; -#define NUM_TAROT_CARDS (sizeof(major_arcana) / sizeof(*major_arcana)) +#define NUM_MAJOR_ARCANA (sizeof(major_arcana) / sizeof(*major_arcana)) -#define WORLD_CARD_INDEX (NUM_TAROT_CARDS - 1) +static char *suits[] = { + " wands", + " cups", + "swords", + " coins", +}; + +#define NUM_MINOR_ARCANA 56 +#define NUM_CARDS_PER_SUIT 14 + +#define NUM_TAROT_CARDS (NUM_MAJOR_ARCANA + NUM_MINOR_ARCANA) static void init_deck(tarot_state_t *state) { memset(state->drawn_cards, 0xff, sizeof(state->drawn_cards)); @@ -75,28 +85,58 @@ static void init_deck(tarot_state_t *state) { } static void tarot_display(tarot_state_t *state) { - char buf[10]; + char buf[12]; uint8_t card; bool flipped; + // deck is initialized; show current draw mode and return if (state->drawn_cards[0] == 0xff) { - /* deck is initialized; show current draw mode */ watch_clear_indicator(WATCH_INDICATOR_SIGNAL); - sprintf(buf, "%2d draWW", state->num_cards_to_draw); - watch_display_string(buf, 2); - watch_clear_pixel(2, 3); - watch_clear_pixel(1, 4); + if (state->major_arcana_only) { + sprintf(buf, "TA%2dn&ajor", state->num_cards_to_draw); + } else { + sprintf(buf, "TA%2d All", state->num_cards_to_draw); + } + watch_display_string(buf, 0); return; } - sprintf(buf, "%2d", state->current_card + 1); - watch_display_string(buf, 2); + // show a special status if we're looking at the first or last card in the spread + if (state->current_card == 0) { + sprintf(buf, "St"); + } else if (state->current_card == state->num_cards_to_draw - 1) { + sprintf(buf, "En"); + } else { + sprintf(buf, " "); + } + watch_display_string(buf, 0); + // now display the actual card card = state->drawn_cards[state->current_card]; flipped = (card & FLIPPED_MASK) ? true : false; // check flipped bit card &= ~FLIPPED_MASK; // remove the flipped bit - sprintf(buf, "%s", major_arcana[card]); - watch_display_string(buf, 4); + if (card < NUM_MAJOR_ARCANA) { + // major arcana + // make sure we're not showing a rank + watch_display_string(" ", 2); + + // card name + sprintf(buf, "%s", major_arcana[card]); + watch_display_string(buf, 4); + } else { + // minor arcana + uint8_t suit = (card - NUM_MAJOR_ARCANA) / NUM_CARDS_PER_SUIT; + uint8_t num = ((card - NUM_MAJOR_ARCANA) % NUM_CARDS_PER_SUIT) + 1; + + // show rank + sprintf(buf, "%2d", num); + watch_display_string(buf, 2); + + // suit + sprintf(buf, "%s", suits[suit]); + watch_display_string(buf, 4); + } + if (flipped) { watch_set_indicator(WATCH_INDICATOR_SIGNAL); } else { @@ -113,8 +153,12 @@ static uint8_t get_rand_num(uint8_t num_values) { #endif } -static uint8_t draw_one_card(void) { - return get_rand_num(NUM_TAROT_CARDS); +static uint8_t draw_one_card(tarot_state_t *state) { + if (state->major_arcana_only) { + return get_rand_num(NUM_MAJOR_ARCANA); + } else { + return get_rand_num(NUM_TAROT_CARDS); + } } static bool already_drawn(tarot_state_t *state, uint8_t drawn_card) { @@ -131,9 +175,9 @@ static void pick_cards(tarot_state_t *state) { uint8_t card; for (int i = 0; i < state->num_cards_to_draw; i++) { - card = draw_one_card(); + card = draw_one_card(state); while (already_drawn(state, card)) { - card = draw_one_card(); + card = draw_one_card(state); } card |= get_rand_num(2) << FLIPPED_BIT_POS; // randomly flip the card state->drawn_cards[i] = card; @@ -192,6 +236,7 @@ void tarot_face_activate(movement_settings_t *settings, void *context) { watch_display_string("TA", 0); init_deck(state); state->num_cards_to_draw = 3; + state->major_arcana_only = true; } bool tarot_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { @@ -226,7 +271,13 @@ bool tarot_face_loop(movement_event_t event, movement_settings_t *settings, void tarot_display(state); break; case EVENT_LIGHT_LONG_PRESS: - init_deck(state); + if (state->drawn_cards[0] == 0xff) { + // at main screen; cycle major arcana mode + state->major_arcana_only = !state->major_arcana_only; + } else { + // at card view screen; go back to draw screen + init_deck(state); + } tarot_display(state); break; case EVENT_ALARM_BUTTON_UP: diff --git a/movement/watch_faces/complication/tarot_face.h b/movement/watch_faces/complication/tarot_face.h index 3de5d019..00d08ff1 100644 --- a/movement/watch_faces/complication/tarot_face.h +++ b/movement/watch_faces/complication/tarot_face.h @@ -30,22 +30,33 @@ /* * Tarot card watch face * - * Draw from a deck of the 22 major arcana tarot cards. + * Draw from a deck of tarot cards. Can choose between major arcana only or + * entire deck. * * In tarot reading, a card orientation can be upright or inverted, and the * interpertation of the card can change depending on this state. This face * lights the alarm indicator to show when a card is inverted. Just ignore it * if you prefer not to deal with card inversions. * - * When "Draw" is shown: + * This face uses the terms "Wands", "Cups", "Swords" and "Coins" for the four + * suits, and numbers to represent the 14 ranked cards, with the cards 11-14 + * representing the Page, the Knight, the Queen, and King respectively. + * + * Default draw is a 3-card major arcana spread. + * + * To make it easier to keep track of where you are in the list of drawn cards, + * after drawing, "St" is shown for the 1st card in the spread and "En" is + * shown for the last card. + * + * When "Major" or "All" is shown: * - Light button: cycle # of cards to draw + * - Light button (long press): toggle between major arcana and all cards * - Alarm button: shuffle deck and draw cards * * After cards are drawn/showing: * - Light button: view the next drawn card * - Alarm button: shuffle and re-draw new cards - * - Light button (long press): go back to Draw screen, - * for choosing different # of cards to draw. + * - Light button (long press): go back to Draw screen, for choosing different draw parameters. */ #define MAX_CARDS_TO_DRAW 10 @@ -55,6 +66,7 @@ typedef struct { uint8_t current_card; uint8_t animation_frame; uint8_t num_cards_to_draw; + bool major_arcana_only; bool is_picking; } tarot_state_t; -- cgit v1.2.3 From 5e1f77213843d48a611f401dcffd098fb14d787d Mon Sep 17 00:00:00 2001 From: Jeremy O'Brien Date: Fri, 13 Jan 2023 08:06:29 -0500 Subject: tarot: reduce calls to watch_display_string() --- movement/watch_faces/complication/tarot_face.c | 30 +++++++++++--------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/movement/watch_faces/complication/tarot_face.c b/movement/watch_faces/complication/tarot_face.c index 04fcddef..2ebc2501 100644 --- a/movement/watch_faces/complication/tarot_face.c +++ b/movement/watch_faces/complication/tarot_face.c @@ -86,6 +86,7 @@ static void init_deck(tarot_state_t *state) { static void tarot_display(tarot_state_t *state) { char buf[12]; + char *start_end_string; uint8_t card; bool flipped; @@ -103,40 +104,33 @@ static void tarot_display(tarot_state_t *state) { // show a special status if we're looking at the first or last card in the spread if (state->current_card == 0) { - sprintf(buf, "St"); + start_end_string = "St"; } else if (state->current_card == state->num_cards_to_draw - 1) { - sprintf(buf, "En"); + start_end_string = "En"; } else { - sprintf(buf, " "); + start_end_string = " "; } - watch_display_string(buf, 0); - // now display the actual card + // figure out the card we're showing card = state->drawn_cards[state->current_card]; flipped = (card & FLIPPED_MASK) ? true : false; // check flipped bit card &= ~FLIPPED_MASK; // remove the flipped bit if (card < NUM_MAJOR_ARCANA) { // major arcana - // make sure we're not showing a rank - watch_display_string(" ", 2); - // card name - sprintf(buf, "%s", major_arcana[card]); - watch_display_string(buf, 4); + // show start/end, no rank, card name + sprintf(buf, "%s %s", start_end_string, major_arcana[card]); } else { // minor arcana uint8_t suit = (card - NUM_MAJOR_ARCANA) / NUM_CARDS_PER_SUIT; - uint8_t num = ((card - NUM_MAJOR_ARCANA) % NUM_CARDS_PER_SUIT) + 1; - - // show rank - sprintf(buf, "%2d", num); - watch_display_string(buf, 2); + uint8_t rank = ((card - NUM_MAJOR_ARCANA) % NUM_CARDS_PER_SUIT) + 1; - // suit - sprintf(buf, "%s", suits[suit]); - watch_display_string(buf, 4); + // show start/end, rank + suit + sprintf(buf, "%s%2d%s", start_end_string, rank, suits[suit]); } + watch_display_string(buf, 0); + if (flipped) { watch_set_indicator(WATCH_INDICATOR_SIGNAL); } else { -- cgit v1.2.3 From 3025a739565e86bc444a3ef55d1f42323aeb21dc Mon Sep 17 00:00:00 2001 From: Jeremy O'Brien Date: Fri, 13 Jan 2023 10:26:11 -0500 Subject: tarot: mode long press returns to face 0 --- movement/watch_faces/complication/tarot_face.c | 4 ++++ movement/watch_faces/complication/tarot_face.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/movement/watch_faces/complication/tarot_face.c b/movement/watch_faces/complication/tarot_face.c index 2ebc2501..fe29f8a7 100644 --- a/movement/watch_faces/complication/tarot_face.c +++ b/movement/watch_faces/complication/tarot_face.c @@ -287,6 +287,10 @@ bool tarot_face_loop(movement_event_t event, movement_settings_t *settings, void case EVENT_LOW_ENERGY_UPDATE: watch_display_string("SLEEP ", 4); break; + case EVENT_MODE_LONG_PRESS: + // since we ignore timeouts, provide a convenient way to jump back to the start + movement_move_to_face(0); + break; default: break; } diff --git a/movement/watch_faces/complication/tarot_face.h b/movement/watch_faces/complication/tarot_face.h index 00d08ff1..9dfe8b3d 100644 --- a/movement/watch_faces/complication/tarot_face.h +++ b/movement/watch_faces/complication/tarot_face.h @@ -48,6 +48,9 @@ * after drawing, "St" is shown for the 1st card in the spread and "En" is * shown for the last card. * + * At any point, the mode button can be held to return to your first configured + * watch face. + * * When "Major" or "All" is shown: * - Light button: cycle # of cards to draw * - Light button (long press): toggle between major arcana and all cards -- cgit v1.2.3