Introduces watch/, a real Pebble watchapp (built via pebble build) that
build / build (push) Successful in 30s

shows the daily tarot/astrology reading on-device: persistence, reading
computation, and UI screens, driven by the existing engine/interpreter
code linked in unchanged where possible.

Required engine-side changes to make that linking work:
- A compact low-precision ephemeris (lowprec_ephemeris.c) replacing the
  vendored ~127KB Astronomy Engine, which doesn't fit the watch's ~64KB
  app budget.
- Hand-rolled sqrt/atan2/sin/cos replacements for that ephemeris and
  astro.c's Ascendant calculation - Pebble's statically-linked libm
  hard-faults on real hardware under this app's -fPIE link for all four.
- narrative.c/guidance.c refactored from FILE*/fprintf onto snprintf-
  based buffers, since Pebble's SDK blocks fprintf at compile time.
This commit is contained in:
ml
2026-07-14 17:10:22 +02:00
parent d9b6e2889b
commit 1a654da3e9
44 changed files with 1920 additions and 182 deletions
+20 -8
View File
@@ -1,12 +1,20 @@
#ifndef DECK_NARRATIVE_H
#define DECK_NARRATIVE_H
#include <stdio.h>
#include <stddef.h>
/* Header-only dependency on the engine, same policy as significance.h -
* see its comment for why. */
#include "../../engine/src/astro.h"
/* Generous upper bound on narrative_write()'s output (indent + house
* framing + base + harmonious/discordant addendum + newline) across
* every language this project ships a translation for - callers on
* constrained platforms (the watch) are free to size their own stack
* buffer smaller if they know their own strings are shorter; this is
* just a safe default for a caller that doesn't want to think about it. */
#define NARRATIVE_TEXT_MAX 512
/* Condensed, public-domain descriptions of what each transiting planet
* classically signifies, sourced from Sepharial's "Transits and
* Planetary Periods" (1920, public domain - res/Transits_and_Planetary_
@@ -22,15 +30,19 @@
* narrative.c is original, written for this project in a matching
* voice, not drawn from Sepharial.
*
* Prints a narrative sentence for `aspect`'s transiting planet to `out`,
* indented with `indent` and followed by a newline - or prints nothing
* if the source material has no text applicable to this planet/aspect
* Writes a narrative sentence for `aspect`'s transiting planet into
* `buf` (a caller-supplied buffer of `buf_size` bytes, always left
* null-terminated - NARRATIVE_TEXT_MAX is a safe size), indented with
* `indent` and followed by a newline - or writes an empty string if the
* source material has no text applicable to this planet/aspect
* combination (e.g. an exactly neutral conjunction to a planet whose
* only text is a "well/badly aspected" addendum, like the Sun). A
* conjunction is treated as neutral - neither the "harmonious" nor the
* "discordant" addendum is shown for it - since Sepharial's own text
* says a conjunction "takes the nature of what it conjoins," something
* this data doesn't model.
* this data doesn't model. Uses 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.
*
* `transiting_house` is the whole-sign house (1-12) the transiting
* planet currently occupies in the natal chart - i.e.
@@ -44,9 +56,9 @@
* Every string here is looked up via i18n_get() under "narrative.*"
* keys (engine/i18n's .lang files) before falling back to the English text
* baked into narrative.c, the same catalog tarot_data.c uses - so this
* text respects whatever --lang the caller loaded with i18n_load()
* (main.c does so before calling this). */
void narrative_print(FILE *out, const char *indent, const Aspect *aspect,
* text respects whatever --lang the caller loaded with i18n_load()/
* i18n_load_table() (main.c does so before calling this). */
void narrative_write(char *buf, size_t buf_size, const char *indent, const Aspect *aspect,
int transiting_house);
#endif