1 /*
2  * Copyright (c) 1991 Paul J. Drongowski.
3  * Copyright (c) 1992 Joe Dellinger.
4  * Copyright (c) 2005 Eric S. Raymond.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 /*
31  * Return-Path: <pjd@cadillac.siemens.com>
32  * Received: from cadillac.siemens.com by montebello.soest.hawaii.edu (4.1/montebello-MX-1.9)
33  *      id AA01487; Mon, 10 Aug 92 03:21:41 HST
34  * Received: from kevin.siemens.com by cadillac.siemens.com (4.1/SMI-4.0)
35  *      id AA25847; Mon, 10 Aug 92 09:21:37 EDT
36  * Date: Mon, 10 Aug 92 09:21:37 EDT
37  * From: pjd@cadillac.siemens.com (paul j. drongowski)
38  * Message-Id: <9208101321.AA25847@cadillac.siemens.com>
39  * To: joe@montebello.soest.hawaii.edu
40  * Status: RO
41  */
42 
43 /*
44  * This copy is slightly hacked by Joe Dellinger, August 1992
45  * And some more... November 1992
46  *
47  * Partially re-written by "murray@vs6.scri.fsu.edu"
48  * to use better grammar and to avoid some nonsensical
49  * responses (like claiming to be a person who's been licensed
50  * longer than they've been alive!), Jan 1994
51  *
52  * Those improvements merged with others by Joe Dellinger, Oct 1994
53  */
54 
55 /*
56  * Generate QSO
57  */
58 
59 /*
60  * When run, this program generates a single QSO. The form of the
61  * QSO is similar to QSO's one would expect to hear at a code test.
62  * It begins with a series of V's (commented out in this version),
63  * callsigns of the receiver and
64  * sender, followed by a few sentences about weather, name,
65  * occupation, etc. The QSO ends with the callsigns of the receiver
66  * and sender.
67  *
68  * All output is produced using "printf." This should make the
69  * program easy to port. Output can be piped into another program
70  * such as sparc-morse on the Sun or it can be redirected into
71  * a file (without viewing the contents of course!)
72  *
73  * The program design is similar to a "random poetry generator"
74  * or "mad-libs." Each QSO form is generated by its own C function,
75  * such as "PutForm1." Each function calls other C functions to
76  * produce the sentences in the QSO. The sentence forms are
77  * selected somewhat randomly as well as any blanks to be filled.
78  * Words and phrases are selected from several lists such as
79  * "Transceiver," "Antenna," "Job," etc. Sometimes this scheme is
80  * clever as in the formation of city names. Sometimes it is
81  * stupidly simple-minded and grammatical agreement is lost.
82  * By the way, the callsigns are real and were picked from
83  * rec.radio.amateur.misc on USENET.
84  *
85  * The program was constructed in C for Sun workstations. It uses
86  * the library function "drand48" in function "Roll" to produce
87  * pseudo-random numbers. The library function "srand48" and "time"
88  * in "main" are used to set the pseudo-random number seed.
89  *
90  * Known problems and caveats? Hey, it`s software! All Morse
91  * training programs handle the procedural signs (e.g., AR, SK)
92  * differently. The function "PutQSO" currently prints "+ %"
93  * for the AR and SK at the end of the QSO. These may be ignored,
94  * mapped into something else, or just plain cause your training
95  * program to roll over and play dead. I don`t know. This is a
96  * cheap hack.
97  *
98  * And speaking of cheap... The program will not generate all
99  * characters and pro-signs that are found on an "official" code
100  * test. This program is for practice only and should be supplemented
101  * with lots of random code.
102  *
103  * Always have fun!
104  */
105 
106 
107 #include <sys/types.h>
108 #include <stdio.h>
109 #include <time.h>
110 
111 char *A_Or_An (char *);
112 char *Choose (char *Words[], int Number);
113 int License_Seed (void);
114 
115 int their_age;			/* PERSON'S AGE, SO THEY AREN'T LICENSED MORE
116                                  * THAN THEIR AGE */
117 
118 extern char *Transceiver[];
119 extern char *Antenna[];
120 extern char *UpFeet[];
121 extern char *Weather1[];
122 extern char *Weather2[];
123 extern char *Power[];
124 extern char *Job[];
125 extern char *Name[];
126 extern char *CallSign[];
127 extern char *License[];
128 extern char *City[];
129 extern char *NewCity[];
130 extern char *CityHeights[];
131 extern char *New[];
132 extern char *Heights[];
133 extern char *State[];
134 extern char *Frqmisc[];
135 extern char *Callmisc[];
136 extern char *NumMisc[];
137 extern char *Miscellaneous[];
138 extern char *RST[];
139 
140 int NXCVR;
141 int NANTENNA;
142 int NUPFEET;
143 int NWX1;
144 int NWX2;
145 int NPOWER;
146 int NJOB;
147 int NNAME;
148 int NCALLSIGN;
149 char *Sender, *Receiver;
150 int NLICENSE;
151 int NCITY;
152 int NNEWCITY;
153 int NCITYHTS;
154 int NNEW;
155 int NHEIGHTS;
156 int NSTATE;
157 int NFRQMISC;
158 int NFRQCALLMISC;
159 
160 char *FrqCallmisc[] =
161 {
162     "QRW %s %d",
163     "QRZ %s %d",
164     "QSN %s %d",
165     "QSX %s %d",
166     "QRW %s %d?",
167     "QRZ %s %d?",
168     "QSN %s %d?",
169     "QSX %s %d?",
170     0
171 };
172 
173 int NCALLMISC;
174 int NNUMMISC;
175 int NMISC;
176 int NRST;
177 
178 
179 /*
180  *************************************
181  * Routines to put sentences/clauses *
182  *************************************
183   */
184 
185 void
PutMisc(void)186 PutMisc (void)
187 {
188     printf ("%s\n", Choose (Miscellaneous, NMISC));
189 }
190 
191 void
PutThanks(void)192 PutThanks (void)
193 {
194     switch (Roll (6))
195       {
196       case 2:
197 	  printf ("Thanks for your call.\n");
198 	  break;
199 
200       case 3:
201 	  printf ("Tnx for ur call.\n");
202 	  break;
203 
204       case 4:
205 	  printf ("Tnx for the call.\n");
206 	  break;
207 
208       case 5:
209 	  printf ("Thanks for the call.\n");
210 	  break;
211 
212       default:
213 	  printf ("Thanks %s for the call.\n", Choose (Name, NNAME));
214 	  break;
215       }
216 }
217 
218 void
PutName(void)219 PutName (void)
220 {
221     switch (Roll (6))
222       {
223       case 2:
224 	  printf ("Name is %s.\n", Choose (Name, NNAME));
225 	  break;
226 
227       case 4:
228 	  printf ("This is %s.\n", Choose (Name, NNAME));
229 	  break;
230 
231       case 5:
232 	  printf ("%s here.\n", Choose (Name, NNAME));
233 	  break;
234 
235       default:
236 	  printf ("My name is %s.\n", Choose (Name, NNAME));
237 	  break;
238       }
239 }
240 
241 void
PutJob(void)242 PutJob (void)
243 {
244     switch (Roll (20))
245       {
246       case 2:
247       case 3:
248 	  printf ("My occupation is %s.\n", Choose (Job, NJOB));
249 	  break;
250 
251       case 4:
252       case 5:
253 	  printf ("I work as %s.\n", A_Or_An (Choose (Job, NJOB)));
254 	  break;
255 
256       case 6:
257 	  printf ("I was %s, now unemployed.\n", A_Or_An (Choose (Job, NJOB)));
258 	  break;
259 
260       case 11:
261       case 12:
262 	  printf ("Occupation is %s.\n", Choose (Job, NJOB));
263 	  break;
264 
265       default:
266 	  printf ("I am %s.\n", A_Or_An (Choose (Job, NJOB)));
267 	  break;
268       }
269 }
270 
271 void
PutAge(void)272 PutAge (void)
273 {
274 
275     their_age = Roll (60) + 16;
276 
277     switch (Roll (5))
278       {
279       case 3:
280 	  printf ("My age is %d.\n", their_age);
281 	  break;
282 
283       case 4:
284 	  printf ("I am %d years old.\n", their_age);
285 	  break;
286 
287       default:
288 	  printf ("Age is %d.\n", their_age);
289 	  break;
290       }
291 }
292 
293 void
PutLicense(void)294 PutLicense (void)
295 {
296 int get_years_licence;
297 
298     get_years_licence = Roll (License_Seed ());
299     if (get_years_licence < 2)
300 	get_years_licence = 2;
301 
302     switch (Roll (12))
303       {
304       case 1:
305 	  printf ("I have %s class licence.\n",
306 		  A_Or_An (Choose (License, NLICENSE)));
307 	  break;
308 
309       case 2:
310 	  printf ("I am %s license ham.\n",
311 		  A_Or_An (Choose (License, NLICENSE)));
312 	  break;
313 
314       case 3:
315 	  printf ("I am %s licence ham.\n",
316 		  A_Or_An (Choose (License, NLICENSE)));
317 	  break;
318 
319       case 4:
320 	  printf ("I have been licenced %d years as %s class.\n",
321 		  get_years_licence, Choose (License, NLICENSE));
322 	  break;
323 
324       case 5:
325 	  printf ("I have %s class license.\n",
326 		  A_Or_An (Choose (License, NLICENSE)));
327 	  break;
328 
329       case 6:
330 	  printf ("I am %s class ham.\n",
331 		  A_Or_An (Choose (License, NLICENSE)));
332 	  break;
333 
334       case 7:
335 	  printf ("I have been licensed %d years as %s class.\n",
336 		  get_years_licence, Choose (License, NLICENSE));
337 	  break;
338 
339       default:
340 	  printf ("I have been %s class ham for %d years.\n",
341 		  A_Or_An (Choose (License, NLICENSE)), get_years_licence);
342 	  break;
343       }
344 }
345 
346 void
PutTemperature(void)347 PutTemperature (void)
348 {
349     printf ("Temperature is %d.\n", Roll (80) + 10);
350 }
351 
352 void
PutWeather1(void)353 PutWeather1 (void)
354 {
355     switch (Roll (17))
356       {
357       case 2:
358 	  printf ("WX is %s.\n", Choose (Weather1, NWX1));
359 	  PutTemperature ();
360 	  break;
361 
362       case 3:
363 	  printf ("Weather here is %s.\n", Choose (Weather1, NWX1));
364 	  break;
365 
366       case 4:
367 	  printf ("Weather is %s.\n", Choose (Weather1, NWX1));
368 	  break;
369 
370       case 5:
371 	  printf ("WX is %s.\n", Choose (Weather1, NWX1));
372 	  break;
373 
374       case 6:
375 	  PutTemperature ();
376 	  printf ("Weather here is %s.\n", Choose (Weather1, NWX1));
377 	  break;
378 
379       case 7:
380 	  PutTemperature ();
381 	  printf ("Weather is %s.\n", Choose (Weather1, NWX1));
382 	  break;
383 
384       case 8:
385 	  PutTemperature ();
386 	  printf ("WX is %s.\n", Choose (Weather1, NWX1));
387 	  break;
388 
389       case 9:
390 	  printf ("Weather here is %s and temperature is %d.\n",
391 		  Choose (Weather1, NWX1), Roll (80) + 10);
392 	  break;
393 
394       case 10:
395 	  printf ("Weather is %s, temperature %d.\n",
396 		  Choose (Weather1, NWX1), Roll (80) + 10);
397 	  break;
398 
399       case 11:
400 	  printf ("WX is %d degrees and %s.\n",
401 		  Roll (80) + 10, Choose (Weather1, NWX1));
402 	  break;
403 
404       case 12:
405 	  printf ("The WX is %s and the temp is %d degrees.\n",
406 		  Choose (Weather1, NWX1), Roll (80) + 10);
407 	  break;
408 
409       case 14:
410 	  printf ("Weather is %s.\n", Choose (Weather1, NWX1));
411 	  PutTemperature ();
412 	  break;
413 
414       case 15:
415 	  printf ("Weather here is %s.\n", Choose (Weather1, NWX1));
416 	  PutTemperature ();
417 	  break;
418 
419       default:
420 	  printf ("WX is %s and %d degrees.\n",
421 		  Choose (Weather1, NWX1), Roll (80) + 10);
422       }
423 }
424 
425 void
PutWeather2(void)426 PutWeather2 (void)
427 {
428 
429     switch (Roll (10))
430       {
431       case 0:
432 	  printf ("It is %s.\n", Choose (Weather2, NWX2));
433 	  break;
434 
435       case 1:
436 	  printf ("It is %s and %d degrees.\n",
437 		  Choose (Weather2, NWX2), Roll (80) + 10);
438 	  break;
439 
440       case 2:
441 	  printf ("The WX is %s and the temp is %d degrees.\n",
442 		  Choose (Weather2, NWX2), Roll (80) + 10);
443 	  break;
444 
445       case 3:
446 	  printf ("WX is %s and the temp is %d degrees.\n",
447 		  Choose (Weather2, NWX2), Roll (80) + 10);
448 	  break;
449 
450       case 4:
451 	  printf ("It is %s today.\n", Choose (Weather2, NWX2));
452 	  break;
453 
454       case 5:
455 	  printf ("It is %s and %d degrees.\n",
456 		  Choose (Weather2, NWX2), Roll (100) + 3);
457 	  break;
458 
459       case 6:
460 	  printf ("The WX is %s and the temp is %d degrees.\n",
461 		  Choose (Weather2, NWX2), Roll (90) + 10);
462 	  break;
463 
464       case 7:
465 	  printf ("WX is %s and the temp is %d degrees.\n",
466 		  Choose (Weather2, NWX2), Roll (80) + 10);
467 	  break;
468 
469       default:
470 	  printf ("It is %s here.\n", Choose (Weather2, NWX2));
471 	  break;
472       }
473 }
474 
475 void
PutWeather(void)476 PutWeather (void)
477 {
478     switch (Roll (4))
479       {
480       case 3:
481 	  PutWeather1 ();
482 	  break;
483 
484       default:
485 	  PutWeather2 ();
486 	  break;
487       }
488 }
489 
490 void
PutCityState(void)491 PutCityState (void)
492 {
493     switch (Roll (6))
494       {
495       case 4:
496 	  printf ("%s %s, ",
497 		Choose (CityHeights, NCITYHTS), Choose (Heights, NHEIGHTS));
498 	  break;
499 
500       case 5:
501 	  printf ("%s %s, ", Choose (New, NNEW), Choose (NewCity, NNEWCITY));
502 	  break;
503 
504       default:
505 	  printf ("%s, ", Choose (City, NCITY));
506 	  break;
507       }
508     printf ("%s.\n", Choose (State, NSTATE));
509 }
510 
511 void
PutLocation(void)512 PutLocation (void)
513 {
514 
515     switch (Roll (5))
516       {
517       case 3:
518 	  printf ("My QTH is ");
519 	  break;
520 
521       case 4:
522 	  printf ("My location is ");
523 	  break;
524 
525       default:
526 	  printf ("QTH is ");
527 	  break;
528 
529       }
530     PutCityState ();
531 }
532 
533 void
PutRig(void)534 PutRig (void)
535 
536 {
537     switch (Roll (19))
538       {
539       case 0:
540       case 1:
541 	  printf ("My rig runs %s watts into %s up %s feet.\n",
542 	       Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)),
543 		  Choose (UpFeet, NUPFEET));
544 	  break;
545 
546       case 2:
547       case 3:
548 	  printf ("Rig is a %s watt %s and antenna is %s.\n",
549 		  Choose (Power, NPOWER), Choose (Transceiver, NXCVR),
550 		  A_Or_An (Choose (Antenna, NANTENNA)));
551 	  break;
552 
553       case 4:
554       case 5:
555 	  printf ("My transceiver is %s.\n", A_Or_An (Choose (Transceiver, NXCVR)));
556 	  printf ("It runs %s watts into %s.\n",
557 	      Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)));
558 	  break;
559 
560       case 6:
561       case 7:
562 	  printf ("The rig is %s running %s watts.\n",
563 	     A_Or_An (Choose (Transceiver, NXCVR)), Choose (Power, NPOWER));
564 	  printf ("Antenna is %s up %s m.\n",
565 	    A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET));
566 	  break;
567 
568       case 8:
569       case 9:
570       case 10:
571       case 11:
572 	  printf ("My rig runs %s watts into %s up %s meters.\n",
573 	       Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)),
574 		  Choose (UpFeet, NUPFEET));
575 	  break;
576 
577       case 12:
578 	  printf ("My rig runs %s watts into %s up %s feet, but\nthe antenna has partly fallen.\n",
579 	       Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)),
580 		  Choose (UpFeet, NUPFEET));
581 	  break;
582 
583       case 13:
584 	  printf ("Rig is %s running %s watts into %s up %s ft.\n",
585 	      A_Or_An (Choose (Transceiver, NXCVR)), Choose (Power, NPOWER),
586 	    A_Or_An (Choose (Antenna, NANTENNA)), Choose (UpFeet, NUPFEET));
587 	  break;
588 
589       case 14:
590 	  printf ("My rig runs %s watts into %s up %s feet.\n",
591 	       Choose (Power, NPOWER), A_Or_An (Choose (Antenna, NANTENNA)),
592 		  Choose (UpFeet, NUPFEET));
593 	  break;
594 
595       case 15:
596 	  printf ("Rig is %s watt %s and antenna is %s.\n",
597 		  A_Or_An (Choose (Power, NPOWER)),
598 		  Choose (Transceiver, NXCVR),
599 		  Choose (Antenna, NANTENNA));
600 	  break;
601 
602       case 16:
603 	  printf ("My transceiver is %s.\n",
604 		  A_Or_An (Choose (Transceiver, NXCVR)));
605 	  printf ("It runs %s watts into %s.\n",
606 		  Choose (Power, NPOWER),
607 		  A_Or_An (Choose (Antenna, NANTENNA)));
608 	  break;
609 
610       case 17:
611 	  printf ("The rig is %s running %s watts.\n",
612 		  A_Or_An (Choose (Transceiver, NXCVR)),
613 		  Choose (Power, NPOWER));
614 	  printf ("Antenna is %s up %s feet.\n",
615 		  A_Or_An (Choose (Antenna, NANTENNA)),
616 		  Choose (UpFeet, NUPFEET));
617 	  break;
618 
619       default:
620 	  printf ("Rig is %s ",
621 		  A_Or_An (Choose (Transceiver, NXCVR)));
622 	  printf ("running %s watts into %s up %s feet.\n",
623 		  Choose (Power, NPOWER),
624 		  A_Or_An (Choose (Antenna, NANTENNA)),
625 		  Choose (UpFeet, NUPFEET));
626 	  break;
627       }
628 }
629 
630 void
PutRST(void)631 PutRST (void)
632 {
633 register char *TheRST;
634 
635     TheRST = Choose (RST, NRST);
636 
637     switch (Roll (8))
638       {
639       case 0:
640 	  printf ("UR RST %s=%s.\n", TheRST, TheRST);
641 	  break;
642 
643       case 1:
644 	  printf ("RST is %s=%s.\n", TheRST, TheRST);
645 	  break;
646 
647       case 2:
648 	  printf ("RST %s=%s.\n", TheRST, TheRST);
649 	  break;
650 
651       case 3:
652 	  printf ("Your RST %s=%s.\n", TheRST, TheRST);
653 	  break;
654 
655       case 4:
656 	  printf ("Your RST is %s=%s.\n", TheRST, TheRST);
657 	  break;
658 
659       case 5:
660 	  printf ("Your signal is RST %s/%s.\n", TheRST, TheRST);
661 	  break;
662 
663       case 6:
664 	  printf ("UR signal is RST %s,%s.\n", TheRST, TheRST);
665 	  break;
666 
667       default:
668 	  printf ("Your RST is %s/%s.\n", TheRST, TheRST);
669 	  break;
670       }
671 }
672 
673 
674 void
PutQ_And_Freq(void)675 PutQ_And_Freq (void)
676 {
677     switch (Roll (8))
678       {
679       case 2:
680 	  printf (Frqmisc[Roll (NFRQMISC)], make_freq ());
681 	  printf ("\n");
682 	  break;
683 
684       case 3:
685 	  printf (Callmisc[Roll (NFRQMISC)],
686 		  Choose (CallSign, NCALLSIGN));
687 	  printf ("\n");
688 	  break;
689 
690       case 4:
691 	  printf (FrqCallmisc[Roll (NFRQCALLMISC)],
692 		  Choose (CallSign, NCALLSIGN),
693 		  make_freq ());
694 	  printf ("\n");
695 	  break;
696 
697       case 5:
698 	  printf (NumMisc[Roll (NNUMMISC)],
699 		  Roll (3) + Roll (2) + 1);
700 	  printf ("\n");
701 	  break;
702 
703       default:
704 	  break;
705 
706       }
707 }
708 
709 void
PutFirstCallsign(void)710 PutFirstCallsign (void)
711 {
712     Sender = Choose (CallSign, NCALLSIGN);
713     Receiver = Choose (CallSign, NCALLSIGN);
714     printf ("%s de %s\n", Receiver, Sender);
715 }
716 
717 void
PutLastCallsign(void)718 PutLastCallsign (void)
719 {
720     printf ("%s de %s\n", Receiver, Sender);
721 }
722 
main(int argc,char ** argv)723 main (int argc, char **argv)
724 {
725 
726     NXCVR = CountStrings (Transceiver);
727     NANTENNA = CountStrings (Antenna);
728     NUPFEET = CountStrings (UpFeet);
729     NPOWER = CountStrings (Power);
730     NRST = CountStrings (RST);
731     NWX1 = CountStrings (Weather1);
732     NWX2 = CountStrings (Weather2);
733     NJOB = CountStrings (Job);
734     NNAME = CountStrings (Name);
735     NSTATE = CountStrings (State);
736     NCITY = CountStrings (City);
737     NCITYHTS = CountStrings (CityHeights);
738     NNEW = CountStrings (New);
739     NHEIGHTS = CountStrings (Heights);
740     NNEWCITY = CountStrings (NewCity);
741     NLICENSE = CountStrings (License);
742     NMISC = CountStrings (Miscellaneous);
743     NCALLSIGN = CountStrings (CallSign);
744     NFRQMISC = CountStrings (Frqmisc);
745     NFRQCALLMISC = CountStrings (FrqCallmisc);
746     NCALLMISC = CountStrings (Callmisc);
747     NNUMMISC = CountStrings (NumMisc);
748 
749     srand48 ((long) time (0));
750 
751     PutQSO ();
752 
753     return 0;
754 }
755