File Coverage

blib/lib/Coy.pm
Criterion Covered Total %
statement 93 247 37.6
branch 11 70 15.7
condition 1 55 1.8
subroutine 16 46 34.7
pod 0 24 0.0
total 121 442 27.3


line stmt bran cond sub pod time code
1             package Coy;
2              
3             BEGIN
4             {
5 1     1   6 require Exporter;
6 1         16 @ISA = ('Exporter');
7 1         3 @EXPORT = qw(transcend enlighten);
8 1         4 $VERSION = '0.06';
9              
10 1         4 my $USER_CONFIG_FILE = "$ENV{HOME}/.coyrc";
11              
12 1     1   1109 use Carp ();
  1         2  
  1         63  
13              
14 0     0 0 0 sub transcend { &Carp::croak }
15              
16 0     0 0 0 sub enlighten { &Carp::carp }
17              
18             # THE REAL WORK STARTS HERE
19              
20 1     1   1349 use Lingua::EN::Inflect qw(PL_N PL_V NO inflect NUM A PART_PRES NUMWORDS);
  1         22371  
  1         187  
21 1     1   579 use Lingua::EN::Hyphenate;
  1         3  
  1         1103  
22              
23             sub random
24             {
25 0     0 0 0 for (1..100)
26             {
27 0         0 my $choice = $_[int rand @_];
28 0 0       0 my $selection = (ref($choice) eq 'CODE')
29             ? $choice->()
30             : $choice;
31 0 0       0 return $selection if defined $selection;
32             }
33 0         0 die "couldn't randomize: " . join(", ", @_) . "at " . (caller)[2];
34             }
35              
36             sub syl_count
37             {
38 0     0 0 0 my $count = 0;
39 0         0 my $word;
40 0         0 foreach $word (split / /, $_[0])
41             {
42 0 0       0 $word =~ /^\d+$/ and $word = NUMWORDS($word);
43 0         0 my @syllables = syllables($word);
44 0         0 $count += @syllables;
45             }
46 0         0 return $count;
47             }
48              
49             # Personages
50              
51 1         9 @Coy::personage = ( "The Jade Emperor", "Master Po", "Mumon",
52             "The Seventh Sage", "the Master", "Alan Watts",
53             "Tor Kin Tun", "Tom See", "Or Wunt",
54             "Homer Simpson", "Lao Tse", "The Buddha",
55             "Gautama", "Swordmaster Mushashi", "Con Wei",
56             "Joshu", "Bankei", "Ryokan", "Ryonen", "Eshun",
57             );
58              
59              
60             # EXCLAMATIONS
61              
62 1         2 my @exclamation = ( 'Oh!', 'See!', ' Look!' );
63              
64              
65             # LOCATIONS
66              
67 1         3 my @aquatic = qw( pond river pool dam stream lake );
68              
69             sub Aquatic::atRandom
70 0     0   0 { random
71             "in the " . random(@aquatic),
72             "in " . A(random @aquatic)
73             ;
74             }
75              
76             sub Exoaquatic::atRandom
77 0     0   0 { random
78             "out of the " . random(@aquatic),
79             "from " . A(random @aquatic)
80             ;
81             }
82              
83             sub Suraquatic::atRandom
84 0     0   0 { random
85             "on the " . random(@aquatic),
86             "on " . A(random @aquatic)
87             ;
88             }
89              
90             sub Aerial::atRandom
91 0     0   0 { random
92             "over the " . random(@aquatic),
93             "above the " . random(@aquatic),
94             "over " . random(@Coy::place),
95             "above " . random(@Coy::place),
96             "near " . random(@Coy::place)
97             }
98              
99             sub Arborial::atRandom
100 0     0   0 { random
101             "in " . A(random @Coy::tree),
102             "in the branches of " . A(random @Coy::tree),
103             "in " . A(random @Coy::tree, @Coy::fruit_tree) . " tree",
104             "in the branches of " . A(random @Coy::tree, @Coy::fruit_tree) . " tree";
105             }
106              
107             sub Terrestrial::atRandom
108 0     0   0 { random
109             "under " . A(random @Coy::tree) . random(" tree", ""),
110             "near " . random(@Coy::place),
111             "beside " . A(random @aquatic);
112             }
113              
114              
115             # DIRECTIONS
116              
117 1         4 my @horizontalNS = qw( north south );
118 1         27 my @horizontalEW = qw( east west );
119 1         3 my @vertical = qw( up upwards down downwards );
120 1         2 my @general_dir = qw( away );
121 1         2 my @to_dir_prep = ( "towards" );
122 1         1 my @from_dir_prep = ( "away from", );
123              
124             sub Horizontal::atRandom
125 0     0   0 { my $compass = random
126             @horizontalNS,
127             @horizontalEW,
128             random(@horizontalNS).'-'.random(@horizontalEW)
129             ;
130 0         0 return random
131             ($compass x 8,
132             @general_dir),
133             random(@to_dir_prep)." the ".$compass,
134             random(@to_dir_prep, @from_dir_prep)." ".random(@Coy::place);
135             }
136              
137             sub Any::atRandom
138 0     0   0 { my $compass = random
139             @horizontalNS,
140             @horizontalEW,
141             random(@horizontalNS).'-'.random(@horizontalEW)
142             ;
143 0         0 return random
144             $compass,
145             @general_dir,
146             random(@to_dir_prep)." the ".$compass,
147             random(@to_dir_prep, @from_dir_prep)." ".random(@Coy::place);
148 0         0 @vertical;
149             }
150              
151             # DATABASE
152              
153 1         1 $Coy::agent = {};
154 1         2 $Coy::agent_categories = {};
155 1         1 @Coy::nouns = ();
156 1         2 $Coy::associations = "";
157 1         1 my $nonassoc = 0;
158              
159             sub tree
160             {
161 1     1 0 3 push @Coy::tree, @_;
162 1         1 1;
163             }
164              
165             sub fruit_tree
166             {
167 1     1 0 2 push @Coy::fruit_tree, @_;
168 1         2 1;
169             }
170              
171             sub place
172             {
173 1     1 0 4 push @Coy::place, @_;
174 1         6 1;
175             }
176              
177             sub personage
178             {
179 0     0 0 0 push @Coy::personage, @_;
180 0         0 1;
181             }
182              
183             sub noun
184             {
185 1     1 0 2 my $hashref = shift;
186 1 50       4 Carp::croak "Usage: noun " unless ref($hashref) eq 'HASH';
187 1         14 $Coy::agent = { %$Coy::agent, %$hashref };
188             # print STDERR "Added ", scalar keys %$hashref, " to agent\n";
189 1         3 1;
190             }
191              
192             sub categories
193             {
194 1     1 0 2 my $hashref = shift;
195 1 50       3 Carp::croak "Usage: categories " unless ref($hashref) eq 'HASH';
196 1         4 $Coy::agent_categories = { %$Coy::agent_categories, %$hashref };
197             # print STDERR "Added ", scalar keys %$hashref, " to agent_categories\n";
198 1         2 1;
199             }
200              
201             sub syllable_counter
202             {
203 1     1 0 1 my $sub = shift;
204 1 50       9 $sub = \&$sub unless ref $sub;
205 1     1   6 no strict;
  1         1  
  1         1647  
206 1         4 undef &syllables;
207 1     1   6 local $SIG{__WARN__} = sub {};
  1         5  
208 1         13 *syllables = $sub;
209             }
210              
211 1         20 my @count_prob = ((0)x1,(1)x90,(2)x40,(3..5)x2,(6..12)x1);
212              
213             sub get_Noun_Verb
214             {
215 0     0 0 0 my ($count, $sound, $noun_only) = @_;
216 0         0 my ($noun, $verb, $min, $max);
217 0         0 my $tries = 0;
218 0         0 $nonassoc = 0;
219 0         0 while (++$tries)
220             {
221 0         0 $noun = random @Coy::nouns;
222 0 0       0 return $noun if $noun_only;
223 0         0 my @verbs = keys %{$Coy::agent->{$noun}{act}};
  0         0  
224             # print STDERR "noun = $noun\n";
225             # print STDERR "verbs = @verbs\n";
226 0 0 0     0 push @verbs, @{$Coy::agent->{$noun}{sound}}
  0         0  
227             if $sound && $Coy::agent->{$noun}{sound};
228 0         0 $verb = random @verbs;
229             # print STDERR "[trying $noun/$verb for $count";
230             # print STDERR " (non-assoc)" if $nonassoc;
231             # print STDERR "]\n";
232 0 0       0 if ($tries>20) { $nonassoc = 1 }
  0         0  
233 0 0 0     0 if ($Coy::associations && !$nonassoc)
234             {
235 0   0     0 my $assoc =
236             $Coy::agent->{$noun}{act}{$verb}{associations}||"";
237             # print "$noun/$verb: [$assoc]->[$Coy::associations]\n";
238 0 0 0     0 next unless $assoc && ($assoc =~ /$Coy::associations/i);
239             # print "[$assoc]\n";
240             }
241 0 0       0 if ($tries>50)
242             {
243 0   0     0 $_[0] = $Coy::agent->{$noun}{act}{$verb}{minimum}
244             || $Coy::agent->{$noun}{minimum};
245 0         0 last;
246             }
247 0         0 $min = $Coy::agent->{$noun}{act}{$verb}{minimum};
248 0 0 0     0 $min = $Coy::agent->{$noun}{minimum}
      0        
249             if !defined ($min) || defined($Coy::agent->{$noun}{minimum})
250             && $min < $Coy::agent->{$noun}{minimum};
251 0         0 $max = $Coy::agent->{$noun}{act}{$verb}{maximum};
252 0 0 0     0 $max = $Coy::agent->{$noun}{maximum}
      0        
253             if !defined ($max) || defined($Coy::agent->{$noun}{maximum})
254             && $max > $Coy::agent->{$noun}{maximum};
255             # print STDERR "trying $noun/$verb [$min<=$count<=$max]\n";
256 0 0 0     0 last unless (defined($min) && $count < $min ||
      0        
      0        
257             defined($max) && $count > $max);
258             }
259              
260             # print STDERR "[accepted $noun/$verb]\n";
261 0         0 return ($noun, $verb, PART_PRES($verb),
262             $Coy::agent->{$noun}{act}{$verb}{non_adjectival});
263             }
264              
265             sub Noun
266             {
267 0     0 0 0 my $count = random @count_prob;
268 0         0 my ($noun,@verb) = get_Noun_Verb($count,'SOUND','NOUN_ONLY');
269 0 0       0 return $noun if $Coy::agent->{$noun}{personage};;
270 0         0 return inflect "NO($noun,$count)";
271             }
272              
273             sub Noun_Verb
274             {
275 0     0 0 0 my $count = random @count_prob;
276 0         0 my ($noun,@verb) = get_Noun_Verb($count,'SOUND');
277 0         0 my $verb = random @verb[0..1];
278 0 0       0 return inflect "$noun PL_V($verb,$count)" if $Coy::agent->{$noun}{personage};
279 0         0 return inflect "NO($noun,$count) PL_V($verb,$count)";
280             }
281              
282             sub Participle_Noun
283             {
284 0     0 0 0 my $count = random @count_prob;
285 0         0 my ($noun,$verb,$participle,$non_adjectival) =
286             get_Noun_Verb($count,'SOUND');
287 0 0 0     0 return if $non_adjectival or $Coy::agent->{$noun}{personage};
288 0         0 return inflect "NO($participle $noun,$count)";
289             }
290              
291             sub Noun_Location
292             {
293 0     0 0 0 my $count = random @count_prob;
294 0         0 my ($noun,@verb) = get_Noun_Verb($count,'NOUN_ONLY');
295 0         0 my $verb = random @verb[0..1];
296 0 0       0 return undef unless $Coy::agent->{$noun}{act}{$verb[0]}{location};
297 0         0 my $location = $Coy::agent->{$noun}{act}{$verb[0]}{location}->atRandom();
298 0 0       0 return inflect "$noun $location" if $Coy::agent->{$noun}{personage};
299 0         0 return inflect "NO($noun,$count) $location";
300             }
301              
302             sub Noun_Verb_Location
303             {
304 0     0 0 0 my $count = random @count_prob;
305 0         0 my ($noun,@verb) = get_Noun_Verb($count);
306 0         0 my $verb = random @verb[0..1];
307 0 0       0 return undef unless $Coy::agent->{$noun}{act}{$verb[0]}{location};
308 0         0 my $location = $Coy::agent->{$noun}{act}{$verb[0]}{location}->atRandom();
309 0 0       0 return inflect "$noun PL_V($verb,$count) $location"
310             if $Coy::agent->{$noun}{personage};
311 0         0 return inflect "NO($noun,$count) PL_V($verb,$count) $location";
312             }
313              
314             sub Noun_Verb_Direction
315             {
316 0     0 0 0 my $count = random @count_prob;
317 0         0 my ($noun,@verb) = get_Noun_Verb($count);
318 0         0 my $verb = random @verb[0..1];
319 0 0       0 return undef unless $Coy::agent->{$noun}{act}{$verb[0]}{direction};
320 0         0 my $direction = $Coy::agent->{$noun}{act}{$verb[0]}{direction}->atRandom();
321 0 0       0 return inflect "$noun PL_V($verb,$count) $direction"
322             if $Coy::agent->{$noun}{personage};
323 0         0 return inflect "NO($noun,$count) PL_V($verb,$count) $direction";
324             }
325              
326             sub expand_synonyms
327             {
328 1     1 0 3 foreach my $noun ( @Coy::nouns )
329             {
330 43         41 my %act = %{$Coy::agent->{$noun}{act}};
  43         254  
331 43         126 foreach my $verb ( keys %act )
332             {
333 451 100       917 if (exists $act{$verb}{synonyms})
334             {
335 183         163 foreach my $syn ( @{$act{$verb}{synonyms}} )
  183         272  
336             {
337 480         1322 $Coy::agent->{$noun}{act}{$syn}
338             = $act{$verb};
339             }
340             }
341             }
342             }
343             }
344              
345             sub expand_categories
346             {
347 1     1 0 3 foreach my $noun ( @Coy::nouns )
348             {
349 23 50       45 my $categories = $Coy::agent->{$noun}{category} or next;
350 23         23 my %generic_acts = ();
351 23         27 foreach my $category ( @$categories )
352             {
353 29 50       51 next unless $Coy::agent_categories->{$category};
354 29 50       135 %generic_acts =
355 29         19 ( %{$Coy::agent_categories->{$category}{act}||{}},
356             %generic_acts );
357             }
358             # print STDERR "expanding $noun with", keys(%generic_acts), "\n";
359 23 100       120 %{$Coy::agent->{$noun}{act}} =
  23         72  
360 23         40 ( %generic_acts, %{$Coy::agent->{$noun}{act}||{}} );
361             }
362 1         3 foreach my $noun ( @Coy::personage )
363             {
364 20         30 push @Coy::nouns, $noun;
365 20         63 $Coy::agent->{$noun}{category} = [ "Human" ];
366 20         39 $Coy::agent->{$noun}{maximum} = 1;
367 20         29 $Coy::agent->{$noun}{minimum} = 1;
368 20         25 $Coy::agent->{$noun}{personage} = 1;
369 20   50     73 $Coy::agent->{$noun}{act} = $Coy::agent_categories->{Human}{act}||{};
370             }
371             }
372              
373             sub Generate
374             {
375             local $_ = random
376             (
377 0     0     (sub { Noun }) x 1,
378 0     0     (sub { Noun_Location }) x 6,
379 0     0     (sub { Noun_Verb }) x 3,
380 0     0     (sub { Noun_Verb_Direction }) x 13,
381 0     0     (sub { Noun_Verb_Location }) x 13,
382 0     0 0   (sub { Participle_Noun }) x 5,
  0     0      
383             );
384             ;
385              
386 0           s/^1(?= )/a/;
387 0           s/^2(?= )/random "a pair of", "two"/e;
  0            
388 0           s/^(\d+)(?= )/NUMWORDS($1)/e;
  0            
389 0 0         $Coy::associations = "" unless $nonassoc;
390 0           return ucfirst $_;
391             }
392              
393             sub Generate_Sized
394             {
395 0     0 0   my ($size) = @_;
396 0           my $fulltext = "";
397 0           my $fullcount = 0;
398 0           while ($fullcount != $size)
399             {
400 0           my $text = Generate;
401 0           my $count = $fullcount + syl_count($text);
402 0 0 0       if ($count < $size-1 || $count == $size)
403             {
404 0 0         $fulltext .= ($fulltext?". ":"").$text;
405 0           $fullcount = $count;
406             }
407             }
408 0           return $fulltext;
409             }
410              
411 1     1   876 use Text::Wrap;
  1         2877  
  1         1384  
412              
413             sub with_haiku
414             {
415 0     0 0   my $message = join("",@_);
416 0           my $file = "Mysterious Compiler";
417 0           my $line = "???";
418 0 0         if ($message =~ s/(.*)at\s(\S+)\sline\s(\d+.*?)\s*\Z/$1/s)
    0          
419             {
420 0   0       $file = $2||$file;
421 0   0       $line = $3||$line;
422             }
423             elsif ($message =~ s/(.*)File\s'([^']+)';\s+Line\s+(\d+.*)/$1/s)
424             {
425 0   0       $file = $2||$file;
426 0   0       $line = $3||$line;
427 0           chomp $line;
428 0           $file =~ s/^.*://;
429             }
430              
431 0           associate($message);
432              
433 0           my @words = ();
434 0           foreach my $word (split /\s+/, Generate_Sized(17))
435             {
436 0           push @words, [$word, syl_count($word)];
437             }
438              
439 0           my $haiku = "";
440 0           my $count = 0;
441 0           while ($count<5)
442             {
443 0           my $word = shift @words;
444 0           $haiku .= "$word->[0] ";
445 0           $count+=$word->[1];
446             }
447 0           $haiku .= "\n\t";
448 0           while ($count<12)
449             {
450 0           my $word = shift @words;
451 0           $haiku .= "$word->[0] ";
452 0           $count+=$word->[1];
453             }
454 0           $haiku .= "\n\t";
455 0           $haiku .= join(" ",map {$_->[0]} @words) . ".";
  0            
456              
457              
458 0           $message = wrap("\t\t","\t\t",$message);
459 0           $message =~ s/\t\t//;
460              
461 0           my @book = ('Analects of %s',
462             'Sayings of %s',
463             'The Wisdom of %s',
464             '"%s Speaks"',
465             '"The Way of %s"',
466             );
467              
468 0           my $book = sprintf(random(@book),$file);
469              
470 0           $where = wrap("\t\t\t","\t\t\t ","($book: line $line)");
471 0           $where =~ s/\t\t\t//;
472              
473              
474 0           my $personage = ucfirst random @Coy::personage;
475              
476 0           return <
477              
478             -----
479             $haiku
480             -----
481              
482             ${personage}'s commentary...
483            
484             $message
485              
486             $where
487             MU
488             }
489              
490             sub associate
491             {
492 0     0 0   %Coy::associations = ();
493 0           my ($message) = @_;
494 0           $message =~ s/[^A-Za-z]+/ /g;
495 0           my @words = split /\s+/, $message;
496 0           $Coy::associations = join "|", grep {$_} @words;
  0            
497             # $Coy::associations = qr/$Coy::associations/;
498             }
499              
500             # LOAD STANDARD DATA
501              
502 1         3 syllable_counter "Lingua::EN::Hyphenate::syllables";
503              
504 1         82 noun
505             {
506             duck =>
507             {
508             category => [ Bird ],
509             act =>
510             {
511             swims =>
512             {
513             location => Suraquatic,
514             direction => Horizontal,
515             },
516             },
517             sound => [ "quacks", ]
518             },
519             swallow =>
520             {
521             category => [ Bird ],
522             act => { swoops => { location => Aerial, } },
523             },
524             raven => { category => [ Bird ] },
525             thrush => { category => [ Bird ], sound => [ "sings" ]},
526             songbird => { category => [ Bird ], sound => [ "sings" ]},
527             lark => { category => [ Bird ], sound => [ "sings" ]},
528             gannet => { category => [ Bird ] },
529             dove => { category => [ Bird ], sound => [ "coos" ] },
530             kingfisher => { category => [ Bird ] },
531             woodpecker => { category => [ Bird ] },
532              
533             'carp' => { category => [ Fish ] },
534             goldfish => { category => [ Fish ] },
535             salmon => { category => [ Fish, Leaper ] },
536             pike => { category => [ Fish, Leaper ] },
537             trout => { category => [ Fish, Leaper ] },
538              
539             fox =>
540             {
541             category => [ Animal, Hunter ],
542             sound => [ "barks" ],
543             act =>
544             {
545             trots => { location => Terrestrial },
546             },
547             },
548             bear =>
549             {
550             category => [ Animal ],
551             sound => [ "howls" ],
552             act =>
553             {
554             fishes => { location => Aquatic },
555             },
556             },
557             wolf =>
558             {
559             category => [ Animal, Hunter ],
560             sound => [ "howls" ],
561             },
562             cat =>
563             {
564             category => [ Animal, Hunter ],
565             sound => [ "purrs", "yowls" ],
566             act =>
567             {
568             washes => { location => Terrestrial },
569             sits => { location => Terrestrial },
570             },
571             },
572             rabbit =>
573             {
574             category => [ Animal ],
575             act =>
576             {
577             sniffs => { location => Terrestrial },
578             grazes => { location => Terrestrial },
579             },
580             },
581              
582             "young girl" =>
583             {
584             category => [ Human ],
585             act =>
586             {
587             skips =>
588             {
589             location => Terrestrial,
590             non_adjectival => 1,
591             }
592             },
593             },
594             "old man" =>
595             {
596             category => [ Human ],
597             act =>
598             {
599             swims =>
600             {
601             location => Aquatic,
602             non_adjectival => 1,
603             }
604             },
605             },
606             lover =>
607             {
608             category => [ Human ],
609             minimum => 2,
610             maximum => 2,
611             act =>
612             {
613             kisses => { location => Terrestrial, },
614             cuddles => { location => Terrestrial, },
615             touch => { location => Terrestrial, },
616             whisper => { location => Terrestrial, },
617             dance => { location => Terrestrial, },
618             },
619             },
620             };
621              
622 1         51 categories
623             {
624             Human =>
625             {
626             act =>
627             {
628             dies =>
629             {
630             associations => "die depart exit",
631             location => Terrestrial,
632             },
633             quarrels =>
634             {
635             associations => "argument",
636             location => Terrestrial,
637             minimum => 2,
638             synonyms => [qw(bickers argues banters fights)],
639             },
640             contends =>
641             {
642             associations => "argument",
643             location => Terrestrial,
644             minimum => 2,
645             synonyms => [qw(debates)],
646             non_adjectival => 1,
647             },
648             sits =>
649             {
650             associations => "rest static stop",
651             location => Terrestrial,
652             non_adjectival => 1,
653             },
654             meets =>
655             {
656             associations => "join together",
657             location => Terrestrial,
658             minimum => 2,
659             non_adjectival => 1,
660             synonyms => [qw(encounters)],
661             },
662             laughs =>
663             {
664             associations => "happy",
665             location => Terrestrial,
666             non_adjectival => 1,
667             },
668             parts =>
669             {
670             associations => "leave left miss",
671             location => Terrestrial,
672             minimum => 2,
673             },
674             departs =>
675             {
676             associations => "leave left miss",
677             location => Terrestrial,
678             },
679             weeps =>
680             {
681             associations => "NEG",
682             location => Terrestrial,
683             },
684             sighs =>
685             {
686             associations => "NEG",
687             location => Terrestrial,
688             },
689             embraces =>
690             {
691             associations => "join together with",
692             location => Terrestrial,
693             minimum => 2,
694             maximum => 2,
695             },
696             },
697             },
698             Animal =>
699             {
700             act =>
701             {
702             sits =>
703             {
704             associations => "static",
705             location => Terrestrial,
706             },
707             walks =>
708             {
709             associations => "gone",
710             location => Terrestrial,
711             non_adjectival => 1,
712             },
713             watches =>
714             {
715             associations => "see",
716             location => Terrestrial,
717             non_adjectival => 1,
718             },
719             waits =>
720             {
721             associations => "wait",
722             location => Terrestrial,
723             non_adjectival => 1,
724             },
725             eats =>
726             {
727             associations => 'eat consume use',
728             location => Terrestrial,
729             non_adjectival => 1,
730             }
731             },
732             },
733              
734             Hunter =>
735             {
736             act =>
737             {
738             crouches => { location => Terrestrial },
739             prowls => { location => Terrestrial },
740             stalks => { location => Terrestrial },
741             leaps => { location => Terrestrial },
742             },
743             },
744             Fish =>
745             {
746             act =>
747             {
748             darts =>
749             {
750             location => Aquatic,
751             },
752             swims =>
753             {
754             location => Aquatic,
755             non_adjectival => 1,
756             },
757             },
758             },
759             Leaper =>
760             {
761             act => { leaps => { location => Exoaquatic } },
762             },
763             Bird =>
764             {
765             act =>
766             {
767             flies =>
768             {
769             location => Aerial,
770             direction => Any,
771             },
772             nests =>
773             {
774             location => Arborial,
775             },
776             },
777             },
778             };
779              
780 1         4 tree qw( oak elm willow maple she-oak );
781              
782 1         3 fruit_tree qw( cherry apple lemon );
783              
784 1         2 place ( "Mount Fuji", "a temple", "the Emperor's palace",
785             "a dojo", "the Shaolin temple", "a farmer's cottage",
786             "the village", "the town square", "the harbor",
787             "Bill Clinton's office", "a monastry", "the market-place",
788             );
789              
790              
791             # LOAD USER-DEFINED DATA
792              
793 1 50       20 if (-f $USER_CONFIG_FILE)
794             {
795 1     1   11 no strict;
  1         1  
  1         118  
796 0         0 do $USER_CONFIG_FILE;
797             }
798              
799 1         6 @Coy::nouns = keys %$Coy::agent;
800              
801 1         4 expand_categories;
802 1         3 expand_synonyms;
803              
804             # print STDERR "Nouns: ", scalar @Coy::nouns, "\n";
805              
806             }
807              
808             # AND FINALLY, INSTALL IT ALL...
809              
810             my $nested = -1;
811              
812             $SIG{__WARN__} = sub
813             {
814             local $SIG{__WARN__};
815             $nested++;
816             warn with_haiku(@_) unless $nested;
817             warn @_ if $nested;
818             $nested--;
819             };
820              
821             $SIG{__DIE__} = sub
822             {
823             local $SIG{__DIE__};
824             $nested++;
825             die with_haiku(@_) unless $nested;
826             die @_ if $nested;
827             $nested--;
828             };
829              
830             1;
831              
832              
833             __END__