File Coverage

blib/lib/Game/CharacterSheetGenerator/ElfNames.pm
Criterion Covered Total %
statement 48 54 88.8
branch 11 16 68.7
condition n/a
subroutine 8 8 100.0
pod 0 5 0.0
total 67 83 80.7


line stmt bran cond sub pod time code
1             #!/usr/bin/env perl
2             # Copyright (C) 2012-2022 Alex Schroeder
3              
4             # This program is free software: you can redistribute it and/or modify it under
5             # the terms of the GNU General Public License as published by the Free Software
6             # Foundation, either version 3 of the License, or (at your option) any later
7             # version.
8             #
9             # This program is distributed in the hope that it will be useful, but WITHOUT
10             # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11             # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License along with
14             # this program. If not, see .
15              
16             =encoding utf8
17              
18             =head1 NAME
19              
20             Game::CharacterSheetGenerator::ElfName - return a elf name
21              
22             =head1 SYNOPSIS
23              
24             use Game::CharacterSheetGenerator::ElfName qw(elf_name);
25             # returns both $name and $gender (F, M, or ?)
26             my ($name, $gender) = elf_name();
27             # returns the same name and its gender
28             ($name, $gender) = elf_name("Alex");
29              
30             =head1 DESCRIPTION
31              
32             This package has one function that returns a elf name and a gender. The gender
33             returned is "M", "F", or "?".
34              
35             If a name is provided, the gender is returned.
36              
37             =cut
38              
39             package Game::CharacterSheetGenerator::ElfNames;
40 9     9   54 use Modern::Perl;
  9         22  
  9         45  
41 9     9   1372 use utf8;
  9         36  
  9         39  
