diff --git a/package.json b/package.json index c5534bd..a9520af 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "lint": "oxlint . && eslint . --cache", "lint:fix": "oxlint . --fix && eslint . --fix --cache", "format": "oxfmt --check src/", - "format:fix": "oxfmt src/" + "format:fix": "oxfmt src/", + "prolog": "swipl src/genealogy.pro" }, "dependencies": { "pinia": "^4.0.2", diff --git a/src/genealogy.pro b/src/genealogy.pro index cca0cba..d449966 100644 --- a/src/genealogy.pro +++ b/src/genealogy.pro @@ -199,6 +199,134 @@ couple(zeus, maia). couple(zeus, metis). couple(zeus, semele). +% --- figures with no family lines --- +figure(tartarus). +figure(eros). +figure(proteus). +figure(glaucos). +figure(scylla). +figure(argos). +figure(polydamas). +figure(alke). +figure(diomedes). +figure(palamedes). +figure(elpenor). +figure(eurylochos). +figure(eurycleia). + +:- table sibling/2. sibling(X, Y) :- parent(P, X), parent(P, Y), X \= Y. ancestor(X, Y) :- parent(X, Y). ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y). + +% ============================================================ +% Generation bands +% ============================================================ +:- discontiguous band_fixed/2. +:- discontiguous band_derived/2. + +% --- fixed: the primordials (closed set) --- +band_fixed(chaos, primordial). +band_fixed(gaia, primordial). +band_fixed(tartarus, primordial). +band_fixed(eros, primordial). +band_fixed(nyx, primordial). +band_fixed(erebus, primordial). +band_fixed(uranus, primordial). +band_fixed(pontus, primordial). +% the_fury has gaia + uranus as parents - Titan-shaped, but the Erinyes +% are the old night-dark order. +band_fixed(the_fury, primordial). + +% --- derived bands --- +% titan: born of gaia and uranus. +band_derived(X, titan) :- + parent(gaia, X), + parent(uranus, X). + +% olympian +band_derived(X, olympian) :- + parent(kronos, X), + parent(rhea, X). +% the younger ones need an olympian parent plus a second divine one. +band_derived(X, olympian) :- + parent(P, X), + band(P, olympian), + parent(Q, X), + Q \= P, + forall(parent(R, X), divine(R)). + +% --- fixed: olympians the rules can't reach --- +% dionysus: mortal mother (semele), but he sits on Olympus. +band_fixed(dionysus, olympian). +% aphrodite: single parent (uranus, via the sea-foam). +band_fixed(aphrodite, olympian). +% hephaestus: hera alone, no father. +band_fixed(hephaestus, olympian). + +% second_generation: the divine catch-all - Helios's line, the oceanids, +% atlas/prometheus, the sea line. +band_derived(X, second_generation) :- + parent(P, X), + parent(Q, X), + P @< Q, + divine(P), + divine(Q), + \+ band_derived(X, titan), + \+ band_derived(X, olympian). + +% astraios: only crius recorded (eurybia isn't in the file). +band_fixed(astraios, second_generation). +% neaera: parentless nymph, mother of lampetia and phaethousa by helios. +band_fixed(neaera, second_generation). +% proteus: the old man of the sea, no family lines recorded. +band_fixed(proteus, second_generation). + +% --- fixed: heroes & legends --- +% hero = a mortal with their own story cycle. +band_fixed(heracles, hero). +band_fixed(theseus, hero). +band_fixed(jason, hero). +band_fixed(achilles, hero). +band_fixed(odysseus, hero). +band_fixed(medea, hero). +band_fixed(daedalus, hero). + +% --- divine: used by the derived rules above --- +divine_band(primordial). +divine_band(titan). +divine_band(olympian). +divine_band(second_generation). + +divine(X) :- band(X, B), divine_band(B). + +% --- the bridge: rulings always win --- +:- table band/2. + +band(X, B) :- band_fixed(X, B). +band(X, B) :- band_derived(X, B), \+ band_fixed(X, _). +band(X, mortal) :- + known_figure(X), + \+ band_fixed(X, _), + \+ band_derived(X, _). + +% --- audits: run after every change --- +mentioned(X) :- figure(X). +mentioned(X) :- parent(X, _). +mentioned(X) :- parent(_, X). +mentioned(X) :- couple(X, _). +mentioned(X) :- couple(_, X). + +known_figure(X) :- distinct(X, mentioned(X)). + +% a known figure no band claims +unbanded(X) :- known_figure(X), \+ band(X, _). + +% a figure claimed by two different bands +bands_of(X, Bs) :- setof(B, band(X, B), Bs). +overbanded(X) :- known_figure(X), bands_of(X, Bs), Bs = [_, _ | _]. + +% a ruling naming a figure no other fact knows +phantom_ruling(X) :- band_fixed(X, _), \+ known_figure(X). + +band_count(B, N) :- setof(X, band(X, B), Xs), length(Xs, N).