Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / zotnet / tws / phoon / phoon.c
1 /* phoon - show the phase of the moon
2
3 ver  date   who remarks
4 --- ------- --- -------------------------------------------------------------
5 01A 08nov86 JP  Translated from the ratfor version of 12nov85, which itself
6                   was translated from the Pascal version of 05apr79.
7
8 Copyright (C) 1986 by Jeffrey A. Poskanzer.  Permission to use, copy,
9 modify, and distribute this software and its documentation for any
10 purpose and without fee is hereby granted, provided that this copyright
11 notice appear in all copies and in all supporting documentation.  No
12 representation is made about the suitability of this software for any
13 purpose.  It is provided "as is" without express or implied warranty.
14
15 */
16
17 static char copyright[] = "\nCopyright (C) 1986 by Jeffrey A. Poskanzer.\n";
18
19
20 #include <stdio.h>
21 #include <math.h>
22 #include "tws.h"
23
24
25 /* Global defines and declarations. */
26
27 #define SECSPERMINUTE 60
28 #define SECSPERHOUR (60 * SECSPERMINUTE)
29 #define SECSPERDAY (24 * SECSPERHOUR)
30
31 #define PI 3.14159
32
33 #define NUMLINES 23
34 #define ASPECTRATIO 0.5
35 #define MOONSTARTCOL 18
36 #define QUARTERLITLEN 16
37 #define QUARTERLITLENPLUSONE 17
38
39
40 /* Main program. */
41
42 main( argc, argv, envp )
43 int argc;
44 char *argv[], *envp[];
45     {
46     struct tws t, *twp;
47     char buf[100];
48
49     /* Figure out what date and time to use. */
50     if ( argc == 1 )
51         {
52         /* No arguments present - use the current date and time. */
53         twscopy( &t, dtwstime( ) );
54         }
55     else if ( argc == 2 || argc == 3 || argc == 4 )
56         {
57         /* One, two, or three args - use them. */
58         strcpy( buf, argv[1] );
59         if ( argc > 2 )
60             {
61             strcat( buf, " " );
62             strcat( buf, argv[2] );
63             if ( argc > 3 )
64                 {
65                 strcat( buf, " " );
66                 strcat( buf, argv[3] );
67                 }
68             }
69         twp = dparsetime( buf );
70         if ( twp == NULL || twp -> tw_flags & TW_JUNK )
71             {
72             fprintf( stderr, "illegal date/time: %s\n", buf );
73             exit( 1 );
74             }
75         twscopy( &t, twp );
76         }
77     else
78         {
79         /* Too many args! */
80         fprintf( stderr, "usage:  %s  [ <date/time> ]\n", argv[0] );
81         exit( 1 );
82         }
83
84     /* Pseudo-randomly decide what the moon is made of, and print it. */
85     if ( twclock( dtwstime( ) ) % 17 == 3 )
86         putmoon( &t, "GREENCHEESE" );
87     else
88         putmoon( &t, "@" );
89
90     /* All done. */
91     exit( 0 );
92     }
93
94
95 putmoon( t, atfiller )
96 struct tws *t;
97 char *atfiller;
98     {
99     struct tws twsanewmoon;
100     long secsynodic = 29*SECSPERDAY + 12*SECSPERHOUR + 44*SECSPERMINUTE + 3;
101     long secdiff, secphase;
102     int atflrlen, atflridx, lin, col, midlin, qlitidx;
103     float angphase, mcap, yrad, xrad, y, xright, xleft;
104     int colright, colleft, i;
105     char c;
106
107     static char background[NUMLINES][47] = {
108         "                 .------------.                ",
109         "             .--'  o     . .   `--.            ",
110         "          .-'   .    O   .       . `-.         ",
111         "       .-'@   @@@@@@@   .  @@@@@      `-.      ",
112         "      /@@@  @@@@@@@@@@@   @@@@@@@   .    \\     ",
113         "    ./    o @@@@@@@@@@@   @@@@@@@       . \\.   ",
114         "   /@@  o   @@@@@@@@@@@.   @@@@@@@   O      \\  ",
115         "  /@@@@   .   @@@@@@@o    @@@@@@@@@@     @@@ \\ ",
116         "  |@@@@@               . @@@@@@@@@@@@@ o @@@@| ",
117         " /@@@@@  O  `.-./  .      @@@@@@@@@@@@    @@  \\",
118         " | @@@@    --`-'       o     @@@@@@@@ @@@@    |",
119         " |@ @@@        `    o      .  @@   . @@@@@@@  |",
120         " |       @@            .-.     @@@   @@@@@@@  |",
121         " \\  . o        @@@     `-'   . @@@@   @@@@  o /",
122         "  |      @@   @@@@@ .           @@   .       | ",
123         "  \\     @@@@  @\\@@    /  .  O    .     o   . / ",
124         "   \\  o  @@     \\ \\  /         .    .       /  ",
125         "    `\\     .    .\\.-.___   .      .   .-. /'   ",
126         "      \\           `-'                `-' /     ",
127         "       `-.   o   / |     o    O   .   .-'      ",
128         "          `-.   /     .       .    .-'         ",
129         "             `--.       .      .--'            ",
130         "                 `------------'                " };
131
132     static char qlits[8][16] = {
133         "New Moon +     ",
134         "First Quarter +",
135         "Full Moon +    ",
136         "Last Quarter + ",
137         "First Quarter -",
138         "Full Moon -    ",
139         "Last Quarter - ",
140         "New Moon -     " };
141
142
143     /* Find the length of the atfiller string. */
144     atflrlen = strlen( atfiller );
145
146     /* Convert a new moon date from a string to a tws. */
147     twscopy( &twsanewmoon, dparsetime( "05jan81 23:24:00 PST" ) );
148
149     /* Subtract the new moon date from the desired date to get the interval
150        since the new moon. */
151     secdiff = twsubtract( t, &twsanewmoon );
152
153     /* Figure out the phase - the interval since the last new moon. */
154     secphase = secdiff % secsynodic;
155     if ( secphase < 0L )
156         secphase += secsynodic;  /* fucking mathematician language designers */
157     angphase = (float) secphase / (float) secsynodic * 2.0 * PI;
158     mcap = -cos( angphase );
159
160     /* Figure out how big the moon is. */
161     yrad = NUMLINES / 2.0;
162     xrad = yrad / ASPECTRATIO;
163
164     /* Figure out some other random stuff. */
165     midlin = NUMLINES / 2;
166     qlitidx = angphase / PI * 2.0;
167
168     /* Now output the moon, a slice at a time. */
169     atflridx = 0;
170     for ( lin = 0; lin < NUMLINES; lin = lin + 1 )
171         {
172         /* Compute the edges of this slice. */
173         y = lin + 0.5 - yrad;
174         xright = xrad * sqrt( 1.0 - ( y * y ) / ( yrad * yrad ) );
175         xleft = -xright;
176         if ( angphase >= 0.0 && angphase < PI )
177             xleft = mcap * xleft;
178         else
179             xright = mcap * xright;
180         colleft = (int) (xrad + 0.5) + (int) (xleft + 0.5);
181         colright = (int) (xrad + 0.5) + (int) (xright + 0.5);
182
183         /* Now output the slice. */
184         for ( i = 0; i < colleft; i++ )
185             putchar( ' ' );
186         for ( col = colleft; col <= colright; col = col + 1 )
187             if ( ( c = background[lin][col] ) != '@' )
188                 putchar( c );
189             else
190                 {
191                 putchar( atfiller[atflridx] );
192                 atflridx = (atflridx + 1) % atflrlen;
193                 }
194
195         /* Output the end-of-line information, if any. */
196         if ( lin == midlin - 2 )
197             {
198             putchar( '\t' );
199             putchar( '\t' );
200             fputs( qlits[qlitidx], stdout );
201             }
202         else if ( lin == midlin - 1)
203             {
204             putchar( '\t' );
205             putchar( '\t' );
206             putseconds( secphase % (secsynodic / 4) );
207             }
208         else if ( lin == midlin )
209             {
210             putchar( '\t' );
211             putchar( '\t' );
212             fputs( qlits[qlitidx + 4], stdout );
213             }
214         else if ( lin == midlin + 1 )
215             {
216             putchar( '\t' );
217             putchar( '\t' );
218             putseconds( (secsynodic - secphase) % (secsynodic / 4) );
219             }
220
221         putchar( '\n' );
222         }
223
224     }
225
226
227 putseconds( secs )
228 long secs;
229     {
230     long days, hours, minutes;
231
232     days = secs / SECSPERDAY;
233     secs = secs - days * SECSPERDAY;
234     hours = secs / SECSPERHOUR;
235     secs = secs - hours * SECSPERHOUR;
236     minutes = secs / SECSPERMINUTE;
237     secs = secs - minutes * SECSPERMINUTE;
238
239     printf( "%ld %2ld:%02ld:%02ld", days, hours, minutes, secs );
240     }