home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource1 / ast40dos / options.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-04  |  56.5 KB  |  1,703 lines

  1. /*
  2. ** Astrolog (Version 4.00) File: options.c
  3. **
  4. ** IMPORTANT NOTICE: the graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1993 by Walter D. Pullen
  6. ** (cruiser1@stein.u.washington.edu). Permission is granted to freely
  7. ** use and distribute these routines provided one doesn't sell,
  8. ** restrict, or profit from them in any way. Modification is allowed
  9. ** provided these notices remain with any altered or edited versions of
  10. ** the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 12/31/1993.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40.  
  41. /*
  42. ******************************************************************************
  43. ** Display Subroutines.
  44. ******************************************************************************
  45. */
  46.  
  47. /* This is a subprocedure of CreateGrid() and CreateGridRelation(). Given */
  48. /* two planets, determine what aspect, if any, is present between them,   */
  49. /* and save the aspect name and orb in the specified grid cell.           */
  50.  
  51. void GetAspect(planet1, planet2, ret1, ret2, i, j)
  52. real *planet1, *planet2, *ret1, *ret2;
  53. int i, j;
  54. {
  55.   int k;
  56.   real l, m;
  57.  
  58.   grid->v[i][j] = grid->n[i][j] = 0;
  59.   l = MinDistance(planet2[i], planet1[j]);
  60.   for (k = aspects; k >= 1; k--) {
  61.     m = l-aspectangle[k];
  62.     if (dabs(m) < Orb(i, j, k)) {
  63.       grid->n[i][j] = k;
  64.  
  65.       /* If -ga switch in effect, then change the sign of the orb to    */
  66.       /* correspond to whether the aspect is applying or separating.    */
  67.       /* To do this, we check the velocity vectors to see if the        */
  68.       /* planets are moving toward, away, or are overtaking each other. */
  69.  
  70.       if (exdisplay & DASHga)
  71.         m = SGN2(ret1[j]-ret2[i])*
  72.           SGN2(MinDifference(planet2[i], planet1[j]))*SGN2(m)*dabs(m);
  73.       grid->v[i][j] = (int) (m*60.0);
  74.     }
  75.   }
  76. }
  77.  
  78.  
  79. /* Set up the aspect/midpoint grid. Allocate memory for this array, if not */
  80. /* already done. Allocation is only done once, first time this is called.  */
  81.  
  82. bool EnsureGrid()
  83. {
  84.   char string[STRING];
  85.  
  86.   if (grid != NULL)
  87.     return TRUE;
  88.   Allocate(grid, sizeof(gridstruct), gridstruct PTR);
  89.   if (grid == NULL
  90. #ifdef PC
  91.     /* For PC's the grid better not cross a segment boundary. */
  92.     || HIWORD(LOWORD(grid) + sizeof(gridstruct)) > 0
  93. #endif
  94.     ) {
  95.     sprintf(string, "Not enough memory for grid (%d bytes).",
  96.       sizeof(gridstruct));
  97.     PrintError(string);
  98.     return FALSE;
  99.   }
  100.   return TRUE;
  101. }
  102.  
  103.  
  104. /* Fill in the aspect grid based on the aspects taking place among the */
  105. /* planets in the present chart. Also fill in the midpoint grid.       */
  106.  
  107. void CreateGrid(acc)
  108. int acc;
  109. {
  110.   int i, j, k;
  111.   real l;
  112.  
  113.   if (!EnsureGrid())
  114.     return;
  115.   for (j = 1; j <= total; j++) if (!ignore[j])
  116.     for (i = 1; i <= total; i++) if (!ignore[i])
  117.  
  118.       /* The parameter 'acc' determine what half of the grid is filled in */
  119.       /* with the aspects and what half is filled in with the midpoints.  */
  120.  
  121.       if (acc ? i > j : i < j)
  122.         GetAspect(planet, planet, ret, ret, i, j);
  123.       else if (acc ? i < j : i > j) {
  124.         l = Mod(Midpoint(planet[i], planet[j])); k = (int)l;    /* Calculate */
  125.         grid->n[i][j] = k/30+1;                                 /* midpoint. */
  126.         grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0);
  127.       } else {
  128.         grid->n[i][j] = ZTOS(planet[j]);
  129.         grid->v[i][j] = (int)(planet[j]-(real)(grid->n[i][j]-1)*30.0);
  130.       }
  131. }
  132.  
  133.  
  134. /* This is similar to the previous function; however, this time fill in the */
  135. /* grid based on the aspects (or midpoints if 'acc' set) taking place among */
  136. /* the planets in two different charts, as in the -g -r0 combination.       */
  137.  
  138. void CreateGridRelation(acc)
  139. int acc;
  140. {
  141.   int i, j, k;
  142.   real l;
  143.  
  144.   if (!EnsureGrid())
  145.     return;
  146.   for (j = 1; j <= total; j++) if (!ignore[j])
  147.     for (i = 1; i <= total; i++) if (!ignore[i])
  148.       if (!acc)
  149.         GetAspect(planet1, planet2, ret1, ret2, i, j);
  150.       else {
  151.         l = Mod(Midpoint(planet2[i], planet1[j])); k = (int)l;  /* Calculate */
  152.         grid->n[i][j] = k/30+1;                                 /* midpoint. */
  153.         grid->v[i][j] = (int)((l-(real)(k/30)*30.0)*60.0);
  154.       }
  155. }
  156.  
  157.  
  158. /*
  159. ******************************************************************************
  160. ** Multiple Chart Display Subprograms.
  161. ******************************************************************************
  162. */
  163.  
  164. /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  165. /* relationship chart. This is similar to the ChartGrid() routine; however, */
  166. /* here we have both axes labeled with the planets for the two charts in    */
  167. /* question, instead of just a diagonal down the center for only one chart. */
  168.  
  169. void DisplayGridRelation()
  170. {
  171.   int i, j, k, tot = total, temp;
  172.  
  173. #ifdef INTERPRET
  174.   if (interpret && !(exdisplay & DASHg0)) {
  175.     InterpretGridRelation();
  176.     return;
  177.   }
  178. #endif
  179.   fprintf(S, " 2>");
  180.   for (temp = 0, i = 1; i <= total; i++) if (!ignore[i]) {
  181.     printc(BOXV);
  182.     AnsiColor(objectansi[i]);
  183.     fprintf(S, "%c%c%c", OBJNAM(i));
  184.     AnsiColor(DEFAULT);
  185.     temp++;
  186.     if (column80 && temp >= 19) {
  187.       tot = i;
  188.       i = total;
  189.     }
  190.   }
  191.   fprintf(S, "\n1  ");
  192.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  193.     printc(BOXV);
  194.     AnsiColor(signansi(ZTOS(planet2[i])));
  195.     fprintf(S, "%2d%c", (int)planet2[i] % 30, DEGR2);
  196.     AnsiColor(DEFAULT);
  197.   }
  198.   fprintf(S, "\nV  ");
  199.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  200.     printc(BOXV);
  201.     temp = ZTOS(planet2[i]);
  202.     AnsiColor(signansi(temp));
  203.     fprintf(S, "%c%c%c", SIGNAM(temp));
  204.     AnsiColor(DEFAULT);
  205.   }
  206.   printl();
  207.   for (j = 1; j <= total; j++) if (!ignore[j])
  208.     for (k = 1; k <= 4; k++) {
  209.       if (k < 2)
  210.         PrintTab(BOXH, 3);
  211.       else if (k == 2) {
  212.         AnsiColor(objectansi[j]);
  213.         fprintf(S, "%c%c%c", OBJNAM(j));
  214.       } else {
  215.         temp = ZTOS(planet1[j]);
  216.         AnsiColor(signansi(temp));
  217.         if (k == 3)
  218.           fprintf(S, "%2d%c", (int)planet1[j] - (temp-1)*30, DEGR2);
  219.         else
  220.           fprintf(S, "%c%c%c", SIGNAM(temp));
  221.       }
  222.       if (k > 1)
  223.         AnsiColor(DEFAULT);
  224.       for (i = 1; i <= tot; i++) if (!ignore[i]) {
  225.         printc(k < 2 ? BOXC : BOXV);
  226.         temp = grid->n[i][j];
  227.         if (k > 1) {
  228.           if (i == j)
  229.             AnsiColor(REVERSE);
  230.           AnsiColor(exdisplay & DASHg0 ? signansi(temp) :
  231.             aspectansi[temp]);
  232.         }
  233.         if (k < 2)
  234.           PrintTab(BOXH, 3);
  235.         else if (k == 2) {
  236.           if (exdisplay & DASHg0)
  237.             fprintf(S, "%c%c%c", SIGNAM(temp));
  238.           else
  239.             fprintf(S, "%s", temp ? aspectabbrev[temp] : "   ");
  240.         } else if (k == 3) {
  241.           if (exdisplay & DASHg0)
  242.             fprintf(S, "%2d%c", grid->v[i][j]/60, DEGR2);
  243.           else
  244.             if (grid->n[i][j]) {
  245.               if (grid->v[i][j] < 600)
  246.                 fprintf(S, "%c%2d", exdisplay & DASHga ?
  247.                   (grid->v[i][j] < 0 ? 'a' : 's') :
  248.                   (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  249.               else
  250.                 fprintf(S, "%3d", abs(temp)/60);
  251.             } else
  252.               fprintf(S, "   ");
  253.         } else {
  254.           if (grid->n[i][j])
  255.             fprintf(S, "%02d'", abs(grid->v[i][j])%60);
  256.           else
  257.             fprintf(S, "   ");
  258.         }
  259.         AnsiColor(DEFAULT);
  260.       }
  261.       printl();
  262.     }
  263. }
  264.  
  265.  
  266. /* Display all aspects between objects in the relationship comparison chart, */
  267. /* one per line, in sorted order based on the total "power" of the aspects,  */
  268. /* as specified with the -r0 -m0 switch combination.                         */
  269.  
  270. void DisplayAspectRelation()
  271. {
  272.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  273.   real ip, jp;
  274.  
  275.   loop {
  276.     phi = -1;
  277.  
  278.     /* Search for the next most powerful aspect in the aspect grid. */
  279.  
  280.     for (i = 1; i <= total; i++) if (!ignore[i])
  281.       for (j = 1; j <= total; j++) if (!ignore[j])
  282.         if (k = grid->n[i][j]) {
  283.           ip = i <= OBJECTS ? objectinf[i] : 2.5;
  284.           jp = j <= OBJECTS ? objectinf[j] : 2.5;
  285.           p = (int) (aspectinf[k]*(ip+jp)/2.0*
  286.             (1.0-dabs((real)(grid->v[i][j]))/60.0/aspectorb[k])*1000.0);
  287.           if ((p < pcut || (p == pcut && (i > icut ||
  288.             (i == icut && j > jcut)))) && p > phi) {
  289.             ihi = i; jhi = j; phi = p; ahi = k;
  290.           }
  291.         }
  292.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  293.       break;
  294.     pcut = phi; icut = ihi; jcut = jhi;
  295.     count++;                               /* Display the current aspect.   */
  296. #ifdef INTERPRET
  297.     if (interpret) {                       /* Interpret it if -I in effect. */
  298.       InterpretAspectRelation(jhi, ihi);
  299.       continue;
  300.     }
  301. #endif
  302.     fprintf(S, "%3d: ", count);
  303.     PrintAspect(jhi, ZTOS(planet1[jhi]), (int)Sgn(ret1[jhi]), ahi,
  304.       ihi, ZTOS(planet2[ihi]), (int)Sgn(ret2[ihi]), 'A');
  305.     k = grid->v[ihi][jhi];
  306.     AnsiColor(k < 0 ? WHITE : LTGRAY);
  307.     fprintf(S, "- orb: %c%d,%02d'",
  308.       exdisplay & DASHga ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  309.       abs(k)/60, abs(k)%60);
  310.     AnsiColor(DKGREEN);
  311.     fprintf(S, " - power:%6.2f\n", (real) phi/1000.0);
  312.     AnsiColor(DEFAULT);
  313.   }
  314. }
  315.  
  316.  
  317. /* Display locations of all midpoints between objects in the relationship */
  318. /* comparison chart, one per line, in sorted zodiac order from zero Aries */
  319. /* onward, as specified with the -r0 -m switch combination.               */
  320.  
  321. void DisplayMidpointRelation()
  322. {
  323.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  324.  
  325.   loop {
  326.     mlo = 21600;
  327.  
  328.     /* Search for the next closest midpoint farther down in the zodiac. */ 
  329.  
  330.     for (i = 1; i <= total; i++) if (!ignore[i])
  331.       for (j = 1; j <= total; j++) if (!ignore[j]) {
  332.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  333.         if ((m > mcut || (m == mcut && (i > icut ||
  334.           (i == icut && j > jcut)))) && m < mlo) {
  335.           ilo = i; jlo = j; mlo = m;
  336.         }
  337.       }
  338.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  339.       break;
  340.     mcut = mlo; icut = ilo; jcut = jlo;
  341.     count++;                               /* Display the current midpoint. */
  342. #ifdef INTERPRET
  343.     if (interpret) {                       /* Interpret it if -I in effect. */
  344.       InterpretMidpointRelation(ilo, jlo);
  345.       continue;
  346.     }
  347. #endif
  348.     fprintf(S, "%4d: ", count);
  349.     PrintZodiac((real) mlo/60.0);
  350.     printc(' ');
  351.     PrintAspect(ilo, ZTOS(planet1[ilo]), (int)Sgn(ret1[ilo]), 0,
  352.       jlo, ZTOS(planet2[jlo]), (int)Sgn(ret2[jlo]), 'M');
  353.     AnsiColor(DEFAULT);
  354.     fprintf(S, "-%4d degree span.\n",
  355.       (int)MinDistance(planet1[ilo], planet2[jlo]));
  356.   }
  357. }
  358.  
  359.  
  360. /* Calculate any of the various kinds of relationship charts. This involves */
  361. /* reading in and storing the planet and house positions for both charts,   */
  362. /* and then combining them in the main single chart in the proper manner.   */
  363. /* If the parameter 'var' is set, then we read the info for the two charts  */
  364. /* from files, otherwise use the info in preset "core" and "second" charts. */
  365.  
  366. void CastRelation(var)
  367. int var;
  368. {
  369.   int mon, day, yea, i;
  370.   real tim, zon, lon, lat, t1, t2, t;
  371.  
  372.   /* Read in and cast the first chart. */
  373.  
  374.   if (var)
  375.     InputData(filename);
  376.   mon = MM; day = DD; yea = YY; tim = TT; zon = ZZ; lon = OO; lat = AA;
  377.   if (var) {
  378.     SetTwin(MM, DD, YY, TT, ZZ, OO, AA);
  379.   } else {
  380.     SetCore(Mon2, Day2, Yea2, Tim2, Zon2, Lon2, Lat2);
  381.   }
  382.   t1 = CastChart(TRUE);
  383.   for (i = 1; i <= SIGNS; i++) {
  384.     house1[i] = house[i];
  385.     inhouse1[i] = inhouse[i];
  386.   }
  387.   for (i = 1; i <= total; i++) {
  388.     planet1[i] = planet[i];
  389.     planetalt1[i] = planetalt[i];
  390.     ret1[i] = ret[i];
  391.   }
  392.  
  393.   /* Read in the second chart. */
  394.  
  395.   if (var) {
  396.     InputData(filename2);
  397.     if (relation == DASHrp) {
  398.       progress = TRUE;
  399.       Jdp = (real)MdyToJulian(MM, DD, YY) + TT / 24.0;
  400.       SetCore(mon, day, yea, tim, zon, lon, lat);
  401.     }
  402.   } else {
  403.     SetCore(mon, day, yea, tim, zon, lon, lat);
  404.   }
  405.   SetMain(MM, DD, YY, TT, ZZ, OO, AA);
  406.   t2 = CastChart(TRUE);
  407.   for (i = 1; i <= SIGNS; i++) {
  408.     house2[i] = house[i];
  409.     inhouse2[i] = inhouse[i];
  410.   }
  411.   for (i = 1; i <= total; i++) {
  412.     planet2[i] = planet[i];
  413.     planetalt2[i] = planetalt[i];
  414.     ret2[i] = ret[i];
  415.   }
  416.  
  417.   /* Now combine the two charts based on what relation we are doing.   */
  418.   /* For the standard -r synastry chart, use the house cusps of chart1 */
  419.   /* and the planets positions of chart2.                              */
  420.  
  421.   if (relation <= DASHr)
  422.     for (i = 1; i <= SIGNS; i++)
  423.       house[i] = house1[i];
  424.  
  425.   /* For the -rc composite chart, take the midpoints of the planets/houses. */
  426.  
  427.   else if (relation == DASHrc) {
  428.     for (i = 1; i <= total; i++) {
  429.       planet[i] = Midpoint(planet1[i], planet2[i]);
  430.       planetalt[i] = (planetalt1[i]+planetalt2[i])/2.0;
  431.       ret[i] = (ret1[i]+ret2[i])/2.0;
  432.     }
  433.     for (i = 1; i <= SIGNS; i++)
  434.       house[i] = Midpoint(house1[i], house2[i]);
  435.  
  436.     /* Make sure we don't have any 180 degree errors in house cusp    */
  437.     /* complement pairs, which may happen if the cusps are far apart. */
  438.  
  439.     for (i = 1; i <= SIGNS; i++)
  440.       if (MinDistance(house[_CAP], Mod(house[i]-STOZ(i+3))) > DEGQUAD)
  441.         house[i] = Mod(house[i]+DEGHALF);
  442.  
  443.   /* For the -rm time space midpoint chart, calculate the midpoint time and */
  444.   /* place between the two charts and then recast for the new chart info.   */
  445.  
  446.   } else if (relation == DASHrm) {
  447.     T = (t1+t2)/2.0;
  448.     t = (T*36525.0)+ROUND; JD = floor(t)+2415020.0; TT = FRACT(t)*24.0;
  449.     ZZ = (DecToDeg(zon)+DecToDeg(Zon))/2.0; ZZ = DegToDec(ZZ);
  450.     TT = DecToDeg(TT)-DecToDeg(ZZ); TT = DegToDec(TT);
  451.     if (TT < 0.0) {
  452.       TT = DecToDeg(TT)+24.0; TT = DegToDec(TT); JD -= 1.0;
  453.     }
  454.     JulianToMdy(JD, &MM, &DD, &YY);
  455.     OO = (DecToDeg(lon)+DecToDeg(Lon))/2.0;
  456.     if (dabs(Lon-lon) > DEGHALF)
  457.       OO = Mod(OO+DEGHALF);
  458.     OO = DegToDec(OO);
  459.     AA = (DecToDeg(lat)+DecToDeg(Lat))/2.0; AA = DegToDec(AA);
  460.     SetMain(MM, DD, YY, TT, ZZ, OO, AA);
  461.     CastChart(FALSE);
  462.  
  463.   /* There are a couple of non-astrological charts, which only require the */
  464.   /* number of days that have passed between the two charts to be done.    */
  465.  
  466.   } else
  467.     JD = dabs(t2-t1)*36525.0;
  468.   HousePlace();
  469. }
  470.  
  471.  
  472. /* Given two objects and an aspect between them, or an object and a sign  */
  473. /* that it's entering, print if this is a "major" event, such as a season */
  474. /* change or major lunar phase. This is called from the DisplayInDay      */
  475. /* searching and influence routines. Go an interpretation if need be too. */
  476.  
  477. void PrintInDay(source, aspect, dest)
  478. int source, aspect, dest;
  479. {
  480.   if (aspect == _SIG) {
  481.     if (source == _SUN) {
  482.       AnsiColor(WHITE);
  483.       if (dest == 1)
  484.         fprintf(S, " (Vernal Equinox)");     /* If the Sun changes sign, */
  485.       else if (dest == 4)                    /* then print out if this   */
  486.         fprintf(S, " (Summer Solstice)");    /* is a season change.      */
  487.       else if (dest == 7)
  488.         fprintf(S, " (Autumnal Equinox)");
  489.       else if (dest == 10)
  490.         fprintf(S, " (Winter Solstice)");
  491.     }
  492.   } else if (aspect > 0) {
  493.     if (source == _SUN && dest == _MOO) {
  494.       if (aspect <= _SQU)
  495.         AnsiColor(WHITE);
  496.       if (aspect == _CON)
  497.         fprintf(S, " (New Moon)");     /* Print out if the present */
  498.       else if (aspect == _OPP)         /* aspect is a New, Full,   */
  499.         fprintf(S, " (Full Moon)");    /* or Half Moon.            */
  500.       else if (aspect == _SQU)
  501.         fprintf(S, " (Half Moon)");
  502.     }
  503.   }
  504.   printl();
  505.  
  506. #ifdef INTERPRET
  507.   if (interpret)
  508.     InterpretInDay(source, aspect, dest);
  509. #endif
  510.   AnsiColor(DEFAULT);
  511. }
  512.  
  513.  
  514. /* Given two objects and an aspect (or one object, and an event such as a */
  515. /* sign or direction change) display the configuration in question. This  */
  516. /* is called by the many charts which list aspects among items, such as   */
  517. /* the -m0 aspect lists, -m midpoint lists, -d aspect in day search and   */
  518. /* influence charts, and -t transit search and influence charts.          */
  519.  
  520. void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart)
  521. int obj1, sign1, ret1, asp, obj2, sign2, ret2;
  522. char chart;
  523. {
  524.   int smart, a, s2;
  525.  
  526.   smart = smartcusp && IsCusp(obj2) && asp == _OPP;
  527.   a = smart ? _CON : asp;
  528.   s2 = smart ? sign1 : sign2;
  529.  
  530.   AnsiColor(objectansi[obj1]);
  531.   if (chart == 't' || chart == 'T')
  532.     fprintf(S, "trans ");
  533.   else if (chart == 'e' || chart == 'u' || chart == 'U')
  534.     fprintf(S, "progr ");
  535.   fprintf(S, "%7.7s", objectname[obj1]);
  536.   AnsiColor(signansi(sign1));
  537.   fprintf(S, " %c%c%c%c%c",
  538.     ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), SIGNAM(sign1),
  539.     ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>'));
  540.   AnsiColor(a > 0 ? aspectansi[a] : WHITE);
  541.   printc(' ');
  542.   if (a == _SIG)
  543.     fprintf(S, "-->");                       /* Print a sign change. */
  544.   else if (a == _DIR)
  545.     fprintf(S, "S/%c", obj2 ? 'R' : 'D');    /* Print a direction change. */
  546.   else if (a == 0)
  547.     printf(chart == 'm' ? "&" : "with");
  548.   else
  549.     fprintf(S, "%s", aspectabbrev[a]);       /* Print an aspect. */
  550.   printc(' ');
  551.   if (chart == 'A')
  552.     fprintf(S, "with ");
  553.   if (a == _SIG) {
  554.     AnsiColor(signansi(obj2));
  555.     fprintf(S, "%s", signname[obj2]);
  556.   } else if (a >= 0) {
  557.     AnsiColor(signansi(s2));
  558.     if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U')
  559.       fprintf(S, "natal ");
  560.     fprintf(S, "%c%c%c%c%c ",
  561.       ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), SIGNAM(s2),
  562.       ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>'));
  563.     AnsiColor(smart ? signansi((obj2-15) - (obj2 < 23)) : objectansi[obj2]);
  564.     if (smart) {
  565.       fprintf(S, "%dth cusp", (obj2-15) - (obj2 < 23));
  566.       if (obj2 < 23)
  567.         printc(' ');
  568.     } else
  569.       fprintf(S, "%.10s", objectname[obj2]);
  570.   }
  571.   if (chart == 'D' || chart == 'T' || chart == 'U' ||
  572.     chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M')
  573.     PrintTab(' ', 10-StringLen(objectname[obj2]));
  574. }
  575.  
  576.  
  577. /* Search through a day, and print out the times of exact aspects among the  */
  578. /* planets during that day, as specified with the -d switch, as well as the  */
  579. /* times when a planet changes sign or direction. To do this, we cast charts */
  580. /* for the beginning and end of the day, or a part of a day, and do a linear */
  581. /* equation check to see if anything exciting happens during the interval.   */
  582. /* (This is probably the single most complicated procedure in the program.)  */
  583.  
  584. void DisplayInDaySearch(prog)
  585. int prog;
  586. {
  587.   int time[MAXINDAY], source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY],
  588.     sign1[MAXINDAY], sign2[MAXINDAY], D1, D2, occurcount, division, div,
  589.     i, j, k, l, s1, s2;
  590.   real divsiz, d1, d2, e1, e2, f1, f2, g;
  591.  
  592.   /* If parameter 'prog' is set, look for changes in a progressed chart. */
  593.  
  594.   division = prog ? 1 : divisions;
  595.   divsiz = 24.0/ (real) division*60.0;
  596.  
  597.   /* If -dm in effect, then search through the whole month, day by day. */
  598.  
  599.   if (exdisplay & DASHdm) {
  600.     D1 = 1;
  601.     if (prog && Mon2 == 0) {
  602.       Mon2 = 1; D2 = DayInYear(Yea2);
  603.     } else
  604.       D2 = DayInMonth(prog ? Mon2 : Mon, prog ? Yea2 : Yea);
  605.   } else
  606.     D1 = D2 = Day;
  607.  
  608.   /* Start searching the day or days in question for exciting stuff. */
  609.  
  610.   for (Day2 = D1; Day2 <= D2; Day2++) {
  611.     occurcount = 0;
  612.  
  613.     /* Cast chart for beginning of day and store it for future use. */
  614.  
  615.     SetCore(Mon, Day2, Yea, 0.0, Zon, Lon, Lat);
  616.     if (progress = prog) {
  617.       Jdp = (real)MdyToJulian(Mon2, DD, Yea2);
  618.       SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  619.     }
  620.     CastChart(TRUE);
  621.     for (i = 1; i <= SIGNS; i++) {
  622.       house2[i] = house[i];
  623.       inhouse2[i] = inhouse[i];
  624.     }
  625.     for (i = 1; i <= total; i++) {
  626.       planet2[i] = planet[i];
  627.       ret2[i] = ret[i];
  628.     }
  629.  
  630.     /* Now divide the day into segments and search each segment in turn. */
  631.     /* More segments is slower, but has slightly better time accuracy.   */
  632.  
  633.     for (div = 1; div <= division; div++) {
  634.  
  635.       /* Cast the chart for the ending time of the present segment. The   */
  636.       /* beginning time chart is copied from the previous end time chart. */
  637.  
  638.       SetCore(Mon, Day2, Yea,
  639.         DegToDec(24.0*(real)div/(real)division), Zon, Lon, Lat);
  640.       if (prog) {
  641.         Jdp = (real)MdyToJulian(Mon2, DD+1, Yea2);
  642.         SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  643.       }
  644.       CastChart(TRUE);
  645.       for (i = 1; i <= SIGNS; i++) {
  646.         house1[i] = house2[i]; inhouse1[i] = inhouse2[i];
  647.         house2[i] = house[i];  inhouse2[i] = inhouse[i];
  648.       }
  649.       for (i = 1; i <= total; i++) {
  650.         planet1[i] = planet2[i]; ret1[i] = ret2[i];
  651.         planet2[i] = planet[i];  ret2[i] = ret[i];
  652.       }
  653.  
  654.       /* Now search through the present segment for anything exciting. */
  655.  
  656.       for (i = 1; i <= total; i++) if (!ignore[i] && (prog || IsThing(i))) {
  657.         s1 = ZTOS(planet1[i])-1;
  658.         s2 = ZTOS(planet2[i])-1;
  659.  
  660.         /* Does the current planet change into the next or previous sign? */
  661.  
  662.         if (!ignore[i] && s1 != s2 && !ignore[0]) {
  663.           source[occurcount] = i;
  664.           aspect[occurcount] = _SIG;
  665.           dest[occurcount] = s2+1;
  666.           time[occurcount] = (int) (MinDistance(planet1[i],
  667.             (real) (ret1[i] >= 0.0 ? s2 : s1) * 30.0) /
  668.             MinDistance(planet1[i], planet2[i])*divsiz) +
  669.             (int) ((real) (div-1)*divsiz);
  670.           sign1[occurcount] = sign2[occurcount] = s1+1;
  671.           occurcount++;
  672.         }
  673.  
  674.         /* Does the current planet go retrograde or direct? */
  675.  
  676.         if (!ignore[i] && (ret1[i] < 0.0) != (ret2[i] < 0.0) && !ignore2[0]) {
  677.           source[occurcount] = i;
  678.           aspect[occurcount] = _DIR;
  679.           dest[occurcount] = ret2[i] < 0.0;
  680.           time[occurcount] = (int) (dabs(ret1[i])/(dabs(ret1[i])+dabs(ret2[i]))
  681.             *divsiz) + (int) ((real) (div-1)*divsiz);
  682.           sign1[occurcount] = sign2[occurcount] = s1+1;
  683.           occurcount++;
  684.         }
  685.  
  686.         /* Now search for anything making an aspect to the current planet. */
  687.  
  688.         for (j = i+1; j <= total; j++) if (!ignore[j] && (prog || IsThing(j)))
  689.           for (k = 1; k <= aspects; k++) {
  690.             d1 = planet1[i]; d2 = planet2[i];
  691.             e1 = planet1[j]; e2 = planet2[j];
  692.             if (MinDistance(d1, d2) < MinDistance(e1, e2)) {
  693.               SwapReal(&d1, &e1);
  694.               SwapReal(&d2, &e2);
  695.             }
  696.  
  697.             /* We are searching each aspect in turn. Let's subtract the  */
  698.             /* size of the aspect from the angular difference, so we can */
  699.             /* then treat it like a conjunction.                         */
  700.  
  701.             if (MinDistance(e1, Mod(d1-aspectangle[k])) <
  702.                 MinDistance(e2, Mod(d2+aspectangle[k]))) {
  703.               e1 = Mod(e1+aspectangle[k]);
  704.               e2 = Mod(e2+aspectangle[k]);
  705.             } else {
  706.               e1 = Mod(e1-aspectangle[k]);
  707.               e2 = Mod(e2-aspectangle[k]);
  708.             }
  709.  
  710.             /* Check to see if the aspect actually occurs during our    */
  711.             /* segment, making sure we take into account if one or both */
  712.             /* planets are retrograde or if they cross the Aries point. */
  713.  
  714.             f1 = e1-d1;
  715.             if (dabs(f1) > DEGHALF)
  716.               f1 -= Sgn(f1)*DEGREES;
  717.             f2 = e2-d2;
  718.             if (dabs(f2) > DEGHALF)
  719.               f2 -= Sgn(f2)*DEGREES;
  720.             if (MinDistance(Midpoint(d1, d2), Midpoint(e1, e2)) < DEGQUAD &&
  721.               Sgn(f1) != Sgn(f2)) {
  722.               source[occurcount] = i;
  723.               aspect[occurcount] = k;
  724.               dest[occurcount] = j;
  725.  
  726.               /* Horray! The aspect occurs sometime during the interval.   */
  727.               /* Now we just have to solve an equation in two variables to */
  728.               /* find out where the "lines" cross, i.e. the aspect's time. */
  729.  
  730.               f1 = d2-d1;
  731.               if (dabs(f1) > DEGHALF)
  732.                 f1 -= Sgn(f1)*DEGREES;
  733.               f2 = e2-e1;
  734.               if (dabs(f2) > DEGHALF)
  735.                 f2 -= Sgn(f2)*DEGREES;
  736.               g = (dabs(d1-e1) > DEGHALF ?
  737.                 (d1-e1)-Sgn(d1-e1)*DEGREES : d1-e1)/(f2-f1);
  738.               time[occurcount] = (int) (g*divsiz) +
  739.                 (int) ((real) (div-1)*divsiz);
  740.               sign1[occurcount] = (int) (Mod(planet1[i]+
  741.                 Sgn(planet2[i]-planet1[i])*
  742.                 (dabs(planet2[i]-planet1[i]) > DEGHALF ? -1 : 1)*
  743.                 dabs(g)*MinDistance(planet1[i], planet2[i]))/30.0)+1;
  744.               sign2[occurcount] = (int) (Mod(planet1[j]+
  745.                 Sgn(planet2[j]-planet1[j])*
  746.                 (dabs(planet2[j]-planet1[j]) > DEGHALF ? -1 : 1)*
  747.                 dabs(g)*MinDistance(planet1[j], planet2[j]))/30.0)+1;
  748.               occurcount++;
  749.             }
  750.           }
  751.       }
  752.     }
  753.  
  754.     /* After all the aspects, etc, in the day have been located, sort   */
  755.     /* them by time at which they occur, so we can print them in order. */
  756.  
  757.     for (i = 1; i < occurcount; i++) {
  758.       j = i-1;
  759.       while (j >= 0 && time[j] > time[j+1]) {
  760.         SWAP(source[j], source[j+1]);
  761.         SWAP(aspect[j], aspect[j+1]);
  762.         SWAP(dest[j], dest[j+1]);
  763.         SWAP(time[j], time[j+1]);
  764.         SWAP(sign1[j], sign1[j+1]); SWAP(sign2[j], sign2[j+1]);
  765.         j--;
  766.       }
  767.     }
  768.  
  769.     /* Finally, loop through and display each aspect and when it occurs. */
  770.  
  771.     for (i = 0; i < occurcount; i++) {
  772.       s1 = time[i]/60;
  773.       s2 = time[i]-s1*60;
  774.       j = Day2;
  775.       if (prog) {
  776.         l = Mon2;
  777.         while (j > (k = DayInMonth(l, Yea2))) {
  778.           j -= k;
  779.           l++;
  780.         }
  781.       }
  782.       SetSave(prog ? l : Mon, j, prog ? Yea2 : Yea,
  783.         DegToDec((real)time[i] / 60.0), Zon, Lon, Lat);
  784.       k = DayOfWeek(prog ? l : Mon, j, prog ? Yea2 : Yea);
  785.       AnsiColor(rainbowansi[k + 1]);
  786.       fprintf(S, "(%c%c%c) ", DAYNAM(k));
  787.       AnsiColor(DEFAULT);
  788.       fprintf(S, "%s %s ",
  789.         CharDate(prog ? l : Mon, j, prog ? Yea2 : Yea, FALSE),
  790.         CharTime(s1, s2));
  791.       PrintAspect(source[i], sign1[i],
  792.         (int)Sgn(ret1[source[i]])+(int)Sgn(ret2[source[i]]),
  793.         aspect[i], dest[i], sign2[i],
  794.         (int)Sgn(ret1[dest[i]])+(int)Sgn(ret2[dest[i]]), prog ? 'e' : 'd');
  795.       PrintInDay(source[i], aspect[i], dest[i]);
  796.     }
  797.   }
  798. }
  799.  
  800.  
  801. /* Based on the given chart information, display all the aspects taking    */
  802. /* place in the chart, as specified with the -D switch. The aspects are    */
  803. /* printed in order of influence determined by treating them as happening  */
  804. /* outside among transiting planets, such that rare outer planet aspects   */
  805. /* are given more power than common ones among inner planets. (This is     */
  806. /* almost identical to the -m0 list, except the influences are different.) */
  807.  
  808. void DisplayInDayInfluence()
  809. {
  810.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  811.   real power[MAXINDAY];
  812.   int occurcount = 0, i, j, k, l, m;
  813.  
  814.   /* Go compute the aspects in the chart. */
  815.  
  816.   i = exdisplay;
  817.   exdisplay |= DASHga;    /* We always want applying vs. separating orbs. */
  818.   CreateGrid(FALSE);
  819.   exdisplay = i;
  820.  
  821.   /* Search through the grid and build up the list of aspects. */
  822.  
  823.   for (j = 2; j <= total; j++) {
  824.     if (ignore[j])
  825.       continue;
  826.     for (i = 1; i < j; i++) {
  827.       if (ignore[i] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  828.         continue;
  829.       if (smartcusp && k > _OPP && IsCusp(j))
  830.         continue;
  831.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  832.       l = grid->v[i][j];
  833.       power[occurcount] =
  834.         ((i <= BASE ? transitinf[i] : 2.0)/4.0)*
  835.         ((j <= BASE ? transitinf[j] : 2.0)/4.0)*
  836.         aspectinf[k]*(1.0-(real)abs(l)/60.0/Orb(i, j, k));
  837.       occurcount++;
  838.     }
  839.   }
  840.  
  841.   /* Sort aspects by order of influence. */
  842.  
  843.   for (i = 1; i < occurcount; i++) {
  844.     j = i-1;
  845.     while (j >= 0 && power[j] < power[j+1]) {
  846.       SWAP(source[j], source[j+1]);
  847.       SWAP(aspect[j], aspect[j+1]);
  848.       SWAP(dest[j], dest[j+1]);
  849.       SwapReal(&power[j], &power[j+1]);
  850.       j--;
  851.     }
  852.   }
  853.  
  854.   /* Now display each aspect line. */
  855.  
  856.   for (i = 0; i < occurcount; i++) {
  857.     fprintf(S, "%3d: ", i+1);
  858.     j = source[i]; k = aspect[i]; l = dest[i];
  859.     PrintAspect(
  860.       j, ZTOS(planet[j]), (int)Sgn(ret[j]), k,
  861.       l, ZTOS(planet[l]), (int)Sgn(ret[l]), 'D');
  862.     m = grid->v[j][l];
  863.     AnsiColor(m < 0 ? WHITE : LTGRAY);
  864.     fprintf(S, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  865.       abs(m)/60, DEGR1, abs(m)%60);
  866.     AnsiColor(DKGREEN);
  867.     fprintf(S, " - power:%6.2f", power[i]);
  868.     PrintInDay(j, k, l);
  869.   }
  870. }
  871.  
  872.  
  873. /* Search through a month, and print out the times of exact transits where   */
  874. /* planets in the time frame make aspect to the planets in some other chart, */
  875. /* as specified with the -t switch. To do this, we cast charts for the start */
  876. /* and end of the month, or part of the month, and do an equation check for  */
  877. /* aspects to the other base chart during the interval.                      */
  878.  
  879. void DisplayTransitSearch(prog)
  880. int prog;
  881. {
  882.   real planet3[TOTAL+1], house3[SIGNS+1], ret3[TOTAL+1];
  883.   uint time[MAXINDAY];
  884.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY], sign[MAXINDAY],
  885.     isret[MAXINDAY], M1, M2, occurcount, div, i, j, k, s1, s2, s3;
  886.   real divsiz, daysiz, d, e1, e2, f1, f2;
  887.  
  888.   for (i = 1; i <= SIGNS; i++)
  889.     house3[i] = house[i];
  890.   for (i = 1; i <= total; i++) {
  891.     planet3[i] = planet[i];
  892.     ret3[i] = ret[i];
  893.   }
  894.   if (Mon2 == 0) {      /* Searching month number zero means to search */
  895.     M1 = 1; M2 = 12;    /* the whole year instead, month by month.     */
  896.   } else
  897.     M1 = M2 = Mon2;
  898.  
  899.   /* Start searching the month or months in question for any transits. */
  900.  
  901.   for (Mon2 = M1; Mon2 <= M2; Mon2++) {
  902.     daysiz = (real) DayInMonth(Mon2, Yea2)*24.0*60.0;
  903.     divsiz = daysiz/ (real) divisions;
  904.  
  905.     /* Cast chart for beginning of month and store it for future use. */
  906.  
  907.     SetCore(Mon2, 1, Yea2, 0.0, Zon2, Lon2, Lat2);
  908.     if (progress = prog) {
  909.       Jdp = (real)MdyToJulian(MM, DD, YY);
  910.       SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  911.     }
  912.     CastChart(TRUE);
  913.     for (i = 1; i <= SIGNS; i++)
  914.       house2[i] = house[i];
  915.     for (i = 1; i <= OBJECTS; i++) {
  916.       planet2[i] = planet[i];
  917.       ret2[i] = ret[i];
  918.     }
  919.  
  920.     /* Divide our month into segments and then search each segment in turn. */
  921.  
  922.     for (div = 1; div <= divisions; div++) {
  923.       occurcount = 0;
  924.  
  925.       /* Cast the chart for the ending time of the present segment, and */
  926.       /* copy the start time chart from the previous end time chart.    */
  927.  
  928.       d = 1.0 + (daysiz/24.0/60.0)*(real)div/(real)divisions;
  929.       SetCore(Mon2, (int)d, Yea2,
  930.         DegToDec(FRACT(d)*24.0), Zon2, Lon2, Lat2);
  931.       if (prog) {
  932.         Jdp = (real)MdyToJulian(MM, DD, YY);
  933.         SetCore(Mon, Day, Yea, Tim, Zon, Lon, Lat);
  934.       }
  935.       CastChart(TRUE);
  936.       for (i = 1; i <= SIGNS; i++) {
  937.         house1[i] = house2[i]; house2[i] = house[i];
  938.       }
  939.       for (i = 1; i <= OBJECTS; i++) {
  940.         planet1[i] = planet2[i]; ret1[i] = ret2[i];
  941.         planet2[i] = planet[i];  ret2[i] = ret[i];
  942.       }
  943.  
  944.       /* Now search through the present segment for any transits. Note that */
  945.       /* stars can be transited, but they can't make transits themselves.   */
  946.  
  947.       for (i = 1; i <= total; i++) if (!ignore[i])
  948.         for (j = 1; j <= BASE; j++) if (!ignore2[j] && (prog || IsThing(j)))
  949.  
  950.           /* Between each pair of planets, check if they make any aspects. */
  951.  
  952.           for (k = 1; k <= aspects; k++) {
  953.             d = planet3[i]; e1 = planet1[j]; e2 = planet2[j];
  954.             if (MinDistance(e1, Mod(d-aspectangle[k])) <
  955.                 MinDistance(e2, Mod(d+aspectangle[k]))) {
  956.               e1 = Mod(e1+aspectangle[k]);
  957.               e2 = Mod(e2+aspectangle[k]);
  958.             } else {
  959.               e1 = Mod(e1-aspectangle[k]);
  960.               e2 = Mod(e2-aspectangle[k]);
  961.             }
  962.  
  963.             /* Check to see if the present aspect actually occurs during the */
  964.             /* segment, making sure we check any Aries point crossings.      */
  965.  
  966.             f1 = e1-d;
  967.             if (dabs(f1) > DEGHALF)
  968.               f1 -= Sgn(f1)*DEGREES;
  969.             f2 = e2-d;
  970.             if (dabs(f2) > DEGHALF)
  971.               f2 -= Sgn(f2)*DEGREES;
  972.             if (MinDistance(d, Midpoint(e1, e2)) < DEGQUAD &&
  973.               Sgn(f1) != Sgn(f2) && occurcount < MAXINDAY) {
  974.  
  975.               /* Ok, we have found a transit. Now determine the time */
  976.               /* and save this transit in our list to be printed.    */
  977.  
  978.               source[occurcount] = j;
  979.               aspect[occurcount] = k;
  980.               dest[occurcount] = i;
  981.               time[occurcount] = (int) (dabs(f1)/(dabs(f1)+dabs(f2))*divsiz) +
  982.                 (int) ((real) (div-1)*divsiz);
  983.               sign[occurcount] = (int) (Mod(
  984.                 MinDistance(planet1[j], Mod(d-aspectangle[k])) <
  985.                 MinDistance(planet2[j], Mod(d+aspectangle[k])) ?
  986.                 d-aspectangle[k] : d+aspectangle[k])/30.0)+1;
  987.               isret[occurcount] = (int)Sgn(ret1[j]) + (int)Sgn(ret2[j]);
  988.               occurcount++;
  989.             }
  990.           }
  991.  
  992.       /* After all transits located, sort them by time at which they occur. */
  993.  
  994.       for (i = 1; i < occurcount; i++) {
  995.         j = i-1;
  996.         while (j >= 0 && time[j] > time[j+1]) {
  997.           SWAP(source[j], source[j+1]);
  998.           SWAP(aspect[j], aspect[j+1]);
  999.           SWAP(dest[j], dest[j+1]);
  1000.           SWAP(time[j], time[j+1]);
  1001.           SWAP(sign[j], sign[j+1]);
  1002.           SWAP(isret[j], isret[j+1]);
  1003.           j--;
  1004.         }
  1005.       }
  1006.  
  1007.       /* Now loop through list and display all the transits. */
  1008.  
  1009.       for (i = 0; i < occurcount; i++) {
  1010.         k = smartcusp && IsCusp(dest[i]);
  1011.         if (k && aspect[i] > _OPP)
  1012.           continue;
  1013.         else
  1014.           k = k && aspect[i] == _OPP;
  1015.         s1 = time[i]/24/60;
  1016.         s3 = time[i]-s1*24*60;
  1017.         s2 = s3/60;
  1018.         s3 = s3-s2*60;
  1019.         SetSave(Mon2, s1+1, Yea2,
  1020.           DegToDec((real)(time[i]-s1*24*60) / 60.0), Zon2, Lon2, Lat2);
  1021.         fprintf(S, "%s %s ",
  1022.           CharDate(Mon2, s1+1, Yea2, FALSE), CharTime(s2, s3));
  1023.         PrintAspect(source[i], sign[i], isret[i], aspect[i],
  1024.           dest[i], ZTOS(planet3[dest[i]]), (int)Sgn(ret3[dest[i]]),
  1025.           prog ? 'u' : 't');
  1026.  
  1027.         /* Check for a Solar, Lunar, or any other return. */
  1028.  
  1029.         if (aspect[i] == _CON && source[i] == dest[i]) {
  1030.           AnsiColor(WHITE);
  1031.           fprintf(S, " (%s Return)", source[i] == _SUN ? "Solar" :
  1032.             (source[i] == _MOO ? "Lunar" : objectname[source[i]]));
  1033.         }
  1034.         printl();
  1035. #ifdef INTERPRET
  1036.         if (interpret)
  1037.           InterpretTransit(source[i], aspect[i], dest[i]);
  1038. #endif
  1039.         AnsiColor(DEFAULT);
  1040.       }
  1041.     }
  1042.   }
  1043. }
  1044.  
  1045.  
  1046. /* Given an arbitrary day, determine what aspects are made between this */
  1047. /* transiting chart and the given natal chart, as specified with the -T */
  1048. /* switch, and display the transits in order sorted by influence.       */
  1049.  
  1050. void DisplayTransitInfluence(prog)
  1051. int prog;
  1052. {
  1053.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  1054.   real power[MAXINDAY];
  1055.   byte ignore3[TOTAL+1];
  1056.   int occurcount = 0, i, j, k, l, m;
  1057.  
  1058.   /* Cast the natal and transiting charts as with a relationship chart. */
  1059.  
  1060.   for (i = 1; i <= SIGNS; i++)
  1061.     house1[i] = house[i];
  1062.   for (i = 1; i <= total; i++) {
  1063.     planet1[i] = planet[i];
  1064.     ret1[i] = ret[i];
  1065.   }
  1066.   SetCore(Mon2, Day2, Yea2, Tim2, Zon2, Lon2, Lat2);
  1067.   if (progress = prog) {
  1068.     Jdp = (real)MdyToJulian(MM, DD, YY);
  1069.     MM = Mon; DD = Day; YY = Yea;
  1070.   }
  1071.   CastChart(TRUE);
  1072.   for (i = 1; i <= SIGNS; i++)
  1073.     house2[i] = house[i];
  1074.   for (i = 1; i <= total; i++) {
  1075.     planet2[i] = planet[i];
  1076.     ret2[i] = ret[i];
  1077.   }
  1078.  
  1079.   /* Do a relationship aspect grid to get the transits. We have to make and */
  1080.   /* restore three changes to get it right for this chart. (1) We make the  */
  1081.   /* natal planets have zero velocity so applying vs. separating is only a  */
  1082.   /* function of the transiter. (2) We force applying vs. separating orbs   */
  1083.   /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */
  1084.   /* main restrictions to allow for transiting objects not restricted.      */
  1085.  
  1086.   for (i = 1; i <= total; i++) {
  1087.     ret[i] = ret1[i];
  1088.     ret1[i] = 0.0;
  1089.     ignore3[i] = ignore[i];
  1090.     ignore[i] = ignore[i] && ignore2[i];
  1091.   }
  1092.   i = exdisplay;
  1093.   exdisplay |= DASHga;
  1094.   CreateGridRelation(FALSE);
  1095.   exdisplay = i;
  1096.   for (i = 1; i <= total; i++) {
  1097.     ret1[i] = ret[i];
  1098.     ignore[i] = ignore3[i];
  1099.   }
  1100.  
  1101.   /* Loop through the grid, and build up a list of the valid transits. */
  1102.  
  1103.   for (i = 1; i <= BASE; i++) {
  1104.     if (ignore2[i] || !IsThing(i))
  1105.       continue;
  1106.     for (j = 1; j <= total; j++) {
  1107.       if (ignore[j] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  1108.         continue;
  1109.       if (smartcusp && k > _OPP && IsCusp(j))
  1110.         continue;
  1111.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  1112.       l = grid->v[i][j];
  1113.       power[occurcount] = transitinf[i]*
  1114.         ((j <= BASE ? objectinf[j] : 2.0)/4.0)*aspectinf[k]*
  1115.         (1.0-(real)abs(l)/60.0/Orb(i, j, k));
  1116.       occurcount++;
  1117.     }
  1118.   }
  1119.  
  1120.   /* After all transits located, sort them by their total power. */
  1121.  
  1122.   for (i = 1; i < occurcount; i++) {
  1123.     j = i-1;
  1124.     while (j >= 0 && power[j] < power[j+1]) {
  1125.       SWAP(source[j], source[j+1]);
  1126.       SWAP(aspect[j], aspect[j+1]);
  1127.       SWAP(dest[j], dest[j+1]);
  1128.       SwapReal(&power[j], &power[j+1]);
  1129.       j--;
  1130.     }
  1131.   }
  1132.  
  1133.   /* Now loop through list and display each transit in effect at the time. */
  1134.  
  1135.   for (i = 0; i < occurcount; i++) {
  1136.     k = aspect[i];
  1137.     l = source[i];
  1138.     fprintf(S, "%3d: ", i+1);
  1139.     j = ZTOS(planet2[l]);
  1140.     PrintAspect(l, j, (int)Sgn(ret2[l]), k,
  1141.       dest[i], ZTOS(planet1[dest[i]]), (int)Sgn(ret1[dest[i]]),
  1142.       prog ? 'U' : 'T');
  1143.     m = grid->v[l][dest[i]];
  1144.     AnsiColor(m < 0 ? WHITE : LTGRAY);
  1145.     fprintf(S, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  1146.       abs(m)/60, DEGR1, abs(m)%60);
  1147.     AnsiColor(DKGREEN);
  1148.     fprintf(S, " - power:%6.2f", power[i]);
  1149.     if (k == _CON && l == dest[i]) {       /* Print a small "R" for returns. */
  1150.       AnsiColor(WHITE);
  1151.       fprintf(S, " R");
  1152.     }
  1153.     printl();
  1154. #ifdef INTERPRET
  1155.     if (interpret)
  1156.       InterpretTransit(l, k, dest[i]);
  1157. #endif
  1158.     AnsiColor(DEFAULT);
  1159.   }
  1160. }
  1161.  
  1162.  
  1163. /* Given the zodiac location of a planet in the sky and its declination,   */
  1164. /* and a location on the Earth, compute the azimuth and altitude of where  */
  1165. /* on the local horizon sky the planet would appear to one at the given    */
  1166. /* location. A reference MC position at Greenwich is also needed for this. */
  1167.  
  1168. void EclToHorizon(azi, alt, planet, planetalt, lon, lat, mc)
  1169. real *azi, *alt, planet, planetalt, lon, lat, mc;
  1170. {
  1171.   real lonz, latz;
  1172.  
  1173.   lonz = DTOR(planet); latz = DTOR(planetalt);
  1174.   EclToEqu(&lonz, &latz);
  1175.   lonz = DTOR(Mod(RTOD(mc-lonz+lon)));
  1176.   lonz = DTOR(Mod(RTOD(lonz-lon+PI/2.0)));
  1177.   EquToLocal(&lonz, &latz, PI/2.0-lat);
  1178.   *azi = DEGREES-RTOD(lonz); *alt = RTOD(latz);
  1179. }
  1180.  
  1181.  
  1182. /* Display a list of planetary rising times relative to the local horizon */
  1183. /* for the day indicated in the chart information, as specified with the  */
  1184. /* -Zd switch. For the day, the time each planet rises (transits horizon  */
  1185. /* in East half of sky), sets (transits horizon in West), reaches its     */
  1186. /* zenith point (transits meridian in South half of sky), and nadirs      */
  1187. /* transits meridian in North), is displayed.                             */
  1188.  
  1189. void DisplayInDayHorizon()
  1190. {
  1191.   int source[MAXINDAY], type[MAXINDAY], time[MAXINDAY], sign[MAXINDAY],
  1192.     isret[MAXINDAY], occurcount, division, div, s1, s2, i, j;
  1193.   real planetalt1[TOTAL+1], planetalt2[TOTAL+1], azialt[MAXINDAY],
  1194.     divsiz, lon, lat, mc1, mc2, azi1, alt1, azi2, alt2, d, k;
  1195.  
  1196.   lon = DTOR(Mod(Lon)); lat = DTOR(Lat);
  1197.   division = divisions * 4;
  1198.   divsiz = 24.0/ (real) division*60.0;
  1199.   occurcount = 0;
  1200.  
  1201.   SetCore(Mon, Day, Yea, 0.0, Zon, Lon, Lat);
  1202.   CastChart(TRUE);
  1203.   mc2 = DTOR(planet[_MC]); k = DTOR(planetalt[_MC]);
  1204.   EclToEqu(&mc2, &k);
  1205.   for (i = 1; i <= SIGNS; i++) {
  1206.     house2[i] = house[i];
  1207.     inhouse2[i] = inhouse[i];
  1208.   }
  1209.   for (i = 1; i <= total; i++) {
  1210.     planet2[i] = planet[i];
  1211.     planetalt2[i] = planetalt[i];
  1212.     ret2[i] = ret[i];
  1213.   }
  1214.  
  1215.   /* Loop thorough the day, dividing it into a certain number of segments. */
  1216.   /* For each segment we get the planet positions at its endpoints.        */
  1217.  
  1218.   for (div = 1; div <= division; div++) {
  1219.     SetCore(Mon, Day, Yea,
  1220.       DegToDec(24.0*(real)div/(real)division), Zon, Lon, Lat);
  1221.     CastChart(TRUE);
  1222.     mc1 = mc2;
  1223.     mc2 = DTOR(planet[_MC]); k = DTOR(planetalt[_MC]);
  1224.     EclToEqu(&mc2, &k);
  1225.     for (i = 1; i <= SIGNS; i++) {
  1226.       house1[i] = house2[i]; inhouse1[i] = inhouse2[i];
  1227.       house2[i] = house[i];  inhouse2[i] = inhouse[i];
  1228.     }
  1229.     for (i = 1; i <= total; i++) {
  1230.       planet1[i] = planet2[i]; planet2[i] = planet[i];
  1231.       planetalt1[i] = planetalt2[i]; planetalt2[i] = planetalt[i];
  1232.       ret1[i] = ret2[i]; ret2[i] = ret[i];
  1233.     }
  1234.  
  1235.     /* For our segment, check to see if each planet during it rises, sets, */
  1236.     /* reaches its zenith, or reaches its nadir.                           */
  1237.  
  1238.     for (i = 1; i <= total; i++) if (!ignore[i] && IsThing(i)) {
  1239.       EclToHorizon(&azi1, &alt1, planet1[i], planetalt1[i], lon, lat, mc1);
  1240.       EclToHorizon(&azi2, &alt2, planet2[i], planetalt2[i], lon, lat, mc2);
  1241.       j = 0;
  1242.       /* Check for transits to the horizon. */
  1243.       if ((alt1 > 0.0) != (alt2 > 0.0)) {
  1244.         d = dabs(alt1)/(dabs(alt1)+dabs(alt2));
  1245.         k = Mod(azi1 + d*MinDifference(azi1, azi2));
  1246.         j = 1 + 2*(MinDistance(k, DEGHALF) < DEGQUAD);
  1247.       /* Check for transits to the meridian. */
  1248.       } else if (Sgn(MinDifference(azi1, DEGQUAD)) !=
  1249.         Sgn(MinDifference(azi2, DEGQUAD))) {
  1250.         j = 2 + 2*(MinDistance(azi1, DEGQUAD) < DEGQUAD);
  1251.         d = dabs(azi1 - (j > 2 ? DEGQUAD : 270.0))/MinDistance(azi1, azi2);
  1252.         k = alt1 + d*(alt2-alt1);
  1253.       }
  1254.       if (j && occurcount < MAXINDAY) {
  1255.         source[occurcount] = i;
  1256.         type[occurcount] = j;
  1257.         time[occurcount] = (int)(24.0*((real)(div-1)+d)/(real)division*60.0);
  1258.         sign[occurcount] = (int)Mod(planet1[i] +
  1259.           d*MinDifference(planet1[i], planet2[i]))/30 + 1;
  1260.         isret[occurcount] = (int)Sgn(ret1[i]) + (int)Sgn(ret2[i]);
  1261.         azialt[occurcount] = k;
  1262.         SetSave(Mon, Day, Yea, DegToDec((real)time[occurcount] / 60.0),
  1263.           Zon, Lon, Lat);
  1264.         occurcount++;
  1265.       }
  1266.     }
  1267.   }
  1268.  
  1269.   /* Sort each event in order of time when it happens during the day. */
  1270.  
  1271.   for (i = 1; i < occurcount; i++) {
  1272.     j = i-1;
  1273.     while (j >= 0 && time[j] > time[j+1]) {
  1274.       SWAP(source[j], source[j+1]);
  1275.       SWAP(type[j], type[j+1]);
  1276.       SWAP(time[j], time[j+1]);
  1277.       SWAP(sign[j], sign[j+1]);
  1278.       SWAP(isret[j], isret[j+1]);
  1279.       SwapReal(&azialt[j], &azialt[j+1]);
  1280.       j--;
  1281.     }
  1282.   }
  1283.  
  1284.   /* Finally display the list showing each event and when it occurs. */
  1285.  
  1286.   for (i = 0; i < occurcount; i++) {
  1287.     SetSave(Mon, Day, Yea,
  1288.       DegToDec((real)time[i] / 60.0), Zon, Lon, Lat);
  1289.     j = DayOfWeek(Mon, Day, Yea);
  1290.     AnsiColor(rainbowansi[j + 1]);
  1291.     fprintf(S, "(%c%c%c) ", DAYNAM(j));
  1292.     AnsiColor(DEFAULT);
  1293.     s1 = time[i]/60;
  1294.     s2 = time[i]-s1*60;
  1295.     fprintf(S, "%s %s ", CharDate(Mon, Day, Yea, FALSE), CharTime(s1, s2));
  1296.     AnsiColor(objectansi[source[i]]);
  1297.     fprintf(S, "%7.7s ", objectname[source[i]]);
  1298.     AnsiColor(signansi(sign[i]));
  1299.     fprintf(S, "%c%c%c%c%c ",
  1300.       isret[i] > 0 ? '(' : (isret[i] < 0 ? '[' : '<'), SIGNAM(sign[i]),
  1301.       isret[i] > 0 ? ')' : (isret[i] < 0 ? ']' : '>'));
  1302.     AnsiColor(elemansi[type[i]-1]);
  1303.     if (type[i] == 1)
  1304.       fprintf(S, "rises  ");
  1305.     else if (type[i] == 2)
  1306.       fprintf(S, "zeniths");
  1307.     else if (type[i] == 3)
  1308.       fprintf(S, "sets   ");
  1309.     else
  1310.       fprintf(S, "nadirs ");
  1311.     AnsiColor(DEFAULT);
  1312.     fprintf(S, " at ");
  1313.     if (type[i] & 1) {
  1314.       j = (int) (FRACT(azialt[i])*60.0);
  1315.       fprintf(S, "%3d%c%02d'", (int) azialt[i], DEGR1, j);
  1316.  
  1317.       /* For rising and setting events, we'll also display a direction  */
  1318.       /* vector to make the 360 degree azimuth value thought of easier. */
  1319.  
  1320.       azi1 = cos(DTOR(azialt[i])); alt1 = sin(DTOR(azialt[i]));
  1321.       if (dabs(azi1) < dabs(alt1)) {
  1322.         azi2 = dabs(azi1 / alt1); alt2 = 1.0;
  1323.       } else {
  1324.         alt2 = dabs(alt1 / azi1); azi2 = 1.0;
  1325.       }
  1326.       fprintf(S, " (%.2f%c %.2f%c)",
  1327.         alt2, alt1 < 0.0 ? 's' : 'n', azi2, azi1 > 0.0 ? 'e' : 'w');
  1328.     } else
  1329.       PrintAltitude(azialt[i]);
  1330.     printl();
  1331.   }
  1332. }
  1333.  
  1334.  
  1335. /* Print out an ephemeris - the positions of the planets (at the time in the */
  1336. /* current chart) each day during a specified month, as done with the -E     */
  1337. /* switch. Display the ephemeris for the whole year if -Ey is in effect.     */
  1338.  
  1339. void DisplayEphemeris()
  1340. {
  1341.   int M0, M1, M2, daysiz, i, j, k, s, d, m;
  1342.  
  1343.   /* If -Ey is in effect, then loop through all months in the whole year. */
  1344.  
  1345.   if (exdisplay & DASHEy) {
  1346.     M1 = 1; M2 = 12;
  1347.   } else
  1348.     M1 = M2 = Mon;
  1349.  
  1350.   /* Loop through the month or months in question, printing each ephemeris. */
  1351.  
  1352.   for (M0 = M1; M0 <= M2; M0++) {
  1353.     daysiz = DayInMonth(M0, Yea);
  1354.     printf(eurodate ? "Dy/Mo/Yr" : "Mo/Dy/Yr");
  1355.     for (k = 0, j = 1; j <= total; j++) {
  1356.       if (!ignore[j] && IsThing(j)) {
  1357.         fprintf(S, "  %c%c%c%c ", OBJNAM(j), objectname[j][3] != 0 ?
  1358.           objectname[j][3] : ' ');
  1359.         k++;
  1360.         if (column80 && k >= 10)
  1361.           j = total;
  1362.       }
  1363.     }
  1364.     printl();
  1365.     for (i = 1; i <= daysiz; i++) {
  1366.  
  1367.       /* Loop through each day in the month, casting a chart for that day. */
  1368.  
  1369.       SetCore(M0, i, Yea, Tim, Zon, Lon, Lat);
  1370.       CastChart(TRUE);
  1371.       fprintf(S, "%s ", CharDate(M0, i, Yea, -1));
  1372.       for (k = 0, j = 1; j <= total; j++)
  1373.         if (!ignore[j] && IsThing(j)) {
  1374.           AnsiColor(objectansi[j]);
  1375.           s = ZTOS(planet[j]);
  1376.           d = (int) planet[j] - (s-1)*30;
  1377.           m = (int) (FRACT(planet[j])*60.0);
  1378.           fprintf(S, "%2d%s%02d%c", d, signabbrev[s], m,
  1379.             ret[j] >= 0.0 ? ' ' : '.');
  1380.           k++;
  1381.           if (column80 && k >= 10)
  1382.             j = total;
  1383.         }
  1384.       printl();
  1385.       AnsiColor(DEFAULT);
  1386.     }
  1387.     if (M0 < M2)
  1388.       printl();
  1389.   }
  1390. }
  1391.  
  1392.  
  1393. /* Display a calendar for the given month in the chart, as specified with  */
  1394. /* with the -K switch. When color is on, the title is white, weekends are  */
  1395. /* highlighted in red, and the specific day in the chart is colored green. */
  1396.  
  1397. void DisplayCalendarMonth()
  1398. {
  1399.   int i, j, k;
  1400.  
  1401.   AnsiColor(WHITE);
  1402.   PrintTab(' ', 16-StringLen(monthname[Mon]) >> 1);
  1403.   fprintf(S, "%s%5d\n", monthname[Mon], Yea);
  1404.   for (i = 0; i < 7; i++)
  1405.     fprintf(S, "%c%c%c", dayname[i][0], dayname[i][1], i < 6 ? ' ' : '\n');
  1406.   j = DayOfWeek(Mon, 1, Yea);
  1407.   AnsiColor(DEFAULT);
  1408.   for (i = 0; i < j; i++) {
  1409.     if (i == 0)
  1410.       AnsiColor(RED);
  1411.     fprintf(S, "-- ");
  1412.     if (i == 0)
  1413.       AnsiColor(DEFAULT);
  1414.   }
  1415.   k = DayInMonth(Mon, Yea);
  1416.   for (i = 1; i <= k; i++) {
  1417.     if (i == (int)Day)
  1418.       AnsiColor(GREEN);
  1419.     else if (j == 0 || j == 6)
  1420.       AnsiColor(RED);
  1421.     fprintf(S, "%2d", i);
  1422.     if (j == 0 || j == 6 || i == Day)
  1423.       AnsiColor(DEFAULT);
  1424.     if (j < 6) {
  1425.       j++;
  1426.       printc(' ');
  1427.     } else {
  1428.       j = 0;
  1429.       printl();
  1430.     }
  1431.   }
  1432.   while (j > 0 && j < 7) {
  1433.     if (j == 6)
  1434.       AnsiColor(RED);
  1435.     j++;
  1436.     fprintf(S, "--%c", j < 7 ? ' ' : '\n');
  1437.   }
  1438.   AnsiColor(DEFAULT);
  1439. }
  1440.  
  1441.  
  1442. /* Display a calendar for the entire year given in the chart, as specified */
  1443. /* with the -Ky switch. This is just like twelve of the individual month   */
  1444. /* calendars above displayed together, with same color highlights and all. */
  1445.  
  1446. void DisplayCalendarYear()
  1447. {
  1448.   int r, w, c, m, d, dy, p[3], l[3], n[3];
  1449.  
  1450.   dy = DayOfWeek(1, 1, Yea);
  1451.   for (r = 0; r < 4; r++) {    /* Loop over one set of three months */
  1452.     AnsiColor(WHITE);
  1453.     for (c = 0; c < 3; c++) {
  1454.       m = r*3+c+1;
  1455.       PrintTab(' ', 16-StringLen(monthname[m]) >> 1);
  1456.       fprintf(S, "%s%5d", monthname[m], Yea);
  1457.       if (c < 2)
  1458.         PrintTab(' ', 20 + MONTHSPACE -
  1459.           (16-StringLen(monthname[m]) >> 1) - StringLen(monthname[m]) - 5);
  1460.     }
  1461.     printl();
  1462.     for (c = 0; c < 3; c++) {
  1463.       for (d = 0; d < 7; d++)
  1464.         fprintf(S, "%c%c%c", dayname[d][0], dayname[d][1],
  1465.           d < 6 || c < 2 ? ' ' : '\n');
  1466.       if (c < 2)
  1467.         PrintTab(' ', MONTHSPACE-1);
  1468.       m = r*3+c+1;
  1469.       p[c] = dy % 7;
  1470.       l[c] = DayInMonth(m, Yea);
  1471.       n[c] = 0;
  1472.       dy += l[c];
  1473.     }
  1474.     for (w = 0; w < 6; w++) {      /* Loop over one set of week rows */
  1475.       for (c = 0; c < 3; c++) {    /* Loop over one week in a month  */
  1476.         m = r*3+c+1;
  1477.         d = 0;
  1478.         if (w == 0)
  1479.           while (d < p[c]) {
  1480.             if (d == 0)
  1481.               AnsiColor(RED);
  1482.             fprintf(S, "-- ");
  1483.             if (d == 0)
  1484.               AnsiColor(DEFAULT);
  1485.             d++;
  1486.           }
  1487.         AnsiColor(DEFAULT);
  1488.         while (d < 7 && n[c] < l[c]) {
  1489.           n[c]++;
  1490.           if (n[c] == Day && m == Mon)
  1491.             AnsiColor(GREEN);
  1492.           else if (d == 0 || d == 6)
  1493.             AnsiColor(RED);
  1494.           fprintf(S, "%2d%c", n[c], d < 6 || c < 2 ? ' ' : '\n');
  1495.           if (d == 0 || d == 6 || (n[c] == Day && m == Mon))
  1496.             AnsiColor(DEFAULT);
  1497.           d++;
  1498.         }
  1499.         while (d < 7) {
  1500.           if (d == 0 || d == 6)
  1501.             AnsiColor(RED);
  1502.           fprintf(S, "--%c", d < 6 || c < 2 ? ' ' : '\n');
  1503.           if (d == 0)
  1504.             AnsiColor(DEFAULT);
  1505.           d++;
  1506.         }
  1507.         if (c < 2)
  1508.           PrintTab(' ', MONTHSPACE-1);
  1509.       }
  1510.     }
  1511.     if (r < 3)
  1512.       printl();
  1513.   }
  1514.   AnsiColor(DEFAULT);
  1515. }
  1516.  
  1517.  
  1518. /* Display either a biorhythm chart or the time difference in various units */
  1519. /* between two charts, i.e. two types of relationship "charts" that aren't  */
  1520. /* related in any way to planetary positions, as specified by either the    */
  1521. /* -rb or -rd switches, respectively.                                       */
  1522.  
  1523. void DisplayRelation()
  1524. {
  1525. #ifdef BIORHYTHM
  1526.   int i, j;
  1527.   real k, l;
  1528. #endif
  1529.  
  1530.   /* If we are calculating the difference between two dates, then display */
  1531.   /* the value and return, as with the -rd switch.                        */
  1532.  
  1533.   if (relation == DASHrd) {
  1534.     fprintf(S, "Differences between the dates in the two charts:\n");
  1535.     AnsiColor(rainbowansi[1]); fprintf(S, "Years  : %.0f\n", JD/365.25);
  1536.     AnsiColor(rainbowansi[2]); fprintf(S, "Months : %.0f\n", JD/(365.25/12));
  1537.     AnsiColor(rainbowansi[3]); fprintf(S, "Weeks  : %.0f\n", JD/7.0);
  1538.     AnsiColor(rainbowansi[4]); fprintf(S, "Days   : %.0f\n", JD);
  1539.     AnsiColor(rainbowansi[5]); fprintf(S, "Hours  : %.0f\n", JD*24.0);
  1540.     AnsiColor(rainbowansi[6]); fprintf(S, "Minutes: %.0f\n", JD*24.0*60.0);
  1541.     AnsiColor(rainbowansi[7]); fprintf(S, "Seconds: %.0f\n", JD*24.0*3600.0);
  1542.     AnsiColor(DEFAULT);
  1543.     return;
  1544.   }
  1545.  
  1546. #ifdef BIORHYTHM
  1547.   /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  1548.   /* someone born on the older date, at the time of the younger date. Loop */
  1549.   /* through the week preceeding and following the date in question.       */
  1550.  
  1551.   JD = floor(JD + ROUND);
  1552.   for (JD -= 7.0, i = -7; i <= 7; i++, JD += 1.0) {
  1553.     if (i == 0)
  1554.       AnsiColor(WHITE);
  1555.     else if (i == 1)
  1556.       AnsiColor(DEFAULT);
  1557.     fprintf(S, "T%c%d Day%c:",
  1558.       i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' ');
  1559.     for (j = 1; j <= 3; j++) {
  1560.       printc(' ');
  1561.       switch (j) {
  1562.       case 1: k = _PHY; AnsiColor(RED);   fprintf(S, "Physical");     break;
  1563.       case 2: k = _EMO; AnsiColor(BLUE);  fprintf(S, "Emotional");    break;
  1564.       case 3: k = _INT; AnsiColor(GREEN); fprintf(S, "Intellectual"); break;
  1565.       }
  1566.       AnsiColor(i ? DEFAULT : WHITE);
  1567.  
  1568.       /* The biorhythm calculation is below. */
  1569.  
  1570.       l = Biorhythm(JD, k);
  1571.       fprintf(S, " at %c%3.0f%%", l < 0.0 ? '-' : '+', dabs(l));
  1572.  
  1573.       /* Print smiley face, medium face, or sad face based on current cycle. */
  1574.  
  1575.       AnsiColor(PURPLE);
  1576.       fprintf(S, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  1577.       AnsiColor(i ? DEFAULT : WHITE);
  1578.       if (j < 3)
  1579.         printc(',');
  1580.     }
  1581.     printl();
  1582.   }
  1583. #endif /* BIORHYTHM */
  1584. }
  1585.  
  1586.  
  1587. /* Another important procedure: Display any of the types of (text) charts    */
  1588. /* that the user specified they wanted, by calling the appropriate routines. */
  1589.  
  1590. void PrintChart(prog)
  1591. {
  1592.   if (todisplay == 0)          /* Assume the -v chart if user */
  1593.     todisplay |= DASHv;        /* didn't indicate anything.   */
  1594.   if (todisplay & DASHv) {
  1595.     if (relation < DASHrd)
  1596.       ChartLocation();
  1597.     else
  1598.  
  1599.       /* If the -rb or -rd relationship charts are in effect, then instead  */
  1600.       /* of doing the standard -v chart, print either of these chart types. */
  1601.  
  1602.       DisplayRelation();
  1603.     if (todisplay - (todisplay & DASHv*2-1))
  1604.       printl2();
  1605.   }
  1606.   if (todisplay & DASHw) {
  1607.     ChartWheel();
  1608.     if (todisplay - (todisplay & DASHw*2-1))
  1609.       printl2();
  1610.   }
  1611.   if (todisplay & DASHg) {
  1612.     if (relation > DASHr0) {
  1613.       CreateGrid(FALSE);
  1614.       ChartGrid();
  1615.       if (exdisplay & DASHg0) {    /* If -g0 switch in effect, then  */
  1616.         printl();                  /* display aspect configurations. */
  1617.         DisplayGrands();
  1618.       }
  1619.     } else {
  1620.  
  1621.       /* Do a relationship aspect grid between two charts if -r0 in effect. */
  1622.  
  1623.       CreateGridRelation((exdisplay & DASHg0) > 0);
  1624.       DisplayGridRelation();
  1625.     }
  1626.     if (todisplay - (todisplay & DASHg*2-1))
  1627.       printl2();
  1628.   }
  1629.   if (todisplay & DASHm) {
  1630.     if (!(todisplay & DASHg) || relation <= DASHr0)
  1631.       CreateGrid(FALSE);
  1632.     if (relation > DASHr0) {
  1633.       if (exdisplay & DASHm0)
  1634.         ChartAspect();
  1635.       else
  1636.         ChartMidpoint();
  1637.       if (todisplay - (todisplay & DASHm*2-1))
  1638.         printl2();
  1639.     } else {
  1640.       CreateGridRelation((exdisplay & DASHm0) == 0);
  1641.       if (exdisplay & DASHm0)
  1642.         DisplayAspectRelation();
  1643.       else
  1644.         DisplayMidpointRelation();
  1645.     }
  1646.   }
  1647.   if (todisplay & DASHZ) {
  1648.     if (exdisplay & DASHZd)
  1649.       DisplayInDayHorizon();
  1650.     else
  1651.       ChartHorizon();
  1652.     if (todisplay - (todisplay & DASHZ*2-1))
  1653.       printl2();
  1654.   }
  1655.   if (todisplay & DASHS) {
  1656.     ChartSpace();
  1657.     if (todisplay - (todisplay & DASHS*2-1))
  1658.       printl2();
  1659.   }
  1660.   if (todisplay & DASHj) {
  1661.     ChartInfluence();
  1662.     if (todisplay - (todisplay & DASHj*2-1))
  1663.       printl2();
  1664.   }
  1665.   if (todisplay & DASHL) {
  1666.     ChartAstroGraph();
  1667.     if (todisplay - (todisplay & DASHL*2-1))
  1668.       printl2();
  1669.   }
  1670.   if (todisplay & DASHK) {
  1671.     if (exdisplay & DASHKy)
  1672.       DisplayCalendarYear();
  1673.     else
  1674.       DisplayCalendarMonth();
  1675.     if (todisplay - (todisplay & DASHK*2-1))
  1676.       printl2();
  1677.   }
  1678.   if (todisplay & DASHd) {
  1679.     DisplayInDaySearch(prog);
  1680.     if (todisplay - (todisplay & DASHd*2-1))
  1681.       printl2();
  1682.   }
  1683.   if (todisplay & DASHD) {
  1684.     DisplayInDayInfluence();
  1685.     if (todisplay - (todisplay & DASHD*2-1))
  1686.       printl2();
  1687.   }
  1688.   if (todisplay & DASHE) {
  1689.     DisplayEphemeris();
  1690.     if (todisplay - (todisplay & DASHE*2-1))
  1691.       printl2();
  1692.   }
  1693.   if (todisplay & DASHt) {
  1694.     DisplayTransitSearch(prog);
  1695.     if (todisplay - (todisplay & DASHt*2-1))
  1696.       printl2();
  1697.   }
  1698.   if (todisplay & DASHT)
  1699.     DisplayTransitInfluence(prog);
  1700. }
  1701.  
  1702. /* options.c */
  1703.