Add narrative text and a day-significance rank to the interpreter

Each of the day's top significant transits now gets a short sentence
describing what it classically means and which area of life its house
governs, condensed from Sepharial's Transits and Planetary Periods
(1920, public domain) plus a small table of traditional house
significations. The day-level line also shows its rank out of the 4
defined levels, e.g. "Notable (2/4)". Docs (CLAUDE.md, README,
docs/input-output-format.md, docs/reading.md) updated to match,
including a full worked example in docs/reading.md.
This commit is contained in:
ml
2026-07-05 21:05:53 +02:00
parent 1136e3257a
commit 41422adf98
11 changed files with 476 additions and 41 deletions
+133
View File
@@ -0,0 +1,133 @@
#include "narrative.h"
#include <stdbool.h>
typedef struct {
const char *base; /* always relevant, may be "" (see the Sun) */
const char *harmonious; /* shown only under a trine/sextile; may be "" */
const char *discordant; /* shown only under a square/opposition; may be "" */
} TransitNarrative;
/* See narrative.h's doc comment for sourcing (Sepharial, "Transits and
* Planetary Periods", 1920, Chapter VIII) and the Moon/Pluto exception. */
static const TransitNarrative k_narratives[NUM_BODIES] = {
[PLANET_SUN] = {
.base = "",
.harmonious = "Benefits from superiors and advancement in your sphere of "
"life and work - honours, emoluments, and successful new "
"associations.",
.discordant = "Degradation and dishonour, loss of position, and adverse "
"judgement from superiors.",
},
[PLANET_MOON] = {
/* Original text, not from Sepharial - see narrative.h. */
.base = "Colours the everyday and domestic sphere of life, often "
"coinciding with the opening of new avenues.",
.harmonious = "These changes tend to be advantageous.",
.discordant = "These changes tend to be adverse, with some indisposition "
"or domestic friction.",
},
[PLANET_MERCURY] = {
.base = "Affects writings, journeys, commerce, and everyday activities - "
"a neutral messenger whose effect follows the nature of the "
"aspect it makes.",
.harmonious = "",
.discordant = "",
},
[PLANET_VENUS] = {
.base = "Brings domestic and social affairs to the fore - happiness, "
"comforts, and favours.",
.harmonious = "Success in love affairs and artistic pursuits is likely.",
.discordant = "Grief and disappointment are more likely.",
},
[PLANET_MARS] = {
.base = "A strenuous time of quarrels, contention, strife and anger, with "
"some risk of hurts or injuries depending on the sign it "
"occupies.",
.harmonious = "Can bring benefits from doctors, surgeons, or new projects "
"and enterprises.",
.discordant = "",
},
[PLANET_JUPITER] = {
.base = "Brings increase and expansion - fullness of fortune and health, "
"and a generally fortunate time.",
.harmonious = "",
.discordant = "",
},
[PLANET_SATURN] = {
.base = "Brings depression, stagnation, hindrances and obstacles, and "
"some deprivation of the usual benefits.",
.harmonious = "Favours from older connections and past associations are "
"still possible.",
.discordant = "",
},
[PLANET_URANUS] = {
.base = "Brings separations, estrangements, sudden dislocations and "
"violent upsets.",
.harmonious = "Success through official or civic channels, and "
"beneficial changes or appointments, are possible.",
.discordant = "",
},
[PLANET_NEPTUNE] = {
.base = "Brings a state of chaos and confusion - an involved, uncertain "
"condition of affairs, with plots, subtlety, or unseen "
"influences at work.",
.harmonious = "",
.discordant = "",
},
[PLANET_PLUTO] = {
/* Original text, not from Sepharial - see narrative.h. */
.base = "Brings deep, often hidden transformation - the surfacing or "
"dismantling of something that has outgrown its old form.",
.harmonious = "",
.discordant = "",
},
};
static bool aspect_is_harmonious(AspectType type) {
return type == ASPECT_TRINE || type == ASPECT_SEXTILE;
}
static bool aspect_is_discordant(AspectType type) {
return type == ASPECT_SQUARE || type == ASPECT_OPPOSITION;
}
/* Traditional whole-sign house significations - the "area of life" each
* house governs. This is centuries-old, uncredited astrological
* convention (the same status as the sign/aspect names already baked
* into engine/src/astro.c), not text drawn from Sepharial or any other
* single source. Indexed house - 1. */
static const char *const k_house_area[12] = {
"your sense of self, identity, and outward appearance",
"money, possessions, and personal values",
"communication, siblings, and everyday learning",
"home, family, and your roots",
"romance, creativity, and children",
"daily work, routine, and health",
"partnerships and close relationships",
"shared resources, intimacy, and transformation",
"travel, higher learning, and beliefs",
"career, reputation, and public standing",
"friendships, community, and hopes for the future",
"solitude, the subconscious, and hidden matters",
};
void narrative_print(FILE *out, const char *indent, const Aspect *aspect,
int transiting_house) {
const TransitNarrative *n = &k_narratives[aspect->transiting_planet];
const char *extra = "";
if (aspect_is_harmonious(aspect->type)) extra = n->harmonious;
else if (aspect_is_discordant(aspect->type)) extra = n->discordant;
if (n->base[0] == '\0' && extra[0] == '\0') return;
fprintf(out, "%s", indent);
if (transiting_house >= 1 && transiting_house <= 12) {
fprintf(out, "In matters of %s (house %d). ",
k_house_area[transiting_house - 1], transiting_house);
}
if (n->base[0] != '\0') fprintf(out, "%s", n->base);
if (extra[0] != '\0') fprintf(out, "%s%s", n->base[0] != '\0' ? " " : "", extra);
fprintf(out, "\n");
}