home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource1 / ast40dos / general.c < prev    next >
C/C++ Source or Header  |  1994-01-04  |  24KB  |  818 lines

  1. /*
  2. ** Astrolog (Version 4.00) File: general.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. ** General Functions.
  44. ******************************************************************************
  45. */
  46.  
  47. /* Swap two real floating point values. */
  48.  
  49. void SwapReal(d1, d2)
  50. real *d1, *d2;
  51. {
  52.   real temp;
  53.  
  54.   temp = *d1; *d1 = *d2; *d2 = temp;
  55. }
  56.  
  57.  
  58. /* Return the length of a string. */
  59.  
  60. int StringLen(line)
  61. char *line;
  62. {
  63.   int i;
  64.  
  65.   for (i = 0; *line++; i++)
  66.     ;
  67.   return i;
  68. }
  69.  
  70.  
  71. /* Return whether one string is greater than another. */
  72.  
  73. int StringCmp(s1, s2)
  74. char *s1, *s2;
  75. {
  76.   while (*s1 && *s1 == *s2)
  77.     s1++, s2++;
  78.   return *s1 - *s2;
  79. }
  80.  
  81.  
  82. /* Determine the sign of a number: -1 if value negative, +1 if value */
  83. /* positive, and 0 if it's zero.                                     */
  84.  
  85. real Sgn(d)
  86. real d;
  87. {
  88.   return d == 0.0 ? 0.0 : SGN2(d);
  89. }
  90.  
  91.  
  92. /* Given an x and y coordinate, return the angle formed by a line from the */
  93. /* origin to this coordinate. This is just converting from rectangular to  */
  94. /* polar coordinates; however, we don't determine the radius here.         */
  95.  
  96. real Angle(x, y)
  97. real x, y;
  98. {
  99.   real a;
  100.  
  101.   if (x != 0.0)
  102.     a = ATAN(y/x);
  103.   else
  104.     a = Sgn(y)*PI/2.0;
  105.   if (a < 0.0)
  106.     a += PI;
  107.   if (y < 0.0)
  108.     a += PI;
  109.   return a;
  110. }
  111.  
  112.  
  113. /* Modulus function for floating point values. The modulus value itself */
  114. /* has been specified earlier: it is usually either 360.0 or PI/2.0.    */
  115.  
  116. real Mod(d)
  117. real d;
  118. {
  119.   if (d > modulus)         /* In most cases, our value is only slightly */
  120.     d -= modulus;          /* out of range, so we can test for it and   */
  121.   else if (d < modulus)    /* avoid the more complicated arithmetic.    */
  122.     d += modulus;
  123.   if (d >= 0 && d < modulus)
  124.     return d;
  125.   return (d - floor(d/modulus)*modulus);
  126. }
  127.  
  128.  
  129. /*
  130. ******************************************************************************
  131. ** General Astrology Functions.
  132. ******************************************************************************
  133. */
  134.  
  135. /* A similar modulus function: convert an integer to value from 1..12. */
  136.  
  137. int Mod12(i)
  138. int i;
  139. {
  140.   while (i > SIGNS)
  141.     i -= SIGNS;
  142.   while (i < 1)
  143.     i += SIGNS;
  144.   return i;
  145. }
  146.  
  147.  
  148. /* Convert an inputed fractional degrees/minutes value to a true decimal   */
  149. /* degree quantity. For example, the user enters the decimal value "10.30" */
  150. /* to mean 10 degrees and 30 minutes; this will return 10.5, i.e. 10       */
  151. /* degrees and 30 minutes expressed as a floating point degree value.      */
  152.  
  153. real DecToDeg(d)
  154. real d;
  155. {
  156.   return Sgn(d)*(floor(dabs(d))+FRACT(dabs(d))*100.0/60.0);
  157. }
  158.  
  159.  
  160. /* This is the inverse of the above function. Given a true decimal value */
  161. /* for a zodiac degree, adjust it so the degrees are in the integer part */
  162. /* and the minute expressed as hundredths, e.g. 10.5 degrees -> 10.30    */
  163.  
  164. real DegToDec(d)
  165. real d;
  166. {
  167.   return Sgn(d)*(floor(dabs(d))+FRACT(dabs(d))*60.0/100.0);
  168. }
  169.  
  170.  
  171. /* Return the shortest distance between two degrees in the zodiac. This is  */
  172. /* normally their difference, but we have to check if near the Aries point. */
  173.  
  174. real MinDistance(deg1, deg2)
  175. real deg1, deg2;
  176. {
  177.   real i;
  178.  
  179.   i = dabs(deg1-deg2);
  180.   return i < DEGHALF ? i : DEGREES - i;
  181. }
  182.  
  183.  
  184. /* This is just like the above routine, except the min distance value  */
  185. /* returned will either be positive or negative based on whether the   */
  186. /* second value is ahead or behind the first one in a circular zodiac. */
  187.  
  188. real MinDifference(deg1, deg2)
  189. real deg1, deg2;
  190. {
  191.   real i;
  192.  
  193.   i = deg2 - deg1;
  194.   if (dabs(i) < DEGHALF)
  195.     return i;
  196.   return Sgn(i)*(dabs(i) - DEGREES);
  197. }
  198.  
  199.  
  200. /* Return the degree of the midpoint between two zodiac positions, making */
  201. /* sure we return the true midpoint closest to the positions in question. */
  202.  
  203. real Midpoint(deg1, deg2)
  204. real deg1, deg2;
  205. {
  206.   real mid;
  207.  
  208.   mid = (deg1+deg2)/2.0;
  209.   return MinDistance(deg1, mid) < DEGQUAD ? mid : Mod(mid+DEGHALF);
  210. }
  211.  
  212.  
  213. /* Given a planet and sign, determine whether: The planet rules the sign, */
  214. /* the planet has its fall in the sign, the planet exalts in the sign, or */
  215. /* is debilitated in the sign; and return an appropriate character.       */
  216.  
  217. char Dignify(body, sign)
  218. int body, sign;
  219. {
  220.   if (body > U_HI)
  221.     return ' ';
  222.   if (ruler1[body] == sign || ruler2[body] == sign)
  223.     return 'R';
  224.   if (ruler1[body] == Mod12(sign+6) || ruler2[body] == Mod12(sign+6))
  225.     return 'F';
  226.   if (exalt[body] == sign)
  227.     return 'e';
  228.   if (exalt[body] == Mod12(sign+6))
  229.     return 'd';
  230.   return '-';
  231. }
  232.  
  233.  
  234. /* Determine the number of days in a particular month. The year is needed, */
  235. /* too, because we have to check for leap years in the case of February.   */
  236.  
  237. int DayInMonth(month, year)
  238. int month, year;
  239. {
  240.   return (month == 9 || month == 4 || month == 6 || month == 11 ? 30 :
  241.     (month != 2 ? 31 : 28 +
  242.     (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))));
  243. }
  244.  
  245.  
  246. /* Given an aspect and two objects making that aspect with each other,   */
  247. /* return the maximum orb allowed for such an aspect. Normally this only */
  248. /* depends on the aspect itself, but some objects require narrow orbs,   */
  249. /* and some allow wider orbs, so check for these cases.                  */
  250.  
  251. real Orb(body1, body2, aspect)
  252. int body1, body2, aspect;
  253. {
  254.   real orb, i;
  255.  
  256.   orb = aspectorb[aspect];
  257.   i = body1 > BASE ? 2.0 : planetorb[body1];
  258.   orb = MIN(orb, i);
  259.   i = body2 > BASE ? 2.0 : planetorb[body2];
  260.   orb = MIN(orb, i);
  261.   if (body1 <= BASE)
  262.     orb += planetadd[body1];
  263.   if (body2 <= BASE)
  264.     orb += planetadd[body2];
  265.   return orb;
  266. }
  267.  
  268.  
  269. /*
  270. ******************************************************************************
  271. ** File IO Routines.
  272. ******************************************************************************
  273. */
  274.  
  275. /* Exit the program, and do any cleanup necessary. Note that if we had     */
  276. /* a non-fatal error, and we are in the -Q loop mode, then we won't        */
  277. /* actually terminate the program, but drop back to the command line loop. */
  278.  
  279. void Terminate(value)
  280. int value;
  281. {
  282.   if (value == _FORCE) {
  283.     AnsiColor(WHITE);
  284.     fprintf(stdout, "\n%s terminated.\n", appname);
  285.   }
  286.   if (value == _ERROR && (operation & DASHQ) > 0)
  287.     return;
  288.   if (ansi)
  289.     fprin