#ifndef DECK_GUIDANCE_H #define DECK_GUIDANCE_H #include /* Header-only dependency on the engine for struct/enum *definitions*, * same policy as narrative.h/significance.h - see their comments for * why. Unlike those, though, the root Makefile *does* link * engine/src/tarot_data.c's *implementation* (tarot_card_name()/ * tarot_card_meaning()) into the interpreter binary - a deliberate, * narrow exception; see the Makefile's own comment on * INTERP_TAROT_TEXT_OBJS for why that doesn't compromise this module's * independent testability. */ #include "../../engine/src/tarot.h" #include "significance.h" /* Generous upper bound on guidance_write()'s output (intro/stance line * + Attitude line + Outcome line, each ending in a newline, including * the longest tarot_card_meaning() strings) across every language this * project ships a translation for - see narrative.h's NARRATIVE_TEXT_MAX * for the same reasoning. */ #define GUIDANCE_TEXT_MAX 1024 /* Ties the day's single most significant transit * (interp->top_items[0]) to the Celtic Cross spread, and prints a short * paragraph of concrete guidance on how to meet the day - the "combined * storytelling" piece docs/reading.md flags as future work, now built. * Prints on every day, quiet or major, tailored to interp->day_level - * callers can invoke it unconditionally after every * interpret_daily_reading() call. * * The core guidance keys off two things: the character of the top * transit's aspect (harmonious/discordant/neutral, same classification * narrative.c uses) and whether the spread's Attitude position - Waite's * "Himself: his position or attitude in the circumstances", the * position most directly about how the reader is meeting the day - fell * upright or reversed. That crossing (3 x 2 = 6 combinations) is * original text written for this project, not drawn from Waite or * Sepharial, since neither source discusses combining astrology and * tarot; it stays valid regardless of the day's intensity. What *does* * vary with interp->day_level is only the sentence introducing the top * transit (e.g. "With Saturn as today's dominant influence" on a Major * day vs. "Saturn is only faintly active today, but for what it's * worth" on a Quiet one). A day with no aspects in orb at all * (interp->top_item_count == 0, always DAY_QUIET) has no transiting * planet to introduce, so it falls back to a stance keyed on the * Attitude card's orientation alone. * * The paragraph also names the Attitude and Outcome cards and, via * tarot_card_meaning(), states their actual Waite meaning for the * orientation they landed in (e.g. what Wheel of Fortune reversed * means) - not a duplicated table, the real thing, since tarot_data.c * is linked (see above). * * Every piece of this module's own text (stance/intro/no-transit/label * strings) is looked up via i18n_get() under "guidance.*" keys * (engine/i18n's .lang files) before falling back to the English text baked * into guidance.c, so it respects whatever --lang the caller loaded * with i18n_load()/i18n_load_table() (main.c does so before calling * this). The German guidance.intro.* templates are deliberately phrased * so the planet name placeholder is always the sentence's grammatical * subject (nominative case) across all four day levels - see * guidance.c's own comment on k_intro_fallback. * * Writes into `buf` (a caller-supplied buffer of `buf_size` bytes, * always left null-terminated - GUIDANCE_TEXT_MAX is a safe size) * instead of a FILE*, using only snprintf() internally (never * fprintf/sprintf/vsnprintf, all of which Pebble's SDK blocks at compile * time), so this function links into the watch app unchanged. */ void guidance_write(char *buf, size_t buf_size, const char *indent, const DailyInterpretation *interp, const CelticCrossSpread *spread); #endif