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