Создание простой астрологической программы на Pascal

Цель статьи – показать, как создать простую, но рабочую астрологическую программу, которая по дате, времени и месту рождения выводит знак зодиака, асцендент и расположение основных планет в знаках. Мы будем использовать классический язык Pascal (Free Pascal / Lazarus), потому что он прост в синтаксисе и позволяет быстро собрать консольное приложение.


Что нужно знать о астрологии

  • Знак зодиака – определяется положением Солнца в момент рождения.
  • Асцендент (восходящий знак) – определяется положением горизонта в момент рождения; нужен точный час и долгота места.
  • Планеты (Меркурий, Венера, Марс, Юпитер, Сатурн, Уран, Нептун, Плутон) – их положение в знаках влияет на характер и события.
  • Доминирование домов – в более сложных программах рассчитываются 12 домов, но в базовой версии ограничимся только знаками.

Для расчётов нам понадобится:

  1. Преобразование календарной даты в юлианский день (JD).
  2. Алгоритм расчёта положения Солнца и планет (можно использовать упрощённые формулы из книги «Astronomical Algorithms» Дж. Меркута).
  3. Определение знака по угловой позиции (0°–30° – Овен, 30°–60° – Телец и т.д.).

Инструменты и подготовка среды

  • Установите Free Pascal Compiler (FPC) или среду Lazarus.
  • Создайте новый проект Console Application.
  • Убедитесь, что в настройках проекта включён режим -Mdelphi (поддержка строковых функций).

Структура программы

Ниже – примерный план кода:

program AstroCalc;

uses
 SysUtils, Math;

type
 TPlanet = (Sun, Moon, Mercury, Venus, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto);
 TSign = (Aries, Taurus, Gemini, Cancer, Leo, Virgo,
 Libra, Scorpio, Sagittarius, Capricorn, Aquarius, Pisces);

const
 SignNames: array[TSign] of string = (
 'Овен', 'Телец', 'Близнецы', 'Рак', 'Лев', 'Дева',
 'Весы', 'Скорпион', 'Стрелец', 'Козерог', 'Водолей', 'Рыбы');
{---------------------- Вспомогательные функции ----------------------}
function DateToJulianDay(Y, M, D, H, Min, Sec: Integer): Double;
var
 A, B, JD: Double;
begin
 if M <= 2 then
 begin
 Y := Y, 1;
 M := M + 12;
 end;
 A := Int(Y / 100);
 B := 2 — A + Int(A / 4);
 JD := Int(365.25 * (Y + 4716)) + Int(30.6001 * (M + 1)) + D + B — 1524.5;
 JD := JD + (H + Min / 60 + Sec / 3600) / 24;
 Result := JD;
end;

function NormalizeAngle(A: Double): Double;
begin
 Result := A — 360 * Int(A / 360);
 if Result < 0 then Result := Result + 360;
end;

function GetSignByLongitude(Lon: Double): TSign;
begin
 Result := TSign(Trunc(Lon / 30));
end;

{---------------------- Расчёт положения Солнца ----------------------}
function SunLongitude(JD: Double): Double;
{ Упрощённый алгоритм: средняя аномалия + уравнение центра }
var
 T, M, C, L: Double;
begin
 T := (JD — 2451545.0) / 36525; { Юлианские столетия от J2000 }
 M := 357.52911 + 35999.05029 * T — 0.0001537 * T * T; { Средняя аномалия }
 M := NormalizeAngle(M);
 C := (1.914602 ― 0.004817 * T — 0.000014 * T * T) * Sin(DegToRad(M)) +
 (0;019993 — 0.000101 * T) * Sin(DegToRad(2 * M)) +
 0.000289 * Sin(DegToRad(3 * M));
 L := 280.46646 + 36000.76983 * T + 0.0003032 * T * T + C; { Геоцентрическая долгота }
 Result := NormalizeAngle(L);
end;
{---------------------- Расчёт асцендента ----------------------}
function Ascendant(JD: Double; Latitude, Longitude: Double): Double;
{ Формула по П. Сиделеву, упрощённая: нужны только часовой угол }
var
 T, LST, RA, Dec, H: Double;
begin
 T := (JD — 2451545.0) / 36525;
 LST := NormalizeAngle(280.46061837 + 360.98564736629 * (JD ― 2451545) +
 Longitude + 0.000387933 * T * T, T * T / 38710000);
 { Для упрощения берём среднее положение Солнца как RA и Dec }
 RA := SunLongitude(JD); { в градусах }
 Dec := 0; { приближение, достаточно для базовой версии }
 H := NormalizeAngle(LST — RA);
 Result := NormalizeAngle(ArcTan2d(Sin(DegToRad(H)),
 Cos(DegToRad(H)) * Sin(DegToRad(Latitude)) -
 Tan(DegToRad(Dec)) * Cos(DegToRad(Latitude))));
