Add core engine: tarot + astrology reading generator with CLI and i18n

Plain-C, dependency-free engine that produces a personalized daily
Celtic Cross tarot spread and natal-chart/transit astrology reading,
plus a standalone CLI (dist/deck-engine) and run.sh wrapper. Includes
English/German output via a simple key=value translation format, and
docs/diagrams describing the architecture and I/O.
This commit is contained in:
ml
2026-07-04 06:49:18 +02:00
commit e4ea31270f
59 changed files with 17134 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
#ifndef DECK_ASTRO_H
#define DECK_ASTRO_H
#include <time.h>
#define NUM_BODIES 10
#define MAX_ASPECTS 100
/* Named distinctly from Astronomy Engine's own astro_body_t constants
* (BODY_SUN, BODY_MOON, ...) to avoid colliding with them in astro.c,
* which includes both headers. */
typedef enum {
PLANET_SUN = 0,
PLANET_MOON,
PLANET_MERCURY,
PLANET_VENUS,
PLANET_MARS,
PLANET_JUPITER,
PLANET_SATURN,
PLANET_URANUS,
PLANET_NEPTUNE,
PLANET_PLUTO
} Body;
typedef enum {
SIGN_ARIES = 0,
SIGN_TAURUS,
SIGN_GEMINI,
SIGN_CANCER,
SIGN_LEO,
SIGN_VIRGO,
SIGN_LIBRA,
SIGN_SCORPIO,
SIGN_SAGITTARIUS,
SIGN_CAPRICORN,
SIGN_AQUARIUS,
SIGN_PISCES
} ZodiacSign;
typedef enum {
MOON_NEW = 0,
MOON_WAXING_CRESCENT,
MOON_FIRST_QUARTER,
MOON_WAXING_GIBBOUS,
MOON_FULL,
MOON_WANING_GIBBOUS,
MOON_LAST_QUARTER,
MOON_WANING_CRESCENT
} MoonPhaseName;
typedef enum {
ASPECT_CONJUNCTION = 0,
ASPECT_SEXTILE,
ASPECT_SQUARE,
ASPECT_TRINE,
ASPECT_OPPOSITION
} AspectType;
typedef struct {
double ecliptic_longitude; /* geocentric, degrees, [0, 360) */
ZodiacSign sign;
double degree_in_sign; /* [0, 30) */
} PlanetPosition;
typedef struct {
int year, month, day; /* birth date, local calendar */
int hour, minute; /* birth time, local clock */
double utc_offset_hours; /* local time = UTC + utc_offset_hours */
double latitude; /* degrees north positive */
double longitude; /* degrees east positive */
} BirthData;
typedef struct {
PlanetPosition bodies[NUM_BODIES];
double ascendant_longitude;
ZodiacSign houses[12]; /* houses[0] = sign of house 1 (whole-sign system) */
} NatalChart;
typedef struct {
Body transiting_planet;
Body natal_planet;
AspectType type;
double orb; /* how many degrees off exact, always >= 0 */
} Aspect;
typedef struct {
PlanetPosition bodies[NUM_BODIES];
MoonPhaseName moon_phase;
Aspect aspects[MAX_ASPECTS];
int aspect_count;
} DailyTransits;
void astro_compute_natal_chart(const BirthData *birth, NatalChart *out);
void astro_compute_daily_transits(time_t utc_moment, const NatalChart *natal,
DailyTransits *out);
const char *astro_body_name(Body body);
const char *astro_sign_name(ZodiacSign sign);
const char *astro_moon_phase_name(MoonPhaseName phase);
const char *astro_aspect_name(AspectType type);
#endif