42              
43             require Exporter;
44             our @ISA = qw(Exporter);
45             our @EXPORT_OK = qw(elf_name);
46              
47             sub one {
48 90     90 0 156 my $i = int(rand(scalar @_));
49 90         334 return $_[$i];
50             }
51              
52             # http://sindarinlessons.weebly.com/37---how-to-make-names-1.html
53              
54             # https://realelvish.net/names/sindarin/woodelf/all/
55              
56             my @prefix =
57             qw(achar adertha adleg al amartha aníra aphada ar ava awartha badh batha
58             beria blab brenia brona buia cab can car carpha cen critha dartha delia
59             dew díhena doltha drava drega dringa echad edledhia egleria eitha elia
60             ercha ertha fantha fara feira feria fuia gad gala gir gladh glavra
61             glintha glir gohena gonod gor gosta groga gruitha gwatha gwathra gweria
62             gwesta had hal haltha hamma harna hasta henia hwinia ialla ídha ídhra
63             ista iuitha laba lala lamma lasta lathra linna luitha mel metha mista nag
64             nalla nara narcha ndag ndagra ndamma nde nedia negra neitha nella nesta
65             ngal nganna nod nor northa orthel orthor osgar pad padra ped pel per puia
66             rada ran reda redh reitha reth rhib rista ritha rosta ruthra síla sog
67             suila teilia teitha telia theria thilia thora thosta tintha tir toba
68             toltha tortha trasta trevad tuia);
69              
70             my @word =
71             qw(abonthen achad adan agar agarwen aglar aglareb agor aith alag alagos alph
72             alu alwed amar amarth amarthan amath amdir amlug amon amrûn anc and
73             andreth ang angol angren annui annûn anor anu anwar apharch ar aran aras
74             arn arod arth asgar ast astor athe aur avorn awarth bain balch bara baran
75             beleg belt belthas beren bereth bor born bragol braig brand brassen
76             bregol brog bronadui brui brûn bŷr cadu cadwar cal calar calen callon cam
77             canad cand caran carch carweg caun celair celeb celebren celeg celevon
78             cem cidinn cinnog cîw coll com conui corch cordof corn coru coth craban
79             crann crist crumui cû cugu cuin cûn cund curu cŷr dail de del deleb delu
80             dem der dern dîn dínen dîr dol dolen doll dom donn dorn dram draug dring
81             dû dûr dŷr ech ecthel eden edhel edhellen edlenn eg egas eglan eglir
82             eglos eiliant einior el elanor ell elloth elu en er ereb eredh ereg eru
83             erui esgal estel estent ethir ew ewen fain fair falas falf fanui far faug
84             faun fe feg fel fela fen fer fern ferui filig fim find fíreb firen forgam
85             forn forod forodren fuin gail galadh galas galenas gamp gaud gear gearon
86             gel gell gellam gellui gem ger gern geruil glad glam glamor glamren glan
87             glass glaur glaw gler glîr glórin gloss goeol golass gondren gordh gorn
88             gost graw gronn gruin gûr gwache gwain gwann gwarth gwath gwathren
89             gwathui gwaun gwaur gwe gwen gweren gwest gwew gwilwileth gwîn hadhod hal
90             hall hallas hand hannas harad haradren hargam harn harvo hast hathel he
91             helch heledir hell hen heneb her hethu hîl him hîr hiril hith hithren
92             hithui hîw horn hû hûr hwand hwîn iand iar iaun iaur îdh idhor idhren ind
93             ingem inu iphant írui ist istui ithil ivren lagor laich lain lalaith lalf
94             lam lanc land lang lass laug lavan leb leg lend ler lew leweg lhain lhew
95             lhind lhûg lim limp lind lithui loen lom lorn lossen lost loth luin lum
96             lung lŷg madweg maelui magor maidh malt malthen malthorn malu man mbar
97             mbarad mecheneb med medli medlin medui meg megil melch meldir meldis
98             meleth mell mellon melui men mer meren meron mesg methen mew milui min
99             minai mîr mith mithren mîw morgul morn muil muin mûl mund mŷl naith nar
100             narch naru nathal naud naug naugla naur nauth naw nawag ndam nder ndîr
101             ndîs negen neledh nen nend nenui ner nestadren ngail ngalad ngannel
102             ngaraf ngaur ngawad ngilith ngoll ngollor ngolodh ngolu ngolwen ngor
103             ngorgor ngorn ngorth ngorthad ngûl ngurth nguru nguruthos niben nîd nîf
104             nimp nîn nind nîr noen norn noroth nórui nûr oel oer ogol ol onod orch
105             orchall orod oron othol ovor pant paran parch path paur pedweg pegui
106             pelin pen peng periand peth pigen pîn puig rain raud raudh raug raun raw
107             reg rem ren rend reth rhanc rhaw rhosg rhoss rhudol rhúnen rî rîn ring
108             rîs riss roch rosc ross rost rûdh ruin rustui rûth rŷn sadar sador said
109             sain sammar sarch sel ser sereg sîdh silef silivren sîr sûl tad taid tal
110             talagand talt tan tanc tang tara tarch tarlanc tathren taug taur tavor
111             taw tawar tawaren tawen tegil ten ter tes thala thanc thand tharan tharn
112             thaur thavor thaw thend thent thîr thon thorn thoron thûl thurin tinnu
113             tint tinu tîr tirn tithen tolog tond tong torn torog trîw tû tûg tuilind
114             tulus tûr uanui uilos uireb ûl ulund ûn ungol ûr urug urui);
115              
116             my @neutral_suffix =
117             qw(ben dil ndil or wi);
118             my @female_suffix = (@neutral_suffix, @neutral_suffix,
119             qw(iel iell ien il eth el wen));
120             my @male_suffix = (@neutral_suffix, @neutral_suffix,
121             qw(dir ion on));
122              
123             sub female_name {
124 24     24 0 58 my $r = rand();
125 24 100       55 if ($r < 0.6) { return one(@word) . one(@female_suffix) }
  15 100       124  
126 6         51 elsif ($r < 0.8) { return one(@prefix) . one(@female_suffix) }
127 3         18 else { return one(@prefix) . return one(@word) }
128             }
129              
130             sub male_name {
131 21     21 0 35 my $r = rand();
132 21 100       46 if ($r < 0.6) { return one(@word) . one(@male_suffix) }
  15 100       99  
133 3         11 elsif ($r < 0.8) { return one(@prefix) . one(@male_suffix) }
134 3         13 else { return one(@prefix) . return one(@word) }
135             }
136              
137             # We do some post-processing of words, inspired by these two web pages, but using
138             # our own replacements.
139             # http://sindarinlessons.weebly.com/37---how-to-make-names-1.html
140             # http://sindarinlessons.weebly.com/38---how-to-make-names-2.html
141              
142             sub normalize {
143 45     45 0 65 my $name = shift;
144              
145 45         112 $name =~ s/(.) \1/$1/g;
146 45         80 $name =~ s/d t/d/g;
147 45         79 $name =~ s/a ui/au/g;
148 45         71 $name =~ s/nd m/dhm/g;
149 45         68 $name =~ s/n?d w/dhw/g;
150 45         66 $name =~ s/r gw/rw/g;
151 45         73 $name =~ s/^nd/d/;
152 45         73 $name =~ s/^ng/g/;
153 45         66 $name =~ s/th n?d/d/g;
154 45         79 $name =~ s/dh dr/dhr/g;
155 45         67 $name =~ s/ //g;
156              
157 45     1   160 $name =~ tr/âêîôûŷ/aeioúi/;
  1         787  
  1         2  
  1         10  
158 45         71 $name =~ s/ll$/l/;
159 45         97 $name =~ s/ben$/wen/g;
160 45         72 $name =~ s/bwi$/wi/;
161 45         77 $name =~ s/[^aeiouúi]ndil$/dil/g;
162 45         70 $name =~ s/ae/aë/g;
163 45         65 $name =~ s/ea/ëa/g;
164 45         66 $name =~ s/ii/ï/g;
165              
166 45         99 $name = ucfirst($name);
167              
168 45         174 return $name;
169             }
170              
171             sub elf_name {
172 45     45 0 64 my $name = shift;
173 45 50       92 if ($name) {
174 0         0 my $gender;
175 0         0 for (@female_suffix) {
176 0 0       0 return ($name, 'F') if $name =~ /$_$/;
177             }
178 0         0 for (@male_suffix) {
179 0 0       0 return ($name, 'M') if $name =~ /$_$/;
180             }
181 0         0 return ($name, '?');
182             } else {
183 45 100       94 if (rand() < 0.5) { return (normalize(female_name()), 'F') }
  24         56  
184 21         49 else { return (normalize(male_name()), 'M') }
185             }
186             }
187              
188             1;