end;

{---------------------- Основная часть ----------------------}
var
 Year, Month, Day, Hour, Min, Sec: Integer;
 LatDeg, LonDeg: Double;
 JD, SunLon, AscLon: Double;
 SunSign, AscSign: TSign;
begin
 WriteLn('=== Астрологический калькулятор (Pascal) ===');
 Write('Введите дату рождения (ГГГГ ММ ДД): ');
 ReadLn(Year, Month, Day);
 Write('Введите время рождения (чч мм сс): ');
 ReadLn(Hour, Min, Sec);
 Write('Широта места (в градусах, + север,, юг): ');
 ReadLn(LatDeg);
 Write('Долгота места (в градусах, + восток, ― запад): ');
 ReadLn(LonDeg);

 JD := DateToJulianDay(Year, Month, Day, Hour, Min, Sec);

 SunLon := SunLongitude(JD);
 AscLon := Ascendant(JD, LatDeg, LonDeg);

 SunSign := GetSignByLongitude(SunLon);
 AscSign := GetSignByLongitude(AscLon);

 WriteLn;
 WriteLn('Результаты расчётов:');
 WriteLn('Солнце находится в знаке: ', SignNames[SunSign],
 ' (долгота ', FormatFloat('0.00', SunLon), '°)');
 WriteLn('Асцендент (восходящий знак): ', SignNames[AscSign],
 ' (долгота ', FormatFloat('0.00', AscLon), '°)');
 WriteLn;
 WriteLn('--- Примечание -------------------------------------------------');
 WriteLn('Для полного гороскопа следует добавить расчёт остальных планет,');
 WriteLn('домов, аспектов и использовать более точные эфемериды.');
 WriteLn('-----------------------------------------------------------------');
end.

Пояснение ключевых частей кода

Преобразование даты в юлианский день

Функция DateToJulianDay реализует формулу, предложенную Юлием Цезарем и уточнённую в Astronomical Algorithms. Юлианский день – это единый счётчик дней, позволяющий легко вычислять положения небесных тел.

Нормализация углов

Функция NormalizeAngle гарантирует, что любой угол будет в диапазоне 0°…360°. Это важно, потому что астрологические знаки делятся ровно на 30°.

Расчёт долготы Солнца

Мы используем упрощённый набор коэффициентов (средняя аномалия, уравнение центра). Для большинства любительских задач такой уровень точности (≈0,5°) достаточен.

Асцендент

Точный расчёт асцендента требует звёздных координат Солнца (RA, Dec) и местного звёздного времени (LST). В примере мы берём RA ≈ долготу Солнца, а Dec ≈ 0°, что упрощает формулу, но сохраняет смысл – асцендент будет в пределах нескольких градусов от реального.

Определение знака

Функция GetSignByLongitude делит угол на 30° и возвращает соответствующий элемент перечисления TSign. Массив SignNames хранит русские названия знаков.

Как расширить программу

  • Добавить расчёт остальных планет. Для каждой планеты нужны свои коэффициенты (ср. таблицы в «Astronomical Algorithms»).
  • Вычисление домов. Реализовать систему Плацидуса, Коха или равных дома.
  • Аспекты. Проверять угловые расстояния между планетами (0°, 60°, 90°, 120°, 180°) с допуском ±8°.
  • Графический вывод. В Lazarus можно построить круговую диаграмму (круг Зодиака) с помощью компонентов TCanvas.
  • База эфемерид. Подключить файл DE430 или использовать онлайн‑API (NASA JPL) для более точных расчётов.

Тестирование и проверка результатов

Для проверки возьмите известные даты рождения знаменитостей и сравните полученные знаки с публичными данными. Пример:

Время: 08:30
Место: Москва (55.75° N, 37.62° E)

Ожидаемый результат:
- Солнце в Водолее
- Асцендент в Овне (приблизительно)

Запустите программу, введите эти параметры и убедитесь, что вывод совпадает.

Полезные ресурсы

  • Free Pascal Compiler – официальная страница компилятора.
  • Книга Дж. Меркута Astronomical Algorithms – подробные формулы для расчётов.
  • Сайт astro.com – онлайн‑калькуляторы для сравнения.
  • Школа астрологии «Pro Astro» (см. информацию из интернета) – хорошие вводные курсы по астрологической теории.

Мы создали базовую астрологическую программу на Pascal, которая умеет:

  1. Преобразовывать дату и время в юлианский день.
  2. Вычислять долготу Солнца и определять знак зодиака.
  3. Оценивать асцендент (восходящий знак) по широте и долготе места рождения.

Эта основа легко расширяется: добавьте расчёт остальных планет, домов, аспектов и получите полноценный астрологический движок. Главное – помнить, что астрология – это искусство интерпретации, а программирование лишь предоставляет точные данные;

Удачной разработки!