home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume37 / astrolog / part04 < prev    next >
Encoding:
Text File  |  1993-05-18  |  59.6 KB  |  1,839 lines

  1. Newsgroups: comp.sources.misc
  2. From: astrolog@u.washington.edu (Astrolog)
  3. Subject: v37i073:  astrolog - Generation of astrology charts v3.05, Part04/12
  4. Message-ID: <1993May19.061600.11298@sparky.imd.sterling.com>
  5. X-Md4-Signature: 4bc3d1d99d40050f2a22ad575247c0a7
  6. Date: Wed, 19 May 1993 06:16:00 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: astrolog@u.washington.edu (Astrolog)
  10. Posting-number: Volume 37, Issue 73
  11. Archive-name: astrolog/part04
  12. Environment: UNIX, DOS, VMS
  13. Supersedes: astrolog: Volume 30, Issue 62-69
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 4 (of 12)."
  22. # Contents:  general.c options.c
  23. # Wrapped by pul@hardy on Sun May 16 22:23:16 1993
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'general.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'general.c'\"
  27. else
  28. echo shar: Extracting \"'general.c'\" \(16126 characters\)
  29. sed "s/^X//" >'general.c' <<'END_OF_FILE'
  30. X/*
  31. X** Astrolog (Version 3.05) File: general.c
  32. X**
  33. X** IMPORTANT: The planetary calculation routines used in this program
  34. X** have been Copyrighted and the core of this program is basically a
  35. X** conversion to C of the routines created by James Neely as listed in
  36. X** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  37. X** available from Matrix Software. The copyright gives us permission to
  38. X** use the routines for our own purposes but not to sell them or profit
  39. X** from them in any way.
  40. X**
  41. X** IN ADDITION: the graphics database and chart display routines used in
  42. X** this program are Copyright (C) 1991-1993 by Walter D. Pullen. Permission
  43. X** is granted to freely use and distribute these routines provided one
  44. X** doesn't sell, restrict, or profit from them in any way. Modification
  45. X** is allowed provided these notices remain with any altered or edited
  46. X** versions of the program.
  47. X*/
  48. X
  49. X#include "astrolog.h"
  50. X
  51. X
  52. X/*
  53. X*******************************************************************************
  54. X** General and numeric routines
  55. X*******************************************************************************
  56. X*/
  57. X
  58. X/* Swap two real float values. */
  59. X
  60. Xvoid SwapReal(d1, d2)
  61. Xreal *d1, *d2;
  62. X{
  63. X  real temp;
  64. X
  65. X  temp = *d1; *d1 = *d2; *d2 = temp;
  66. X}
  67. X
  68. X
  69. X/* Return the length of a string. */
  70. X
  71. Xint StringLen(line)
  72. Xchar *line;
  73. X{
  74. X  int i;
  75. X
  76. X  for (i = 0; *line++; i++)
  77. X    ;
  78. X  return i;
  79. X}
  80. X
  81. X
  82. X/* Determine the sign of a number: -1 if value negative, +1 if value */
  83. X/* positive, and 0 if it's zero.                                     */
  84. X
  85. Xreal Sgn(d)
  86. Xreal d;
  87. X{
  88. X  return d < 0.0 ? -1.0 : (d > 0.0 ? 1.0 : 0.0);
  89. X}
  90. X
  91. X
  92. X/* Convert an inputed fractional degrees/minutes value to a true decimal   */
  93. X/* degree quantity. For example, the user enters the decimal value "10.30" */
  94. X/* to mean 10 degrees and 30 minutes; this will return 10.5, i.e. 10       */
  95. X/* degrees and 30 minutes expressed as a floating point degree value.      */
  96. X
  97. Xreal DecToDeg(d)
  98. Xreal d;
  99. X{
  100. X  return Sgn(d)*(floor(dabs(d))+FRACT(dabs(d))*100.0/60.0);
  101. X}
  102. X
  103. X
  104. X/* Modulus function for floating point values. The modulus value itself */
  105. X/* has been specified earlier: it is usually either 360.0 or PI/2.0.    */
  106. X
  107. Xreal Mod(d)
  108. Xreal d;
  109. X{
  110. X  if (d > modulus)         /* In most cases, our value is only slightly */
  111. X    d -= modulus;          /* out of range, so we can test for it and   */
  112. X  else if (d < modulus)    /* avoid the more complicated arithmetic.    */
  113. X    d += modulus;
  114. X  if (d >= 0 && d < modulus)
  115. X    return d;
  116. X  return (d - floor(d/modulus)*modulus);
  117. X}
  118. X
  119. X
  120. X/* A similar modulus function: convert an integer to value from 1..12. */
  121. X
  122. Xint Mod12(i)
  123. Xint i;
  124. X{
  125. X  while (i > SIGNS)
  126. X    i -= SIGNS;
  127. X  while (i < 1)
  128. X    i += SIGNS;
  129. X  return i;
  130. X}
  131. X
  132. X
  133. X/* Return the shortest distance between two degrees in the zodiac. This is  */
  134. X/* normally their difference, but we have to check if near the Aries point. */
  135. X
  136. Xreal MinDistance(deg1, deg2)
  137. Xreal deg1, deg2;
  138. X{
  139. X  real i;
  140. X
  141. X  i = dabs(deg1-deg2);
  142. X  return i < 180 ? i : DEGREES - i;
  143. X}
  144. X
  145. X
  146. X/* Return the degree of the midpoint between two zodiac positions, making */
  147. X/* sure we return the true midpoint closest to the positions in question. */
  148. X
  149. Xreal Midpoint(deg1, deg2)
  150. Xreal deg1, deg2;
  151. X{
  152. X  real mid;
  153. X
  154. X  mid = (deg1+deg2)/2.0;
  155. X  return MinDistance(deg1, mid) < 90.0 ? mid : Mod(mid+180.0);
  156. X}
  157. X
  158. X
  159. X/* Given a planet and sign, determine whether: The planet rules the sign, */
  160. X/* the planet has its fall in the sign, the planet exalts in the sign, or */
  161. X/* is debilitated in the sign; and return an appropriate character.       */
  162. X
  163. Xchar Dignify(body, sign)
  164. Xint body, sign;
  165. X{
  166. X  if (body > OBJECTS)
  167. X    return ' ';
  168. X  if (ruler1[body] == sign || ruler2[body] == sign)
  169. X    return 'R';
  170. X  if (ruler1[body] == Mod12(sign+6) || ruler2[body] == Mod12(sign+6))
  171. X    return 'F';
  172. X  if (exalt[body] == sign)
  173. X    return 'e';
  174. X  if (exalt[body] == Mod12(sign+6))
  175. X    return 'd';
  176. X  return '-';
  177. X}
  178. X
  179. X
  180. X/* Determine the number of days in a particular month. The year is needed, */
  181. X/* too, because we have to check for leap years in the case of February.   */
  182. X
  183. Xint DayInMonth(month, year)
  184. Xint month, year;
  185. X{
  186. X  return (month == 9 || month == 4 || month == 6 || month == 11 ? 30 :
  187. X    (month != 2 ? 31 : 28 +
  188. X    (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))));
  189. X}
  190. X
  191. X
  192. X/* Given an aspect and two objects making that aspect with each other,   */
  193. X/* return the maximum orb allowed for such an aspect. Normally this only */
  194. X/* depends on the aspect itself, but some objects require narrow orbs,   */
  195. X/* and some allow wider orbs, so check for these cases.                  */
  196. X
  197. Xreal Orb(body1, body2, aspect)
  198. Xint body1, body2, aspect;
  199. X{
  200. X  real orb, i;
  201. X
  202. X  orb = aspectorb[aspect];
  203. X  i = body1 > BASE ? 2.0 : (body1 > OBJECTS ? 360.0 : planetorb[body1]);
  204. X  orb = MIN(orb, i);
  205. X  i = body2 > BASE ? 2.0 : (body2 > OBJECTS ? 360.0 : planetorb[body2]);
  206. X  orb = MIN(orb, i);
  207. X  if (body1 <= OBJECTS)
  208. X    orb += planetadd[body1];
  209. X  if (body2 <= OBJECTS)
  210. X    orb += planetadd[body2];
  211. X  return orb;
  212. X}
  213. X
  214. X
  215. X/*
  216. X*******************************************************************************
  217. X** IO routines
  218. X*******************************************************************************
  219. X*/
  220. X
  221. X/* Exit the program, and do any cleanup necessary. */
  222. X
  223. Xvoid Terminate(value)
  224. Xint value;
  225. X{
  226. X  if (ansi)
  227. X    printf("%c[0m", ESCAPE);    /* Get out of any Ansi color mode. */
  228. X  exit(value);
  229. X}
  230. X
  231. X
  232. X/* Simplification for a commonly printed error message. */
  233. X
  234. Xvoid TooFew(option)
  235. Xchar *option;
  236. X{
  237. X  fprintf(stderr, "%s: Too few options to switch -%s\n", appname, option);
  238. X  Terminate(1);
  239. X}
  240. X
  241. X
  242. X/* More simplifications for commonly printed error messages. */
  243. X
  244. Xvoid BadVal(option, value)
  245. Xchar *option;
  246. Xint value;
  247. X{
  248. X  fprintf(stderr, "%s: Value %d passed to switch -%s out of range.\n",
  249. X    appname, value, option);
  250. X  Terminate(1);
  251. X}
  252. X
  253. Xvoid BadVal2(option, value)
  254. Xchar *option;
  255. Xreal value;
  256. X{
  257. X  fprintf(stderr, "%s: Value %.0f passed to switch -%s out of range.\n",
  258. X    appname, value, option);
  259. X  Terminate(1);
  260. X}
  261. X
  262. X
  263. X/* A simple procedure used throughout Astrolog: Print a particular */
  264. X/* character on the screen 'n' times.                              */
  265. X
  266. Xvoid PrintTab(chr, count)
  267. Xchar chr;
  268. Xint count;
  269. X{
  270. X  int i;
  271. X
  272. X  for (i = 0; i < count; i++)
  273. X    putchar(chr);
  274. X}
  275. X
  276. X
  277. X/* Set an Ansi text color. */
  278. X
  279. Xvoid AnsiColor(col)
  280. Xint col;
  281. X{
  282. X  if (!ansi)
  283. X    return;
  284. X  printf("%c[", ESCAPE);
  285. X  if (col < 0)              /* Hack: Negative color means normal text. */
  286. X    putchar('0');
  287. X  else
  288. X    printf("%c;%d", '0' + (col > 7), 30 + (col & 7));
  289. X  putchar('m');
  290. X}
  291. X
  292. X
  293. X/* Nicely format the current longitude and latitude locations and return  */
  294. X/* them in a string. Various parts of the program display a chart header, */
  295. X/* and this allows the similar computations to be coded only once.        */
  296. X
  297. Xchar *StringLocation(Lon, Lat, norm)
  298. Xreal Lon, Lat, norm;
  299. X{
  300. X  static char loc[14];
  301. X  int i, j;
  302. X
  303. X  i = (int) (FRACT(dabs(Lon))*norm+0.1);
  304. X  j = (int) (FRACT(dabs(Lat))*norm+0.1);
  305. X  sprintf(loc, "%3.0f%c%d%d%c %2.0f%c%d%d%c",
  306. X    floor(dabs(Lon)), DEGR1, i/10, i%10, Lon < 0.0 ? 'E' : 'W',
  307. X    floor(dabs(Lat)), DEGR1, j/10, j%10, Lat < 0.0 ? 'S' : 'N');
  308. X  return loc;
  309. X}
  310. X
  311. X
  312. X/* Return the next value in a stream of values describing how to calculate */
  313. X/* the positions of the various planets.                                   */
  314. X
  315. Xreal ReadPlanetData(reset)
  316. Xint reset;
  317. X{
  318. X  static real *datapointer = planetdata;
  319. X
  320. X  if (!reset)
  321. X    return *datapointer++;
  322. X  datapointer = planetdata;
  323. X  return 0.0;
  324. X}
  325. X
  326. X
  327. X/* Similarly, return the next value in a stream of values describing the */
  328. X/* locations of the various fixed stars.                                 */
  329. X
  330. Xreal ReadStarData(reset)
  331. Xint reset;
  332. X{
  333. X  static real *datapointer = stardata;
  334. X
  335. X  if (!reset)
  336. X    return *datapointer++;
  337. X  datapointer = stardata;
  338. X  return 0.0;
  339. X}
  340. X
  341. X
  342. X#ifdef GRAPH
  343. X/* Another stream reader, this one is used by the globe drawing routine: */
  344. X/* for the next body of land/water, return its name (and color), its     */
  345. X/* longitude and latitude, and a vector description of its outline.      */
  346. X
  347. Xint ReadWorldData(nam, loc, lin)
  348. Xchar **nam, **loc, **lin;
  349. X{
  350. X  static char **datapointer = worlddata;
  351. X
  352. X  *loc = *datapointer++;
  353. X  *lin = *datapointer++;
  354. X  *nam = *datapointer++;
  355. X  if ((exdisplay & DASHXP0) && xbitmap)
  356. X    printf("%s\n", *nam+1);
  357. X  if (*loc[0])
  358. X    return TRUE;
  359. X  datapointer = worlddata;    /* Reset stream when no data left. */
  360. X  return FALSE;
  361. X}
  362. X#endif
  363. X
  364. X
  365. X/* Print a zodiac position on the screen. */
  366. X
  367. Xvoid PrintMinute(deg)
  368. Xreal deg;
  369. X{
  370. X  int sign, d, m;
  371. X
  372. X  if (!(operation & DASHs0)) {
  373. X
  374. X    /* Normally, we print out the position in degrees/sign/minutes format: */
  375. X
  376. X    deg = Mod(deg + 1.0/60.0/2.0);
  377. X    AnsiColor(elemansi[(int) (deg / 30.0) & 3]);
  378. X    sign = (int) (deg / 30.0);
  379. X    d = (int) deg - sign*30;
  380. X    m = (int) (FRACT(deg)*60.0);
  381. X    printf("%2d%c%c%c%s%d", d, SIGNAM(sign + 1), m < 10 ? "0" : "", m);
  382. X  } else {
  383. X
  384. X    /* However, if -s0 switch in effect, print position in hours/minutes: */
  385. X
  386. X    deg = Mod(deg + 1.0/4.0/2.0);
  387. X    AnsiColor(elemansi[(int) (deg / 30.0) & 3]);
  388. X    d = (int) (deg / 15.0);
  389. X    m = (int) ((deg - (real)d*15.0)*60.0/24.0);
  390. X    printf("%2dh,%s%dm", d, m < 10 ? "0" : "", m);
  391. X  }
  392. X  AnsiColor(-1);
  393. X}
  394. X
  395. X
  396. X/* This is similar to printing out a zodiac degree, but here we print out */
  397. X/* a (signed) declination value in degrees and minutes.                   */
  398. X
  399. Xvoid PrintAltitude(deg)
  400. Xreal deg;
  401. X{
  402. X  int d, m;
  403. X
  404. X  while (deg > 90.0)    /* Make sure declination value is from -90..+90 deg. */
  405. X    deg -= 180.0;
  406. X  while (deg < -90.0)
  407. X    deg += 180.0;
  408. X  putchar(deg < 0.0 ? '-' : '+');
  409. X  deg = dabs(deg) + 1.0/60.0/2.0;
  410. X  d = (int) deg;
  411. X  m = (int) (FRACT(deg)*60.0);
  412. X  printf("%2d%c%s%d'", d, DEGR2, m < 10 ? "0" : "", m);
  413. X}
  414. X
  415. X
  416. X/* Prompt the user for a floating point value, and make sure it conforms  */
  417. X/* to the specified bounds before returning it. If a non-numeric value is */
  418. X/* entered, then assume it's the name of a month, and try to convert it   */
  419. X/* to the appropriate number from 1 to 12; and also check for an "AM" or  */
  420. X/* "PM" suffix to hour values, and adjust the number appropriately.       */
  421. X
  422. Xreal Input(prompt, low, high)
  423. Xchar *prompt;
  424. Xreal low, high;
  425. X{
  426. X  char line[STRING], c;
  427. X  real x;
  428. X  int i, j;
  429. X
  430. X  while (TRUE) {
  431. X    printf("%s", prompt);
  432. X    AnsiColor(YELLOW);
  433. X    printf(" > ");
  434. X    AnsiColor(-1);
  435. X    if (gets(line) == (char *) NULL) {
  436. X      printf("\n%s terminated.\n", appname);
  437. X      Terminate(2);
  438. X    }
  439. X    i = StringLen(line);
  440. X    for (j = 0; j < i; j++)
  441. X      if (line[j] == ':')      /* Convert all colons in the */
  442. X        line[j] = '.';         /* entered line to periods.  */
  443. X    c = CAP(line[0]);
  444. X
  445. X    /* If they entered a string, then check to see if it's a month name. */
  446. X
  447. X    if (c >= 'A' && c <= 'Z') {
  448. X      switch (c) {
  449. X      case 'J': x = CAP(line[1]) == 'U' ?                   /* January,     */
  450. X        (CAP(line[2]) == 'L' ? 7.0 : 6.0) : 1.0; break;     /* June,July    */
  451. X      case 'F': x = 2.0; break;                             /* February     */
  452. X      case 'M': x = CAP(line[2]) == 'Y' ? 5.0 : 3.0; break; /* March,May    */
  453. X      case 'A': x = CAP(line[1]) == 'U' ? 8.0 : 4.0; break; /* April,August */
  454. X      case 'S': x = 9.0; break;                             /* September    */
  455. X      case 'O': x = 10.0; break;                            /* October      */
  456. X      case 'N': x = 11.0; break;                            /* November     */
  457. X      case 'D': x = 12.0; break;                            /* December     */
  458. X      default: x = 0.0;
  459. X      }
  460. X    } else {
  461. X      sscanf(line, "%lf", &x);    /* Convert entered line to number. */
  462. X      i = StringLen(line)-1;
  463. X      if (i > 0 && CAP(line[i]) == 'M')
  464. X        i--;
  465. X      if (i > 0) {
  466. X        c = CAP(line[i]);
  467. X        if (c == 'A')                    /* Adjust value appropriately */
  468. X          x = x >= 12.0 ? x-12.0 : x;    /* if 'AM' or 'PM' suffix.    */
  469. X        else if (c == 'P')
  470. X          x = x >= 12.0 ? x : x+12.0;
  471. X      }
  472. X    }
  473. X    if (x >= low && x <= high)
  474. X      return x;
  475. X    printf("Value out of range of from %.0f to %.0f.\n", low, high);
  476. X  }
  477. X}
  478. X
  479. X
  480. X/* This important procedure gets all the parameters defining the chart that  */
  481. X/* will be worked with later. Given a "filename", it gets from it all the    */
  482. X/* pertinent chart information. This is more than just reading from a file - */
  483. X/* the procedure also takes care of the cases of prompting the user for the  */
  484. X/* information and using the time functions to determine the date now - the  */
  485. X/* program considers these cases "virtual" files. Furthermore, when reading  */
  486. X/* from a real file, we have to check if it was written in the -o0 format.   */
  487. X
  488. Xvoid InputData(filename)
  489. Xchar *filename;
  490. X{
  491. X  FILE *data;
  492. X  char name[STRING], c;
  493. X  int i;
  494. X  real k, l, m;
  495. X#ifdef TIME
  496. X  struct tm curtime;
  497. X  long curtimer;
  498. X
  499. X  /* If we are to read from the file "now" then that means use the time */
  500. X  /* functions to calculate the present date and time.                  */
  501. X
  502. X  if (filename[0] == 'n' && filename[1] == 'o' && filename[2] == 'w' &&
  503. X      filename[3] == 0) {
  504. X    autom = 1;
  505. X    curtimer = (long) time((long *) 0);
  506. X    curtime = *localtime(&curtimer);
  507. X    M = (real) curtime.tm_mon + 1.0;
  508. X    D = (real) curtime.tm_mday;
  509. X    Y = (real) curtime.tm_year + 1900.0;
  510. X    F = (real) curtime.tm_hour + (real) curtime.tm_min / 100.0 +
  511. X      (real) curtime.tm_sec / 6000.0;
  512. X    X = defzone; L5 = deflong; LA = deflat;
  513. X    return;
  514. X  }
  515. X#endif
  516. X
  517. X  /* If we are to read from the file "tty" then that means prompt the user */
  518. X  /* for all the chart information.                                        */
  519. X
  520. X  if (filename[0] == 't' && filename[1] == 't' && filename[2] == 'y' &&
  521. X      filename[3] == 0) {
  522. X    AnsiColor(WHITE);
  523. X    printf("** %s version %s (%s) **\n", appname, VERSION, ADDRESS);
  524. X    AnsiColor(-1);
  525. X#ifdef SWITCHES
  526. X    printf("   Invoke as 'astrolog %cH' for brief list of command options.\n",
  527. X      DASH);
  528. X#endif
  529. X    M = Input("Enter month of birth (e.g. '7', 'Jul')", 1.0, 12.0);
  530. X    D = Input("Enter day   of birth (e.g. '1', '31') ", 1.0,
  531. X      (real) DayInMonth((int) M, 0));
  532. X    Y = Input("Enter year  of birth (e.g. '1993')    ", -5000.0, 5000.0);
  533. X    printf("Subtract one hour if Daylight Saving time in effect.\n");
  534. X    F = Input("Enter time  of birth (e.g. '18:30' '6:30pm')", -2.0, 24.0);
  535. X    printf("Negative values imply time zones east of Greenwich.\n");
  536. X    X = Input("Time zone in hours before GMT (5=Eastern, 8=Pacific)",
  537. X      -24.0, 24.0);
  538. X    printf("Negative values imply eastern and southern locations.\n");
  539. X    L5 = Input("Longitude west of place (i.e. DEG:MIN)", -180.0, 180.0);
  540. X    LA = Input("Latitude north of place (i.e. DEG:MIN)", -90.0, 90.0);
  541. X    putchar('\n');
  542. X    return;
  543. X  }
  544. X
  545. X  /* Now that the special cases are taken care of, we can assume we are */
  546. X  /* to read from a real file.                                          */
  547. X
  548. X  autom = 1;
  549. X  data = fopen(filename, "r");      /* Look for file in current directory. */
  550. X  if (data == NULL) {
  551. X    sprintf(name, "%s%s", DEFAULT_DIR, filename);    /* Look for file in   */
  552. X    data = fopen(name, "r");                         /* default directory. */
  553. X    if (data == NULL) {
  554. X      fprintf(stderr, "%s: File '%s' not found.\n", appname, filename);
  555. X      Terminate(1);
  556. X    }
  557. X  }
  558. X
  559. X  /* Read the chart parameters from a normal file. */
  560. X
  561. X  if ((c = getc(data)) != 'S') {
  562. X    ungetc(c, data);
  563. X    fscanf(data, "%lf%lf%lf%lf%lf%lf%lf", &M, &D, &Y, &F, &X, &L5, &LA);
  564. X
  565. X  /* Read the actual chart positions from a file produced with the -o0. */
  566. X
  567. X  } else {
  568. X
  569. X    /* Hack: A negative month value means the chart parameters are invalid, */
  570. X    /* hence -o0 is in effect and we can assume the chart positions are     */
  571. X    /* already in memory so we don't have to calculate them later.          */
  572. X
  573. X    M = -1.0;
  574. X    for (i = 1; i <= OBJECTS; i++) {
  575. X      fscanf(data, "%s%lf%lf%lf", name, &k, &l, &m);
  576. X      planet[i] = (l-1.0)*30.0+k+m/60.0;
  577. X      fscanf(data, "%s%lf%lf", name, &k, &l);
  578. X      planetalt[i] = k+l/60.0;
  579. X      ret[i] = DTOR(name[1] == 'D' ? 1.0 : -1.0);
  580. X    }
  581. X    for (i = 1; i <= SIGNS/2; i++) {
  582. X      fscanf(data, "%s%lf%lf%lf", name, &k, &l, &m);
  583. X      house[i+6] = Mod((house[i] = Mod((l-1.0)*30.0+k+m/60.0))+180.0);
  584. X    }
  585. X  }
  586. X  fclose(data);
  587. X}
  588. X
  589. X/* general.c */
  590. END_OF_FILE
  591. if test 16126 -ne `wc -c <'general.c'`; then
  592.     echo shar: \"'general.c'\" unpacked with wrong size!
  593. fi
  594. # end of 'general.c'
  595. fi
  596. if test -f 'options.c' -a "${1}" != "-c" ; then 
  597.   echo shar: Will not clobber existing file \"'options.c'\"
  598. else
  599. echo shar: Extracting \"'options.c'\" \(40939 characters\)
  600. sed "s/^X//" >'options.c' <<'END_OF_FILE'
  601. X/*
  602. X** Astrolog (Version 3.05) File: options.c
  603. X**
  604. X** IMPORTANT: The planetary calculation routines used in this program
  605. X** have been Copyrighted and the core of this program is basically a
  606. X** conversion to C of the routines created by James Neely as listed in
  607. X** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  608. X** available from Matrix Software. The copyright gives us permission to
  609. X** use the routines for our own purposes but not to sell them or profit
  610. X** from them in any way.
  611. X**
  612. X** IN ADDITION: the graphics database and chart display routines used in
  613. X** this program are Copyright (C) 1991-1993 by Walter D. Pullen. Permission
  614. X** is granted to freely use and distribute these routines provided one
  615. X** doesn't sell, restrict, or profit from them in any way. Modification
  616. X** is allowed provided these notices remain with any altered or edited
  617. X** versions of the program.
  618. X*/
  619. X
  620. X#include "astrolog.h"
  621. X
  622. X
  623. X/*
  624. X*******************************************************************************
  625. X** Display subroutines
  626. X*******************************************************************************
  627. X*/
  628. X
  629. X/* This is a subprocedure of CreateGrid() and CreateGridRelation(). Given */
  630. X/* two planets, determine what aspect, if any, is present between them,   */
  631. X/* and save the aspect name and orb in the specified grid cell.           */
  632. X
  633. Xvoid GetAspect(planet1, planet2, i, j)
  634. Xreal *planet1, *planet2;
  635. Xint i, j;
  636. X{
  637. X  int k;
  638. X  real l, m;
  639. X
  640. X  grid->n[i][j] = grid->v[i][j] = 0;
  641. X  l = MinDistance(planet2[i], planet1[j]);
  642. X  for (k = aspects; k >= 1; k--) {
  643. X    m = l-aspectangle[k];
  644. X    if (dabs(m) < Orb(i, j, k)) {
  645. X      grid->n[i][j] = k;
  646. X
  647. X      /* If -ga switch in effect, then change the sign of the orb to    */
  648. X      /* correspond to whether the aspect is applying or separating.    */
  649. X      /* To do this, we check the velocity vectors to see if the        */
  650. X      /* planets are moving toward, away, or are overtaking each other. */
  651. X
  652. X      if (exdisplay & DASHga)
  653. X        m = (ret[j]-ret[i] < 0 ? -1 : 1)*Sgn(planet1[j]-planet2[i])*
  654. X          (dabs(planet1[j]-planet2[i])>180.0 ? -1.0 : 1.0)*Sgn(m)*dabs(m);
  655. X          grid->v[i][j] = (int) (m*60.0);
  656. X    }
  657. X  }
  658. X}
  659. X
  660. X
  661. X/* Set up the aspect/midpoint grid. Allocate memory for this array, if not */
  662. X/* already done. Allocation is only done once, first time this is called.  */
  663. X
  664. Xvoid EnsureGrid()
  665. X{
  666. X  if (grid != NULL)
  667. X    return;
  668. X  Allocate(grid, sizeof(gridstruct), gridstruct PTR);
  669. X  if (grid == NULL
  670. X#ifndef NOPC
  671. X    /* For PC's the grid better not cross a segment boundary. */
  672. X    || HIWORD(LOWORD(grid) + sizeof(gridstruct)) > 0
  673. X#endif
  674. X    ) {
  675. X    fprintf(stderr, "%s: Out of memory for grid.\n", appname);
  676. X    Terminate(1);
  677. X  }
  678. X}
  679. X
  680. X
  681. X/* Fill in the aspect grid based on the aspects taking place among the */
  682. X/* planets in the present chart. Also fill in the midpoint grid.       */
  683. X
  684. Xvoid CreateGrid(acc)
  685. Xint acc;
  686. X{
  687. X  int i, j, k;
  688. X  real l;
  689. X
  690. X  EnsureGrid();
  691. X  for (j = 1; j <= total; j++) if (!ignore[j])
  692. X    for (i = 1; i <= total; i++) if (!ignore[i])
  693. X
  694. X      /* The parameter 'acc' determine what half of the grid is filled in */
  695. X      /* with the aspects and what half is filled in with the midpoints.  */
  696. X
  697. X      if (acc ? i > j : i < j)
  698. X        GetAspect(planet, planet, i, j);
  699. X      else if (acc ? i < j : i > j) {
  700. X        l = Mod(Midpoint(planet[i], planet[j])); k = (int)l;    /* Calculate */
  701. X        grid->n[i][j] = k/30+1;                                 /* midpoint. */
  702. X        grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0);
  703. X      } else {
  704. X        grid->n[i][j] = (int)planet[j]/30+1;
  705. X        grid->v[i][j] = (int)(planet[j]-(real)(grid->n[i][j]-1)*30.0);
  706. X      }
  707. X}
  708. X
  709. X
  710. X/* This is similar to the previous function; however, this time fill in the */
  711. X/* grid based on the aspects (or midpoints if 'acc' set) taking place among */
  712. X/* the planets in two different charts, as in the -g -r0 combination.       */
  713. X
  714. Xvoid CreateGridRelation(acc)
  715. Xint acc;
  716. X{
  717. X  int i, j, k;
  718. X  real l;
  719. X
  720. X  EnsureGrid();
  721. X  for (j = 1; j <= total; j++) if (!ignore[j])
  722. X    for (i = 1; i <= total; i++) if (!ignore[i])
  723. X      if (!acc)
  724. X        GetAspect(planet1, planet2, i, j);
  725. X      else {
  726. X        l = Mod(Midpoint(planet2[i], planet1[j])); k = (int)l;  /* Calculate */
  727. X        grid->n[i][j] = k/30+1;                                 /* midpoint. */
  728. X        grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0);
  729. X      }
  730. X}
  731. X
  732. X
  733. X/* Print an interpretation for a particular aspect in effect in a comparison */
  734. X/* relationship chart. This is called from the InterpretGridRelation and     */
  735. X/* the DisplayAspectRelation routines.                                       */
  736. X
  737. Xvoid InterpretAspectRelation(x, y)
  738. X{
  739. X  int n;
  740. X
  741. X  n = grid->n[y][x];
  742. X  if (n > 0 && n <= ASPECTI && x <= OBJECTS && y <= OBJECTS) {
  743. X    AnsiColor(aspectansi[n]);
  744. X    sprintf(string, "%s %s %s: Person1's", objectname[x],
  745. X      aspectname[n], objectname[y]);
  746. X    FieldWord(string); FieldWord(mindpart[x]);
  747. X    sprintf(string, interact[n],
  748. X      modifier[MIN(abs(grid->v[y][x])/150, 2)][n-1]);
  749. X    FieldWord(string);
  750. X    sprintf(string, "Person2's %s.", mindpart[y]); FieldWord(string);
  751. X    if (therefore[n][0]) {
  752. X      if (n != 1) {
  753. X        sprintf(string, "%s.", therefore[n]); FieldWord(string);
  754. X      } else
  755. X        FieldWord("These parts affect each other prominently.");
  756. X    }
  757. X    FieldWord("");
  758. X  }
  759. X}
  760. X
  761. X
  762. X/* Print the interpretation of each aspect in the relationship aspect grid, */
  763. X/* as specified with the -r0 -g -I switch combination.                      */
  764. X
  765. Xvoid InterpretGridRelation()
  766. X{
  767. X  int i, j;
  768. X
  769. X  for (i = 1; i <= OBJECTS; i++) if (!ignore[i])
  770. X    for (j = 1; j <= OBJECTS; j++) if (!ignore[j])
  771. X      InterpretAspectRelation(i, j);
  772. X}
  773. X
  774. X
  775. X/* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  776. X/* relationship chart. This is similar to the ChartGrid() routine; however, */
  777. X/* here we have both axes labeled with the planets for the two charts in    */
  778. X/* question, instead of just a diagonal down the center for only one chart. */
  779. X
  780. Xvoid DisplayGridRelation()
  781. X{
  782. X  int i, j, k, tot = total, temp;
  783. X
  784. X  if (interpret && !(exdisplay & DASHg0)) {
  785. X    InterpretGridRelation();
  786. X    return;
  787. X  }
  788. X  printf(" 2>");
  789. X  for (temp = 0, i = 1; i <= total; i++) if (!ignore[i]) {
  790. X    putchar(BOXV);
  791. X    AnsiColor(objectansi[i]);
  792. X    printf("%c%c%c", OBJNAM(i));
  793. X    AnsiColor(-1);
  794. X    temp++;
  795. X    if (column80 && temp >= 19) {
  796. X      tot = i;
  797. X      i = total;
  798. X    }
  799. X  }
  800. X  printf("\n1  ");
  801. X  for (i = 1; i <= tot; i++) if (!ignore[i]) {
  802. X    putchar(BOXV);
  803. X    AnsiColor(elemansi[(int)(planet2[i]/30.0) & 3]);
  804. X    printf("%2d%c", (int)planet2[i] % 30, DEGR2);
  805. X    AnsiColor(-1);
  806. X  }
  807. X  printf("\nV  ");
  808. X  for (i = 1; i <= tot; i++) if (!ignore[i]) {
  809. X    putchar(BOXV);
  810. X    temp = (int)(planet2[i]/30.0)+1;
  811. X    AnsiColor(elemansi[temp-1 & 3]);
  812. X    printf("%c%c%c", SIGNAM(temp));
  813. X    AnsiColor(-1);
  814. X  }
  815. X  putchar('\n');
  816. X  for (j = 1; j <= total; j++) if (!ignore[j])
  817. X    for (k = 1; k <= 4; k++) {
  818. X      if (k < 2)
  819. X        PrintTab(BOXH, 3);
  820. X      else if (k == 2) {
  821. X        AnsiColor(objectansi[j]);
  822. X        printf("%c%c%c", OBJNAM(j));
  823. X      } else {
  824. X        temp = (int)(planet1[j]/30.0)+1;
  825. X        AnsiColor(elemansi[temp-1 & 3]);
  826. X        if (k == 3)
  827. X          printf("%2d%c", (int)planet1[j] - (temp-1)*30, DEGR2);
  828. X        else
  829. X          printf("%c%c%c", SIGNAM(temp));
  830. X      }
  831. X      if (k > 1)
  832. X        AnsiColor(-1);
  833. X      for (i = 1; i <= tot; i++) if (!ignore[i]) {
  834. X        putchar(k < 2 ? BOXC : BOXV);
  835. X        temp = grid->n[i][j];
  836. X        if (k > 1)
  837. X          AnsiColor(exdisplay & DASHg0 ? elemansi[temp-1 & 3] :
  838. X            aspectansi[temp]);
  839. X        if (k < 2)
  840. X          PrintTab(BOXH, 3);
  841. X        else if (k == 2) {
  842. X          if (exdisplay & DASHg0)
  843. X            printf("%c%c%c", SIGNAM(temp));
  844. X          else
  845. X            printf("%s", aspectabbrev[temp]);
  846. X        } else if (k == 3) {
  847. X          if (exdisplay & DASHg0)
  848. X            printf("%2d%c", grid->v[i][j]/60, DEGR2);
  849. X          else
  850. X            if (grid->n[i][j]) {
  851. X              if (grid->v[i][j] < 600)
  852. X                printf("%c%2d", exdisplay & DASHga ?
  853. X                  (grid->v[i][j] < 0 ? 'a' : 's') :
  854. X                  (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  855. X              else
  856. X                printf("%3d", abs(temp)/60);
  857. X            } else
  858. X              printf("   ");
  859. X        } else {
  860. X          if (grid->n[i][j]) {
  861. X            temp = abs(grid->v[i][j])%60;
  862. X            printf("%d%d'", temp/10, temp%10);
  863. X          } else
  864. X            printf("   ");
  865. X        }
  866. X        AnsiColor(-1);
  867. X      }
  868. X      putchar('\n');
  869. X    }
  870. X}
  871. X
  872. X
  873. X/* Display all aspects between objects in the relationship comparison chart, */
  874. X/* one per line, in sorted order based on the total "power" of the aspects,  */
  875. X/* as specified with the -r0 -m0 switch combination.                         */
  876. X
  877. Xvoid DisplayAspectRelation()
  878. X{
  879. X  int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  880. X  real ip, jp;
  881. X
  882. X  while (TRUE) {
  883. X    phi = -1;
  884. X
  885. X    /* Search for the next most powerful aspect in the aspect grid. */
  886. X
  887. X    for (i = 1; i <= TOTAL; i++) if (!ignore[i])
  888. X      for (j = 1; j <= TOTAL; j++) if (!ignore[j])
  889. X        if (k = grid->n[i][j]) {
  890. X          ip = i <= OBJECTS ? objectinf[i] : 2.5;
  891. X          jp = j <= OBJECTS ? objectinf[j] : 2.5;
  892. X          p = (int) (aspectinf[k]*(ip+jp)/2.0*
  893. X            (1.0-dabs((real)(grid->v[i][j]))/60.0/aspectorb[k])*1000.0);
  894. X          if ((p < pcut || (p == pcut && (i > icut ||
  895. X            (i == icut && j > jcut)))) && p > phi) {
  896. X            ihi = i; jhi = j; phi = p; ahi = k;
  897. X          }
  898. X        }
  899. X    if (phi < 0)    /* Exit when no less powerful aspect found. */
  900. X      break;
  901. X    pcut = phi; icut = ihi; jcut = jhi;
  902. X    count++;                               /* Display the current aspect. */
  903. X    if (interpret)
  904. X      InterpretAspectRelation(jhi, ihi);
  905. X    else {
  906. X      printf("%3d:", count);
  907. X      AnsiColor(objectansi[jhi]);
  908. X      printf(" %7.7s ", objectname[jhi]);
  909. X      k = (int) planet1[jhi]/30;
  910. X      AnsiColor(elemansi[k & 3]);
  911. X      printf("%c%c%c%c%c", ret1[jhi] >= 0.0 ? '(' : '[', SIGNAM(k+1),
  912. X        ret1[jhi] >= 0.0 ? ')' : ']');
  913. X      AnsiColor(aspectansi[ahi]);
  914. X      printf(" %s with ", aspectabbrev[ahi]);
  915. X      k = (int) planet2[ihi]/30.0;
  916. X      AnsiColor(elemansi[k & 3]);
  917. X      printf("%c%c%c%c%c", ret2[ihi] >= 0.0 ? '(' : '[', SIGNAM(k+1),
  918. X        ret2[ihi] >= 0.0 ? ')' : ']');
  919. X      AnsiColor(objectansi[ihi]);
  920. X      printf(" %s", objectname[ihi]);
  921. X      PrintTab(' ', 11-StringLen(objectname[ihi]));
  922. X      AnsiColor(-1);
  923. X      k = grid->v[ihi][jhi];
  924. X      printf("- orb: %c%d,%d%d' - power:%6.2f\n",
  925. X        exdisplay & DASHga ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  926. X        abs(k)/60, abs(k)%60/10, abs(k)%60%10, (real) phi/1000.0);
  927. X    }
  928. X  }
  929. X}
  930. X
  931. X
  932. X/* Display locations of all midpoints between objects in the relationship */
  933. X/* comparison chart, one per line, in sorted zodiac order from zero Aries */
  934. X/* onward, as specified with the -r0 -m switch combination.               */
  935. X
  936. Xvoid DisplayMidpointRelation()
  937. X{
  938. X  int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, k, count = 0;
  939. X
  940. X  if (exdisplay & DASHm0) {
  941. X    DisplayAspectRelation();
  942. X    return;
  943. X  }
  944. X  while (TRUE) {
  945. X    mlo = 21600;
  946. X
  947. X    /* Search for the next closest midpoint farther down in the zodiac. */ 
  948. X
  949. X    for (i = 1; i <= TOTAL; i++) if (!ignore[i])
  950. X      for (j = 1; j <= TOTAL; j++) if (!ignore[j]) {
  951. X        m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  952. X        if ((m > mcut || (m == mcut && (i > icut ||
  953. X          (i == icut && j > jcut)))) && m < mlo) {
  954. X          ilo = i; jlo = j; mlo = m;
  955. X        }
  956. X      }
  957. X    if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  958. X      break;
  959. X    mcut = mlo; icut = ilo; jcut = jlo;
  960. X    count++;                               /* Display the current midpoint. */
  961. X    printf("%4d: ", count);
  962. X    PrintMinute((real) mlo/60.0);
  963. X    AnsiColor(objectansi[ilo]);
  964. X    printf(" %7.7s ", objectname[ilo]);
  965. X    k = (int) planet1[ilo]/30;
  966. X    AnsiColor(elemansi[k & 3]);
  967. X    printf("%c%c%c%c%c", ret1[ilo] >= 0.0 ? '(' : '[', SIGNAM(k+1),
  968. X      ret1[ilo] >= 0.0 ? ')' : ']');
  969. X    AnsiColor(WHITE);
  970. X    printf(" with ");
  971. X    k = (int) planet2[jlo]/30.0;
  972. X    AnsiColor(elemansi[k & 3]);
  973. X    printf("%c%c%c%c%c", ret2[jlo] >= 0.0 ? '(' : '[', SIGNAM(k+1),
  974. X      ret2[jlo] >= 0.0 ? ')' : ']');
  975. X    AnsiColor(objectansi[jlo]);
  976. X    printf(" %s", objectname[jlo]);
  977. X    PrintTab(' ', 11-StringLen(objectname[jlo]));
  978. X    AnsiColor(-1);
  979. X    printf("-%4d degree span.\n",
  980. X      (int) MinDistance(planet1[ilo], planet2[jlo]));
  981. X  }
  982. X}
  983. X
  984. X
  985. X/* Calculate any of the various kinds of relationship charts. This involves */
  986. X/* reading in and storing the planet and house positions for both charts,   */
  987. X/* and then combining them in the main single chart in the proper manner.   */
  988. X
  989. X#define DegToDec(A) Sgn(A)*(floor(dabs(A))+FRACT(dabs(A))*60/100.0)
  990. X
  991. Xvoid CastRelation()
  992. X{
  993. X  real zon, lon, lat, t1, t2, t;
  994. X  int i;
  995. X
  996. X  /* Read in the first chart. */
  997. X
  998. X  InputData(filename);
  999. X  zon = X; lon = L5; lat = LA;
  1000. X  t1 = CastChart(TRUE);
  1001. X  for (i = 1; i <= SIGNS; i++) {
  1002. X    house1[i] = house[i];
  1003. X    inhouse1[i] = inhouse[i];
  1004. X  }
  1005. X  for (i = 1; i <= total; i++) {
  1006. X    planet1[i] = planet[i];
  1007. X    planetalt1[i] = planetalt[i];
  1008. X    ret1[i] = ret[i];
  1009. X  }
  1010. X
  1011. X  /* Read in the second chart. */
  1012. X
  1013. X  InputData(filename2);
  1014. X  Mon = M; Day = D; Yea = Y; Tim = F; Zon = X; Lon = L5; Lat = LA;
  1015. X  t2 = CastChart(TRUE);
  1016. X  for (i = 1; i <= SIGNS; i++) {
  1017. X    house2[i] = house[i];
  1018. X    inhouse2[i] = inhouse[i];
  1019. X  }
  1020. X  for (i = 1; i <= total; i++) {
  1021. X    planet2[i] = planet[i];
  1022. X    planetalt2[i] = planetalt[i];
  1023. X    ret2[i] = ret[i];
  1024. X  }
  1025. X
  1026. X  /* Now combine the two charts based on what relation we are doing.   */
  1027. X  /* For the standard -r synastry chart, use the house cusps of chart1 */
  1028. X  /* and the planets positions of chart2.                              */
  1029. X
  1030. X  if (relation <= DASHr)
  1031. X    for (i = 1; i <= SIGNS; i++)
  1032. X      house[i] = house1[i];
  1033. X
  1034. X  /* For the -rc composite chart, take the midpoints of the planets/houses. */
  1035. X
  1036. X  else if (relation == DASHrc) {
  1037. X    for (i = 1; i <= total; i++) {
  1038. X      planet[i] = Midpoint(planet1[i], planet2[i]);
  1039. X      planetalt[i] = (planetalt1[i]+planetalt2[i])/2.0;
  1040. X      ret[i] = (ret1[i]+ret2[i])/2.0;
  1041. X    }
  1042. X    for (i = 1; i <= SIGNS; i++)
  1043. X      house[i] = Midpoint(house1[i], house2[i]);
  1044. X
  1045. X    /* Make sure we don't have any 180 degree errors in house cusp    */
  1046. X    /* complement pairs, which may happen if the cusps are far apart. */
  1047. X
  1048. X    for (i = 1; i <= SIGNS; i++)
  1049. X      if (MinDistance(house[10], Mod(house[i]-(real)(i+2)*30.0)) > 90.0)
  1050. X        house[i] = Mod(house[i]+180.0);
  1051. X
  1052. X  /* For the -rm time space midpoint chart, calculate the midpoint time and */
  1053. X  /* place between the two charts and then recast for the new chart info.   */
  1054. X
  1055. X  } else if (relation == DASHrm) {
  1056. X    T = (t1+t2)/2.0;
  1057. X    t = (T*36525.0)+0.5; JD = floor(t)+2415020.0; F = FRACT(t)*24.0;
  1058. X    X = (DecToDeg(zon)+DecToDeg(Zon))/2.0; X = DegToDec(X);
  1059. X    F = DecToDeg(F)-DecToDeg(X); F = DegToDec(F);
  1060. X    if (F < 0.0) {
  1061. X      F = DecToDeg(F)+24.0; F = DegToDec(F); JD -= 1.0;
  1062. X    }
  1063. X    JulianToMdy(JD, &M, &D, &Y);
  1064. X    L5 = (DecToDeg(lon)+DecToDeg(Lon))/2.0;
  1065. X    if (dabs(Lon-lon) > 180.0)
  1066. X      L5 = Mod(L5+180.0);
  1067. X    L5 = DegToDec(L5);
  1068. X    LA = (DecToDeg(lat)+DecToDeg(Lat))/2.0; LA = DegToDec(LA);
  1069. X    Mon = M; Day = D; Yea = Y; Tim = F; Zon = X; Lon = L5; Lat = LA;
  1070. X    CastChart(FALSE);
  1071. X
  1072. X  /* There are a couple of non-astrological charts, which only require the */
  1073. X  /* number of days that have passed between the two charts to be done.    */
  1074. X
  1075. X  } else
  1076. X    JD = floor((dabs(t2-t1)*36525.0)+0.5);
  1077. X  HousePlace();
  1078. X}
  1079. X
  1080. X
  1081. X/* This is a subprocedure of DisplayInDay(). Print the interpretation for */
  1082. X/* a particular instance of the various exciting events that can happen.  */ 
  1083. X
  1084. Xvoid InterpretInDay(source, aspect, dest)
  1085. Xint source, aspect, dest;
  1086. X{
  1087. X  if (source > OBJECTS || dest > OBJECTS)
  1088. X    return;
  1089. X
  1090. X  /* Interpret object changing direction. */
  1091. X
  1092. X  if (aspect == -2) {
  1093. X    AnsiColor(objectansi[source]);
  1094. X    FieldWord("Energy representing"); FieldWord(mindpart[source]);
  1095. X    FieldWord("will tend to manifest in");
  1096. X    FieldWord(dest ? "an independent, backward, introverted" :
  1097. X      "the standard, direct, open");
  1098. X    FieldWord("manner.");
  1099. X    FieldWord("");
  1100. X
  1101. X  /* Interpret object entering new sign. */
  1102. X
  1103. X  } else if (aspect == -1) {
  1104. X    AnsiColor(objectansi[source]);
  1105. X    FieldWord("Energy representing"); FieldWord(mindpart[source]);
  1106. X    sprintf(string, "will be %s,", description[dest]);
  1107. X    FieldWord(string);
  1108. X    sprintf(string, "and it %s.", desire[dest]); FieldWord(string);
  1109. X    FieldWord("");
  1110. X
  1111. X  /* Interpret aspect between transiting planets. */
  1112. X
  1113. X  } else if (aspect > 0 && aspect <= ASPECTI) {
  1114. X    AnsiColor(aspectansi[aspect]);
  1115. X    FieldWord("Energy representing"); FieldWord(mindpart[source]);
  1116. X    sprintf(string, interact[aspect], modifier[1][aspect-1]);
  1117. X    FieldWord(string);
  1118. X    sprintf(string, "energies of %s.", mindpart[dest]); FieldWord(string);
  1119. X    if (therefore[aspect][0]) {
  1120. X      if (aspect > 1) {
  1121. X        sprintf(string, "%s.", therefore[aspect]); FieldWord(string);
  1122. X      } else
  1123. X        FieldWord("They will affect each other prominently.");
  1124. X    }
  1125. X    FieldWord("");
  1126. X  }
  1127. X}
  1128. X
  1129. X
  1130. X/* Search through a day, and print out the times of exact aspects among the  */
  1131. X/* planets during that day, as specified with the -d switch, as well as the  */
  1132. X/* times when a planet changes sign or direction. To do this, we cast charts */
  1133. X/* for the beginning and end of the day, or a part of a day, and do a linear */
  1134. X/* equation check to see if anything exciting happens during the interval.   */
  1135. X/* (This is probably the single most complicated procedure in the program.)  */
  1136. X
  1137. Xvoid DisplayInDay(prog)
  1138. Xint prog;
  1139. X{
  1140. X  int time[MAXINDAY], source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY],
  1141. X    sign1[MAXINDAY], sign2[MAXINDAY], occurcount, division, div,
  1142. X    i, j, k, s1, s2;
  1143. X  real Day2, D1, D2, divsiz, d1, d2, e1, e2, f1, f2, g;
  1144. X
  1145. X  /* If parameter 'prog' is set, look for changes in a progressed chart. */
  1146. X
  1147. X  division = prog ? 1 : divisions;
  1148. X  divsiz = 24.0/ (real) division*60.0;
  1149. X
  1150. X  /* If -d0 in effect, then search through the whole month, day by day. */
  1151. X
  1152. X  if (exdisplay & DASHdm) {
  1153. X    D1 = 1.0;
  1154. X    if (prog && Mon2 == 0.0) {
  1155. X      Mon2 = 1.0; D2 = 365.0-28.0+(real)DayInMonth(2, (int) Yea2);
  1156. X    } else D2 = (real)
  1157. X      DayInMonth((int) (prog ? Mon2 : Mon), (int) (prog ? Yea2 : Yea));
  1158. X  } else
  1159. X    D1 = D2 = Day;
  1160. X
  1161. X  /* Start searching the day or days in question for exciting stuff. */
  1162. X
  1163. X  for (Day2 = D1; Day2 <= D2; Day2 += 1.0) {
  1164. X    occurcount = 0;
  1165. X
  1166. X    /* Cast chart for beginning of day and store it for future use. */
  1167. X
  1168. X    M = Mon; D = Day2; Y = Yea; F = 0.0; X = Zon; L5 = Lon; LA = Lat;
  1169. X    if (progress = prog) {
  1170. X      Jdp = MdyToJulian(Mon2, D, Yea2);
  1171. X      M = Mon; D = Day; Y = Yea; F = Tim; X = Zon; L5 = Lon; LA = Lat;
  1172. X    }
  1173. X    CastChart(TRUE);
  1174. X    for (i = 1; i <= SIGNS; i++) {
  1175. X      house2[i] = house[i];
  1176. X      inhouse2[i] = inhouse[i];
  1177. X    }
  1178. X    for (i = 1; i <= total; i++) {
  1179. X      planet2[i] = planet[i];
  1180. X      ret2[i] = ret[i];
  1181. X    }
  1182. X
  1183. X    /* Now divide the day into segments and search each segment in turn. */
  1184. X    /* More segments == slower, but slightly better time accuracy.       */
  1185. X
  1186. X    for (div = 1; div <= division; div++) {
  1187. X
  1188. X      /* Cast the chart for the ending time of the present segment. The   */
  1189. X      /* beginning time chart is copied from the previous end time chart. */
  1190. X
  1191. X      M = Mon; D = Day2; Y = Yea; X = Zon; L5 = Lon; LA = Lat;
  1192. X      F = 24.0*div/ (real) division;
  1193. X      if (prog) {
  1194. X        Jdp = MdyToJulian(Mon2, D+1.0, Yea2);
  1195. X        M = Mon; D = Day; Y = Yea; F = Tim; X = Zon; L5 = Lon; LA = Lat;
  1196. X      }
  1197. X      CastChart(TRUE);
  1198. X      for (i = 1; i <= SIGNS; i++) {
  1199. X        house1[i] = house2[i]; inhouse1[i] = inhouse2[i];
  1200. X        house2[i] = house[i];  inhouse2[i] = inhouse[i];
  1201. X      }
  1202. X      for (i = 1; i <= total; i++) {
  1203. X        planet1[i] = planet2[i]; ret1[i] = ret2[i];
  1204. X        planet2[i] = planet[i];  ret2[i] = ret[i];
  1205. X      }
  1206. X
  1207. X      /* Now search through the present segment for anything exciting. */
  1208. X
  1209. X      for (i = 1; i <= total; i++) if (!ignore[i] &&
  1210. X        (prog || i <= THINGS || i > C_HI)) {
  1211. X        s1 = (int) planet1[i] / 30;
  1212. X        s2 = (int) planet2[i] / 30;
  1213. X
  1214. X        /* Does the current planet change into the next or previous sign? */
  1215. X
  1216. X        if (!ignore[i] && s1 != s2) {
  1217. X          source[occurcount] = i;
  1218. X          aspect[occurcount] = -1;
  1219. X          dest[occurcount] = s2+1;
  1220. X          time[occurcount] = (int) (MinDistance(planet1[i],
  1221. X            (real) (ret1[i] >= 0.0 ? s2 : s1) * 30.0) /
  1222. X            MinDistance(planet1[i], planet2[i])*divsiz) +
  1223. X            (int) ((real) (div-1)*divsiz);
  1224. X          sign1[occurcount] = sign2[occurcount] = s1+1;
  1225. X          occurcount++;
  1226. X        }
  1227. X
  1228. X        /* Does the current planet go retrograde or direct? */
  1229. X
  1230. X        if (!ignore[i] && (ret1[i] < 0.0) != (ret2[i] < 0.0)) {
  1231. X          source[occurcount] = i;
  1232. X          aspect[occurcount] = -2;
  1233. X          dest[occurcount] = ret2[i] < 0.0;
  1234. X          time[occurcount] = (int) (dabs(ret1[i])/(dabs(ret1[i])+dabs(ret2[i]))
  1235. X            *divsiz) + (int) ((real) (div-1)*divsiz);
  1236. X          sign1[occurcount] = sign2[occurcount] = s1+1;
  1237. X          occurcount++;
  1238. X        }
  1239. X
  1240. X        /* Now search for anything making an aspect to the current planet. */
  1241. X
  1242. X        for (j = i+1; j <= total; j++) if (!ignore[j] &&
  1243. X          (prog || j <= THINGS || j > C_HI))
  1244. X          for (k = 1; k <= aspects; k++) {
  1245. X            d1 = planet1[i]; d2 = planet2[i];
  1246. X            e1 = planet1[j]; e2 = planet2[j];
  1247. X            if (MinDistance(d1, d2) < MinDistance(e1, e2)) {
  1248. X              SwapReal(&d1, &e1);
  1249. X              SwapReal(&d2, &e2);
  1250. X            }
  1251. X
  1252. X            /* We are searching each aspect in turn. Let's subtract the  */
  1253. X            /* size of the aspect from the angular difference, so we can */
  1254. X            /* then treat it like a conjunction.                         */
  1255. X
  1256. X            if (MinDistance(e1, Mod(d1-aspectangle[k])) <
  1257. X                MinDistance(e2, Mod(d2+aspectangle[k]))) {
  1258. X              e1 = Mod(e1+aspectangle[k]);
  1259. X              e2 = Mod(e2+aspectangle[k]);
  1260. X            } else {
  1261. X              e1 = Mod(e1-aspectangle[k]);
  1262. X              e2 = Mod(e2-aspectangle[k]);
  1263. X            }
  1264. X
  1265. X            /* Check to see if the aspect actually occurs during our    */
  1266. X            /* segment, making sure we take into account if one or both */
  1267. X            /* planets are retrograde or if they cross the Aries point. */
  1268. X
  1269. X            f1 = e1-d1;
  1270. X            if (dabs(f1) > 180.0)
  1271. X              f1 -= Sgn(f1)*DEGREES;
  1272. X            f2 = e2-d2;
  1273. X            if (dabs(f2) > 180.0)
  1274. X              f2 -= Sgn(f2)*DEGREES;
  1275. X            if (MinDistance(Midpoint(d1, d2), Midpoint(e1, e2)) < 90.0 &&
  1276. X              Sgn(f1) != Sgn(f2)) {
  1277. X              source[occurcount] = i;
  1278. X              aspect[occurcount] = k;
  1279. X              dest[occurcount] = j;
  1280. X
  1281. X              /* Horray! The aspect occurs sometime during the interval.   */
  1282. X              /* Now we just have to solve an equation in two variables to */
  1283. X              /* find out where the "lines" cross, i.e. the aspect's time. */
  1284. X
  1285. X              f1 = d2-d1;
  1286. X              if (dabs(f1) > 180.0)
  1287. X                f1 -= Sgn(f1)*DEGREES;
  1288. X              f2 = e2-e1;
  1289. X              if (dabs(f2) > 180.0)
  1290. X                f2 -= Sgn(f2)*DEGREES;
  1291. X              g = (dabs(d1-e1) > 180.0 ?
  1292. X                (d1-e1)-Sgn(d1-e1)*DEGREES : d1-e1)/(f2-f1);
  1293. X                time[occurcount] = (int) (g*divsiz) +
  1294. X                (int) ((real) (div-1)*divsiz);
  1295. X              sign1[occurcount] = (int) (Mod(planet1[i]+
  1296. X                Sgn(planet2[i]-planet1[i])*
  1297. X                (dabs(planet2[i]-planet1[i]) > 180.0 ? -1 : 1)*
  1298. X                dabs(g)*MinDistance(planet1[i], planet2[i]))/30.0)+1;
  1299. X              sign2[occurcount] = (int) (Mod(planet1[j]+
  1300. X                Sgn(planet2[j]-planet1[j])*
  1301. X                (dabs(planet2[j]-planet1[j]) > 180.0 ? -1 : 1)*
  1302. X                dabs(g)*MinDistance(planet1[j], planet2[j]))/30.0)+1;
  1303. X              occurcount++;
  1304. X            }
  1305. X          }
  1306. X      }
  1307. X    }
  1308. X
  1309. X    /* After all the aspects, etc, in the day have been located, sort   */
  1310. X    /* them by time at which they occur, so we can print them in order. */
  1311. X
  1312. X    for (i = 1; i < occurcount; i++) {
  1313. X      j = i-1;
  1314. X      while (j >= 0 && time[j] > time[j+1]) {
  1315. X        SWAP(source[j], source[j+1]);
  1316. X        SWAP(aspect[j], aspect[j+1]);
  1317. X        SWAP(dest[j], dest[j+1]);
  1318. X        SWAP(time[j], time[j+1]);
  1319. X        SWAP(sign1[j], sign1[j+1]); SWAP(sign2[j], sign2[j+1]);
  1320. X        j--;
  1321. X      }
  1322. X    }
  1323. X
  1324. X    /* Finally, loop through and display each aspect and when it occurs. */
  1325. X
  1326. X    for (i = 0; i < occurcount; i++) {
  1327. X      s1 = time[i]/60;
  1328. X      s2 = time[i]-s1*60;
  1329. X      s1 = Mod12(s1);
  1330. X      j = (int) Day2;
  1331. X      if (prog) {
  1332. X        g = Mon2;
  1333. X        while (j > (k = DayInMonth((int) g, (int) Yea2))) {
  1334. X          j -= k;
  1335. X          g += 1.0;
  1336. X        }
  1337. X      }
  1338. X      printf("%2.0f/%d%d/%4.0f ",
  1339. X        prog ? g : Mon, j/10, j%10, prog ? Yea2 : Yea);  /* Print date. */
  1340. X      printf("%2d:%d%d%cm ",
  1341. X        s1, s2/10, s2%10, time[i] < 12*60 ? 'a' : 'p');  /* Print time. */
  1342. X      AnsiColor(objectansi[source[i]]);
  1343. X      if (prog)
  1344. X        printf("progr ");
  1345. X      printf("%7.7s", objectname[source[i]]);
  1346. X      AnsiColor(elemansi[sign1[i]-1 & 3]);
  1347. X      j = (ret1[source[i]] < 0.0)+(ret2[source[i]] < 0.0);
  1348. X      printf(" %c%c%c%c%c", j < 1 ? '(' : (j > 1 ? '[' : '<'),
  1349. X        SIGNAM(sign1[i]), j < 1 ? ')' : (j > 1 ? ']' : '>'));
  1350. X      if (aspect[i] > 0)
  1351. X        AnsiColor(aspectansi[aspect[i]]);
  1352. X      else
  1353. X        AnsiColor(WHITE);
  1354. X      if (aspect[i] == -1)
  1355. X        printf(" --> ");
  1356. X      else if (aspect[i] == -2)
  1357. X        printf(" S/%c", dest[i] ? 'R' : 'D');   /* Print a direction change. */
  1358. X      else
  1359. X        printf(" %s ", aspectabbrev[aspect[i]]);
  1360. X      if (aspect[i] == -1) {
  1361. X        AnsiColor(elemansi[dest[i]-1 & 3]);
  1362. X        printf("%s", signname[dest[i]]);
  1363. X        if (source[i] == 1) {
  1364. X          if (dest[i] == 1)
  1365. X            printf(" (Vernal Equinox)");      /* If the Sun changes sign, */
  1366. X          else if (dest[i] == 4)              /* then print out if this   */
  1367. X            printf(" (Summer Solstice)");     /* is a season change.      */
  1368. X          else if (dest[i] == 7)
  1369. X            printf(" (Autumnal Equinox)");
  1370. X          else if (dest[i] == 10)
  1371. X            printf(" (Winter Solstice)");
  1372. X        }
  1373. X      } else if (aspect[i] > 0) {
  1374. X        AnsiColor(elemansi[sign2[i]-1 & 3]);
  1375. X        j = (ret1[dest[i]] < 0.0)+(ret2[dest[i]] < 0.0);
  1376. X        printf("%c%c%c%c%c ",
  1377. X          j < 1 ? '(' : (j > 1 ? '[' : '<'), SIGNAM(sign2[i]),
  1378. X          j < 1 ? ')' : (j > 1 ? ']' : '>'));
  1379. X        AnsiColor(objectansi[dest[i]]);
  1380. X        printf("%s", objectname[dest[i]]);
  1381. X        if (source[i] == 1 && dest[i] == 2) {
  1382. X          if (aspect[i] <= 3)
  1383. X            AnsiColor(WHITE);
  1384. X          if (aspect[i] == 1)
  1385. X            printf(" (New Moon)");     /* Print out if the present */
  1386. X          else if (aspect[i] == 2)     /* aspect is a New, Full,   */
  1387. X            printf(" (Full Moon)");    /* or Half Moon.            */
  1388. X          else if (aspect[i] == 3)
  1389. X            printf(" (Half Moon)");
  1390. X        }
  1391. X      }
  1392. X      putchar('\n');
  1393. X      if (interpret)
  1394. X        InterpretInDay(source[i], aspect[i], dest[i]);
  1395. X      AnsiColor(-1);
  1396. X    }
  1397. X  }
  1398. X}
  1399. X
  1400. X
  1401. X/* This is a subprocedure of DisplayTransit(). Print the interpretation for */
  1402. X/* a particular transit of a planet to a natal object of a chart.           */ 
  1403. X
  1404. Xvoid InterpretTransit(source, aspect, dest)
  1405. Xint source, aspect, dest;
  1406. X{
  1407. X  if (source <= OBJECTS && dest <= OBJECTS) {
  1408. X    AnsiColor(aspectansi[aspect]);
  1409. X    FieldWord("Energy representing"); FieldWord(mindpart[source]);
  1410. X    sprintf(string, interact[aspect], modifier[1][aspect-1]);
  1411. X    FieldWord(string);
  1412. X    sprintf(string, "the person's %s.", mindpart[dest]); FieldWord(string);
  1413. X    if (therefore[aspect][0]) {
  1414. X      if (aspect > 1) {
  1415. X        sprintf(string, "%s.", therefore[aspect]); FieldWord(string);
  1416. X      } else
  1417. X        FieldWord("This part of their psyche will be strongly influenced.");
  1418. X    }
  1419. X    FieldWord("");
  1420. X  }
  1421. X}
  1422. X
  1423. X
  1424. X/* Search through a month, and print out the times of exact transits where   */
  1425. X/* planets in the time frame make aspect to the planets in some other chart, */
  1426. X/* as specified with the -T switch. To do this, we cast charts for the start */
  1427. X/* and end of the month, or part of the month, and do an equation check for  */
  1428. X/* aspects to the other base chart during the interval.                      */
  1429. X
  1430. Xvoid DisplayTransit(prog)
  1431. Xint prog;
  1432. X{
  1433. X  real planet3[TOTAL+1], house3[SIGNS+1], ret3[TOTAL+1];
  1434. X  unsigned time[MAXINDAY];
  1435. X  int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY], sign[MAXINDAY],
  1436. X    isret[MAXINDAY], occurcount, div, i, j, k, s1, s2, s3;
  1437. X  real M1, M2, divsiz, daysiz, d, e1, e2, f1, f2;
  1438. X
  1439. X  for (i = 1; i <= SIGNS; i++)
  1440. X    house3[i] = house[i];
  1441. X  for (i = 1; i <= total; i++) {
  1442. X    planet3[i] = planet[i];
  1443. X    ret3[i] = ret[i];
  1444. X  }
  1445. X  if (Mon2 == 0.0) {        /* Searching month number zero means to search */
  1446. X    M1 = 1.0; M2 = 12.0;    /* the whole year instead, month by month.     */
  1447. X  } else
  1448. X    M1 = M2 = Mon2;
  1449. X
  1450. X  /* Start searching the month or months in question for any transits. */
  1451. X
  1452. X  for (Mon2 = M1; Mon2 <= M2; Mon2 += 1.0) {
  1453. X    daysiz = (real) DayInMonth((int) Mon2, (int) Yea2)*24.0*60.0;
  1454. X    divsiz = daysiz/ (real) divisions;
  1455. X
  1456. X    /* Cast chart for beginning of month and store it for future use. */
  1457. X
  1458. X    M = Mon2; D = 1.0; Y = Yea2; F = 0.0;
  1459. X    X = defzone; L5 = deflong; LA = deflat;
  1460. X    if (progress = prog) {
  1461. X      Jdp = MdyToJulian(M, D, Y);
  1462. X      M = Mon; D = Day; Y = Yea; F = Tim; X = Zon; L5 = Lon; LA = Lat;
  1463. X    }
  1464. X    CastChart(TRUE);
  1465. X    for (i = 1; i <= SIGNS; i++)
  1466. X      house2[i] = house[i];
  1467. X    for (i = 1; i <= OBJECTS; i++) {
  1468. X      planet2[i] = planet[i];
  1469. X      ret2[i] = ret[i];
  1470. X    }
  1471. X
  1472. X    /* Divide our month into segments and then search each segment in turn. */
  1473. X
  1474. X    for (div = 1; div <= divisions; div++) {
  1475. X      occurcount = 0;
  1476. X
  1477. X      /* Cast the chart for the ending time of the present segment, and */
  1478. X      /* copy the start time chart from the previous end time chart.    */
  1479. X
  1480. X      M = Mon2; Y = Yea2; F = 0.0; X = defzone; L5 = deflong; LA = deflat;
  1481. X      D = 1.0+(daysiz/24.0/60.0)*div/ (real) divisions;
  1482. X      if (prog) {
  1483. X        Jdp = MdyToJulian(M, D, Y);
  1484. X        M = Mon; D = Day; Y = Yea; F = Tim; X = Zon; L5 = Lon; LA = Lat;
  1485. X      }
  1486. X      CastChart(TRUE);
  1487. X      for (i = 1; i <= SIGNS; i++) {
  1488. X        house1[i] = house2[i]; house2[i] = house[i];
  1489. X      }
  1490. X      for (i = 1; i <= OBJECTS; i++) {
  1491. X        planet1[i] = planet2[i]; ret1[i] = ret2[i];
  1492. X        planet2[i] = planet[i];  ret2[i] = ret[i];
  1493. X      }
  1494. X
  1495. X      /* Now search through the present segment for any transits. Note that */
  1496. X      /* stars can be transited, but they can't make transits themselves.   */
  1497. X
  1498. X      for (i = 1; i <= total; i++) if (!ignore[i])
  1499. X        for (j = 1; j <= BASE; j++) if (!ignore2[j] &&
  1500. X          (prog || j <= THINGS || j > C_HI))
  1501. X
  1502. X          /* Between each pair of planets, check if they make any aspects. */
  1503. X
  1504. X          for (k = 1; k <= aspects; k++) {
  1505. X            d = planet3[i]; e1 = planet1[j]; e2 = planet2[j];
  1506. X            if (MinDistance(e1, Mod(d-aspectangle[k])) <
  1507. X                MinDistance(e2, Mod(d+aspectangle[k]))) {
  1508. X              e1 = Mod(e1+aspectangle[k]);
  1509. X              e2 = Mod(e2+aspectangle[k]);
  1510. X            } else {
  1511. X              e1 = Mod(e1-aspectangle[k]);
  1512. X              e2 = Mod(e2-aspectangle[k]);
  1513. X            }
  1514. X
  1515. X            /* Check to see if the present aspect actually occurs during the */
  1516. X            /* segment, making sure we check any Aries point crossings.      */
  1517. X
  1518. X            f1 = e1-d;
  1519. X            if (dabs(f1) > 180.0)
  1520. X              f1 -= Sgn(f1)*DEGREES;
  1521. X            f2 = e2-d;
  1522. X            if (dabs(f2) > 180.0)
  1523. X              f2 -= Sgn(f2)*DEGREES;
  1524. X            if (MinDistance(d, Midpoint(e1, e2)) < 90.0 &&
  1525. X              Sgn(f1) != Sgn(f2) && occurcount < MAXINDAY) {
  1526. X
  1527. X              /* Ok, we have found a transit. Now determine the time */
  1528. X              /* and save this transit in our list to be printed.    */
  1529. X
  1530. X              source[occurcount] = j;
  1531. X              aspect[occurcount] = k;
  1532. X              dest[occurcount] = i;
  1533. X              time[occurcount] = (int) (dabs(f1)/(dabs(f1)+dabs(f2))*divsiz) +
  1534. X                (int) ((real) (div-1)*divsiz);
  1535. X              sign[occurcount] = (int) (Mod(
  1536. X                MinDistance(planet1[j], Mod(d-aspectangle[k])) <
  1537. X                MinDistance(planet2[j], Mod(d+aspectangle[k])) ?
  1538. X                d-aspectangle[k] : d+aspectangle[k])/30.0)+1;
  1539. X              isret[occurcount] = (ret1[j] < 0.0)+(ret2[j] < 0.0);
  1540. X              occurcount++;
  1541. X            }
  1542. X          }
  1543. X
  1544. X      /* After all transits located, sort them by time at which they occur. */
  1545. X
  1546. X      for (i = 1; i < occurcount; i++) {
  1547. X        j = i-1;
  1548. X        while (j >= 0 && time[j] > time[j+1]) {
  1549. X          SWAP(source[j], source[j+1]);
  1550. X          SWAP(aspect[j], aspect[j+1]);
  1551. X          SWAP(dest[j], dest[j+1]);
  1552. X          SWAP(time[j], time[j+1]);
  1553. X          SWAP(sign[j], sign[j+1]);
  1554. X          SWAP(isret[j], isret[j+1]);
  1555. X          j--;
  1556. X        }
  1557. X      }
  1558. X
  1559. X      /* Now loop through list and display all the transits. */
  1560. X
  1561. X      for (i = 0; i < occurcount; i++) {
  1562. X        k = smartcusp && dest[i] >= C_LO && dest[i] <= C_HI;
  1563. X        if (k && aspect[i] > 2)
  1564. X          continue;
  1565. X        else
  1566. X          k = k && aspect[i] == 2;
  1567. X        s1 = time[i]/24/60;
  1568. X        s3 = time[i]-s1*24*60;
  1569. X        s2 = s3/60;
  1570. X        s3 = s3-s2*60;
  1571. X        printf("%2.0f/%d%d/%4.0f %2d:%d%d%cm ",
  1572. X          Mon2, (s1+1)/10, (s1+1)%10, Yea2, Mod12(s2),
  1573. X          s3/10, s3%10, s2 < 12 ? 'a' : 'p');
  1574. X        AnsiColor(objectansi[source[i]]);
  1575. X        printf("%s %7.7s", !prog ? "trans" : "progr", objectname[source[i]]);
  1576. X        j = sign[i];
  1577. X        AnsiColor(elemansi[j-1 & 3]);
  1578. X        printf(" %c%c%c%c%c ",
  1579. X          isret[i] < 1 ? '(' : (isret[i] > 1 ? '[' : '<'), SIGNAM(j),
  1580. X          isret[i] < 1 ? ')' : (isret[i] > 1 ? ']' : '>'));
  1581. X        AnsiColor(aspectansi[k ? 1 : aspect[i]]);
  1582. X        printf("%s ", aspectabbrev[k ? 1 : aspect[i]]);
  1583. X        j = k ? sign[i] : (int)planet3[dest[i]]/30 + 1;
  1584. X        AnsiColor(elemansi[j-1 & 3]);
  1585. X        printf("%c%c%c%c%c ", ret3[dest[i]] >= 0.0 ? '(' : '[',
  1586. X          SIGNAM(j), ret3[dest[i]] >= 0.0 ? ')' : ']');
  1587. X        AnsiColor((objectansi[dest[i]]-1 ^ k)+1);
  1588. X        printf("natal ");
  1589. X        if (k)
  1590. X          printf("%dth cusp", dest[i]-15 - (dest[i] < 23));
  1591. X        else
  1592. X          printf("%s", objectname[dest[i]]);
  1593. X        AnsiColor(-1);
  1594. X
  1595. X        /* Check for a Solar, Lunar, or any other return. */
  1596. X
  1597. X        if (aspect[i] == 1 && source[i] == dest[i]) {
  1598. X          AnsiColor(WHITE);
  1599. X          printf(" (%s Return)", source[i] == 1 ? "Solar" :
  1600. X            (source[i] == 2 ? "Lunar" : objectname[source[i]]));
  1601. X        }
  1602. X        putchar('\n');
  1603. X        if (interpret)
  1604. X          InterpretTransit(source[i], aspect[i], dest[i]);
  1605. X        AnsiColor(-1);
  1606. X      }
  1607. X    }
  1608. X  }
  1609. X}
  1610. X
  1611. X
  1612. X/* Print out an ephemeris - the positions of the planets at midnight each */
  1613. X/* day during a specified month, as done with the -E switch.              */
  1614. X
  1615. Xvoid DisplayEphemeris()
  1616. X{
  1617. X  real M0, M1, M2;
  1618. X  int daysiz, i, j, k, s, d, m;
  1619. X
  1620. X  /* If -Ey is in effect, then loop through all months in the whole year. */
  1621. X
  1622. X  if (exdisplay & DASHEy) {
  1623. X    M1 = 1.0; M2 = 12.0;
  1624. X  } else
  1625. X    M1 = M2 = Mon;
  1626. X
  1627. X  /* Loop through the month or months in question, printing each ephemeris. */
  1628. X
  1629. X  for (M0 = M1; M0 <= M2; M0 += 1.0) {
  1630. X    daysiz = DayInMonth((int) M0, (int) Yea);
  1631. X    printf("Mo/Dy/Yr");
  1632. X    for (k = 0, j = 1; j <= total; j++) {
  1633. X      if (!ignore[j] && (j <= THINGS || j > C_HI)) {
  1634. X        printf("  %c%c%c%c ", OBJNAM(j), objectname[j][3] != 0 ?
  1635. X          objectname[j][3] : ' ');
  1636. X        k++;
  1637. X        if (column80 && k >= 10)
  1638. X          j = total;
  1639. X      }
  1640. X    }
  1641. X    putchar('\n');
  1642. X    for (i = 1; i <= daysiz; i++) {
  1643. X
  1644. X      /* Loop through each day in the month, casting a chart for that day. */
  1645. X
  1646. X      M = M0; D = (real) i; Y = Yea;
  1647. X      F = 0.0; X = defzone; L5 = deflong; LA = deflat;
  1648. X      CastChart(TRUE);
  1649. X      printf("%2d/%2d/%2d ", (int) M0, i, ((int) Yea) % 100);
  1650. X      for (k = 0, j = 1; j <= total; j++)
  1651. X        if (!ignore[j] && (j <= THINGS || j > C_HI)) {
  1652. X          AnsiColor(objectansi[j]);
  1653. X          s = (int) (planet[j]/30.0) + 1;
  1654. X          d = (int) planet[j] - (s-1)*30;
  1655. X          m = (int) (FRACT(planet[j])*60.0);
  1656. X          printf("%2d%s%s%d%c", d, signabbrev[s], m < 10 ? "0" : "", m,
  1657. X            ret[j] >= 0.0 ? ' ' : '.');
  1658. X          k++;
  1659. X          if (column80 && k >= 10)
  1660. X            j = total;
  1661. X        }
  1662. X      putchar('\n');
  1663. X      AnsiColor(-1);
  1664. X    }
  1665. X    if (M0 < M2)
  1666. X      putchar('\n');
  1667. X  }
  1668. X}
  1669. X
  1670. X
  1671. X/* Display either a biorhythm chart or the number of days that have passed */
  1672. X/* between two charts, i.e. two types of relationship "charts" that aren't */
  1673. X/* related in any way to planetary positions, as specified by either the   */
  1674. X/* -rb or -rd switches, respectively.                                      */
  1675. X
  1676. Xvoid DisplayRelation()
  1677. X{
  1678. X  int i, j;
  1679. X  real k, l;
  1680. X
  1681. X  /* If we are calculating the difference between two dates, then display */
  1682. X  /* the value and return, as with the -rd switch.                        */
  1683. X
  1684. X  if (relation == DASHrd) {
  1685. X    printf("%.0f day%s ha%s passed between the dates in the two charts.\n",
  1686. X     JD, JD != 1.0 ? "s" : "", JD != 1.0 ? "ve" : "s");
  1687. X    return;
  1688. X  }
  1689. X
  1690. X  /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  1691. X  /* someone born on the older date, at the time of the younger date. Loop */
  1692. X  /* through the week preceeding and following the date in question.       */
  1693. X
  1694. X  for (JD -= 7.0, i = -7; i <= 7; i++, JD += 1.0) {
  1695. X    if (i == 0)
  1696. X      AnsiColor(WHITE);
  1697. X    else if (i == 1)
  1698. X      AnsiColor(-1);
  1699. X    printf("T%c%d Day%c:", i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' ');
  1700. X    for (j = 1; j <= 3; j++) {
  1701. X      putchar(' ');
  1702. X      switch (j) {
  1703. X      case 1: k = 23.0; AnsiColor(RED);   printf("Physical");     break;
  1704. X      case 2: k = 28.0; AnsiColor(BLUE);  printf("Emotional");    break;
  1705. X      case 3: k = 33.0; AnsiColor(GREEN); printf("Intellectual"); break;
  1706. X      }
  1707. X      AnsiColor(i ? -1 : WHITE);
  1708. X
  1709. X      /* The biorhythm formula is below. */
  1710. X
  1711. X      l = sin((JD/k)*PI*2.0)*100.0;
  1712. X      printf(" at %c%3.0f%%", l < 0.0 ? '-' : '+', dabs(l));
  1713. X
  1714. X      /* Print smiley face, medium face, or sad face based on current cycle. */
  1715. X
  1716. X      printf(" :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  1717. X      if (j < 3)
  1718. X        putchar(',');
  1719. X    }
  1720. X    putchar('\n');
  1721. X  }
  1722. X}
  1723. X
  1724. X
  1725. X/* Another important procedure: Display any of the types of (text) charts    */
  1726. X/* that the user specified they wanted, by calling the appropriate routines. */
  1727. X
  1728. Xvoid PrintChart(prog)
  1729. X{
  1730. X  if (todisplay == 0)          /* Assume the -v chart if user */
  1731. X    todisplay |= DASHv;        /* didn't indicate anything.   */
  1732. X  if (todisplay & DASHv) {
  1733. X    if (relation < DASHrd)
  1734. X      ChartLocation(FALSE);
  1735. X    else
  1736. X
  1737. X      /* If the -rb or -rd relationship charts are in effect, then instead  */
  1738. X      /* of doing the standard -v chart, print either of these chart types. */
  1739. X
  1740. X      DisplayRelation();
  1741. X    if (todisplay - (todisplay & DASHv*2-1))
  1742. X      printf("\n\n");
  1743. X  }
  1744. X  if (todisplay & DASHw) {
  1745. X    ChartWheel();
  1746. X    if (todisplay - (todisplay & DASHw*2-1))
  1747. X      printf("\n\n");
  1748. X  }
  1749. X  if (todisplay & DASHg) {
  1750. X    if (relation != DASHr0) {
  1751. X      CreateGrid(FALSE);
  1752. X      ChartGrid(FALSE);
  1753. X      if (exdisplay & DASHg0) {    /* If -g0 switch in effect, then  */
  1754. X        putchar('\n');             /* display aspect configurations. */
  1755. X        DisplayGrands();
  1756. X      }
  1757. X    } else {
  1758. X
  1759. X      /* Do a relationship aspect grid between two charts if -r0 in effect. */
  1760. X
  1761. X      CreateGridRelation(exdisplay & DASHg0 ? 2 : FALSE);
  1762. X      DisplayGridRelation();
  1763. X    }
  1764. X    if (todisplay - (todisplay & DASHg*2-1))
  1765. X      printf("\n\n");
  1766. X  }
  1767. X  if (todisplay & DASHm) {
  1768. X    if (!(todisplay & DASHg) || relation == DASHr0)
  1769. X      CreateGrid(FALSE);
  1770. X    if (relation != DASHr0) {
  1771. X      ChartMidpoint();
  1772. X      if (todisplay - (todisplay & DASHm*2-1))
  1773. X        printf("\n\n");
  1774. X    } else {
  1775. X      CreateGridRelation((exdisplay & DASHm0) == 0);
  1776. X      DisplayMidpointRelation();
  1777. X    }
  1778. X  }
  1779. X  if (todisplay & DASHZ) {
  1780. X    ChartHorizon();
  1781. X    if (todisplay - (todisplay & DASHZ*2-1))
  1782. X      printf("\n\n");
  1783. X  }
  1784. X  if (todisplay & DASHS) {
  1785. X    ChartSpace();
  1786. X    if (todisplay - (todisplay & DASHS*2-1))
  1787. X      printf("\n\n");
  1788. X  }
  1789. X  if (todisplay & DASHj) {
  1790. X    ChartInfluence();
  1791. X    if (todisplay - (todisplay & DASHj*2-1))
  1792. X      printf("\n\n");
  1793. X  }
  1794. X  if (todisplay & DASHL) {
  1795. X    ChartAstroGraph();
  1796. X    if (todisplay - (todisplay & DASHL*2-1))
  1797. X      printf("\n\n");
  1798. X  }
  1799. X  if (todisplay & DASHd) {
  1800. X    DisplayInDay(prog);
  1801. X    if (todisplay - (todisplay & DASHd*2-1))
  1802. X      printf("\n\n");
  1803. X  }
  1804. X  if (todisplay & DASHE) {
  1805. X    DisplayEphemeris();
  1806. X    if (todisplay - (todisplay & DASHE*2-1))
  1807. X      printf("\n\n");
  1808. X  }
  1809. X  if (todisplay & DASHT)
  1810. X    DisplayTransit(prog);
  1811. X}
  1812. X
  1813. X/* options.c */
  1814. END_OF_FILE
  1815. if test 40939 -ne `wc -c <'options.c'`; then
  1816.     echo shar: \"'options.c'\" unpacked with wrong size!
  1817. fi
  1818. # end of 'options.c'
  1819. fi
  1820. echo shar: End of archive 4 \(of 12\).
  1821. cp /dev/null ark4isdone
  1822. MISSING=""
  1823. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1824.     if test ! -f ark${I}isdone ; then
  1825.     MISSING="${MISSING} ${I}"
  1826.     fi
  1827. done
  1828. if test "${MISSING}" = "" ; then
  1829.     echo You have unpacked all 12 archives.
  1830.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1831. else
  1832.     echo You still need to unpack the following archives:
  1833.     echo "        " ${MISSING}
  1834. fi
  1835. ##  End of shell archive.
  1836. exit 0
  1837.  
  1838. exit 0 # Just in case...
  1839.