in reply to Creating a random generator

Here is the code for the random generator to date, but first some notes. I hope that I did most of this right.
#!/usr/bin/perl use strict; use warnings; use CGI; use CGI::Carp qw(fatalsToBrowser); use Games::Dice qw(roll); use HTML::Template; use Lingua::EN::Numbers::Ordinate; print "content-type: text/html \n\n"; my @Dice = qw(1d4 1d6 1d8 1d10 1d12 1d20); my @Radius = ( "1' or Touch", "5'", "10'", "20'", "50'", "100'" ); my $radius = "in a $Radius[rand @Radius] radius"; my @Time = qw(round turn hour day week month year); my @PM = qw(+ -); my @Resist = ( "immune", "is "roll '1d100'"&#037; magic resistant", "has no resistance" ); my @Wizard_School = qw(Abjuration Air Alteration Conjuration/Summoning + Divination Earth Enchantment/Charm Fire Illusion/Phantasm Invocation +/Evocation Necromancy Water); my @Cleric_Sphere = qw(Air All Animal Astral Chaos Charm Combat Creati +on Divination Earth Fire Guardian Healing Law Necromatic Numbers Plan +t Protection Summoning Sun Thought Time Travelers War Wards Water Wea +ther); my @Spell_Freq = ('common','uncommon','rare','very rare'); my @Magic_Item_Type = ('Magical Liquids','Scrolls','Rings','Rods','Sta +ves','Wands','Books','Gems & Jewelry','Clothing','Boots & Gloves','Gi +rdles & Helms','Bags & Bottles','Dust & Stones','Household Items','Mu +sical Instruments','Weird Stuff','Humorous Items','Armor and Shields' +,'Weapons','Artifacts'); my @Magic_Item_Group = ( "magic items in the $Magic_Item_Type[rand @Magic_Item_Type] group", "all magic items" ); my @Magic_Items = ( "can use all magic items", "can not use any magic items", "can only use magic items in the $Magic_Item_Type[rand @Magic_Item_Typ +e] group", "can not use magic items in the $Magic_Item_Type[rand @Magic_Item_Type +] group", "causes $Magic_Item_Group[rand @Magic_Item_Group] to dysfunction $radi +us", "causes $Magic_Item_Group[rand @Magic_Item_Group] to loose their power + $radius", "attracts $Magic_Item_Group[rand @Magic_Item_Group] $radius", "repels $Magic_Item_Group[rand @Magic_Item_Group] $radius", "destroys $Magic_Item_Group[rand @Magic_Item_Group] $radius" ); my @Other_Magic = ( "magic dead", "a $Radius[rand @Radius] radius Wild Magic zone", "a magic attracter", "addicted to magic energies" ); my @ImDm = ( "immune to", "takes ×2 dmg from" ); my @AbilityName = qw(strength dexterity constitution intelligence wisd +om charisma); my @Class = qw(Warrior Rogue Priest Wizard Psionisist); my @WeapType = qw(bludgeoning piercing slashing missile); my @WeapMat = qw(bone metal stone wooden); my @WeapMag = ("non-",""); my @Weapon = ( "$WeapType[rand@WeapType]", "$WeapMat[rand@WeapMat]", "$WeapMag[rand@WeapMag]magical" ); my @LNW = ('language',non-weapon proficiency','weapon'); my @NWPlearn = ( "$AbilityName[rand @AbilityName] based", "$Class[rand @Class] specific" ); my @SavThrow = ('Paralyzation','Poison','Death Magic','Rods','Staves', +'Wands','Petrifaction','Polymorph','Breath Weapon','Spells'); my @SATS = ( "to saving throws vs. $SavThrow[rand @SavThrow]", "Armor Class", "THAC0 modifier", "to Surprise" ); my @WMS = ('all crtical misses','failed backstabs','failed saving thro +ws'); my @Gaze = qw(Paralysis Stone Stun Death); my @Vocal = qw(Deafen Fear Terror Flight); my @Effect1 = qw{Acid Cold Electricity Fire Gas Sonic); my @Effect2 = qw(Acid Cold Electricity Fire Poison Energy Drain); my @Effect3 = qw(Acid Cold Electricity Fire Energy Drain Gas Poison So +nic); my @Attack =( "Breath Weapon - $Effect1[rand @Effect1] for $Dice[rand @Dice] damage" +, "Gaze Attack - $Gaze[rand @Gaze]", "Touch Attack - $Effect2[rand @Effect2] for $Dice[rand @Dice] damage", "Vocal Attack - $Vocal[rand @Vocal]" ); my @Spells = ( "all Wizard spells", "all Priest spells", "the $Wizard_School[rand @Wizard_School] school of wizard spells", "the $Cleric_Sphere[rand @Cleric_Sphere] sphere of priest spells", "$Effect3[rand @Effect3] spells and spell-like effects", "all spells" ); my @Metal = qw(platinum gold silver copper nickel bronze tin iron stee +l lead aluminum); my @Gem = qw(diamond ruby sapphire emerald amethyst garnet spinel zirc +on crystal quartz); my @Emotion = qw(joy sorrow trust fear love hate indifference); my @Align = qw(lawful chaotic good evil neutral) my @Colors = ( "f00;\">red", "ff0;\">yellow", "0f0;\">green", "0ff;\">cyan", "00f;\">blue", "f0f;\">magenta", "fff;\">white", "000;\">black" ); my $Color = "<span class=\"mut\" style=\"color:#$Colors[rand @Colors]< +/span>"; my @Animal = ( "amphibian", "insetoid", "$Mammal[rand @Mammal]", "reptilian" ); my @Mammal = ( "<a title=\"cattle\">bovine</a>", "<a title=\"dog\">canine</a>", "<a title=\"goat\">caprine</a>", "<a title=\"horse\">equine</a>", "<a title=\"cat\">feline</a>", "<a title=\"rabbit\">leporine</a>", "<a title=\"wolf\">lupine</a>", "<a title=\"sheep\">ovine</a>", "<a title=\"pig\">porcine</a>", "<a title=\"bear\">ursine</a>", "<a title=\"fox\">vulpine</a>" ); my @Animal2 = qw(amphibian insetoid mammallian reptilian); my @Head = ( "an enlarged head", "a shrunken head", "horns" ); my @Size = qw(taller shorter); my @Eyes = ( "glowing eyes", "the appearance of no eyes", "$Color eyes", "eyes in an odd position", "only one eye", roll '1d4+2'" eyes", "infravision<p class=\"muti\">&#0134; ultravision if infravision is al +ready present</p>", #"{If~{Dice~d100}>80?red/green}-weakness color blindness", ##Don't kno +w if statements yet. "photo-sensitivity" ); my @Ears = ( "lobeless ears", "only ear holes", "no ears", "extra-sensitive hearing", roll '1d10*10'"&#037; deafness", roll '1d4+2'" ears" ); my @Nose = ( "an oversized nose", "only nose holes", "no nose", "a nose with an $Animal[rand @Animal] appearance", "an extra-sensitive nose", "no sense of smell" ); my @Mouth = ( "$Color lips", "no lips", "an oversized mouth", roll '1d2+1'" mouths" ); my @Arms = ( "arms that are "roll '1d50'"&#037; longer than average", "arms that are "roll '1d50'"&#037; shorter than average", "no elbow joint", "no wrist joint", roll '1d4+2'" arms (all arms above triple the normal amount are vestig +ial)", "$Animal[rand @Animal]-like arms" ); my @Hands = ( "elongated fingers", "one less finger on each hand", "double jointed fingers", "animal claws", "snake fingers", "webbed fingers" ); my @Legs = ( "legs that are "roll '1d50'"&#037; longer than average", "legs that are "roll '1d50'"&#037; shorter than average", "no knee joint", "no ankle joint", roll '1d4+2'" legs (all legs above double the normal amount are vestig +ial)", "$Animal[rand @Animal] legs" ); my @Feet = ( "elongated toes", "one less toe on each foot", "no toes", "animal paws", "claws for toes", "webbed toes" ); my @Skin = ( "fur covered skin", "$Animal[rand @Animal] skin", "fish scales", "feathers", "invisible skin", "$Color skin", "ultra-sensitive skin" ); my @Bones = ( "wooden bones", "$Gem[rand @Gem] bones", "$Metal[rand @Metal] bones", "fragile bones", "unbreakable bones" ); my @Teeth = ( "enlarged teeth", "fangs", "fangs with venom", "$Gem[rand @Gem] teeth", "$Metal[rand @Metal] teeth", "two sets of teeth" ); my @Hair = ( "$Color hair", "odd textured hair", "uncuttable hair", "no hair anywhere", "invisible hair", "$Metal[rand @Metal] hair" ); my @Nails = ( "$Gem[rand @Gem] nails", "$Metal[rand @Metal] nails", "no nails", "unbreakable nails" ); my @Blood = ( "icor for blood", "poisonous blood", "$Color blood" ); my @Body_Part = ( "$Skin[rand @Skin]", "$Bones[rand @Bones]", "$Blood[rand @Blood]", "$Head[rand @Head]", "$Hair[rand @Hair]", "$Eyes[rand @Eyes]", "$Ears[rand @Ears]", "$Nose[rand @Nose]", "$Mouth[rand @Mouth]", "$Teeth[rand @Teeth]", "$Arms[rand @Arms]", "$Hands[rand @Hands]", "$Legs[rand @Legs]", "$Feet[rand @Feet]", "$Nails[rand @Nails]", "$Animal2[rand @Animal2] wings", "$Animal[rand @Animal] tail", "gills" ); my @BodyPart = ( "eye", "lip", "nail", "nose", "hair", "skin", "entire body" ); my @Aura = ( "visible $Color", "$Emotion[rand @Emotion]", "$Align[rand @Align]" ); my @Things = ( "animals", "plants", "constructs", "dragons", "lycenthropes", "undead", "inanimate objects" ); my @Touch =( "befouls", "purifies", "nullifies holy water", "nullifies unholy water" ); my @Sleep = ( "hardly ever wakes up", "needs twice as much sleep", "needs half as much sleep", "does not need sleep", "is an insomniac", "is a narcoleptic", "unable to remember the past after sleeping" ); my @Eat = ( "can't stop eating", "needs twice as much food", "needs half as much food", "does not need to eat", "is carnivorous", "is herbivorous", "is lethargic after eating any amount of food" ); my @Drink = ( "can't stop drinking", "needs twice as much liquid", "needs half as much liquid", "does not need liquids", "is an alcoholic", "can not get drunk", "is intoxicated after injesting any liquid" ); my @SED = ( "$Sleep[rand @Sleep]", "$Eat[rand @Eat]", "$Drink[rand @Drink]", "$Sleep[rand @Sleep] and $Eat[rand @Eat]", "$Sleep[rand @Sleep] and $Drink[rand @Drink]", "$Eat[rand @Eat] and $Drink[rand @Drink]", "$Sleep[rand @Sleep], $Eat[rand @Eat], and $Drink[rand @Drink]" ); my @Divine = ( "Demi-Power", "Lesser Power", "Intermediate Power", "Greater Power", ); my @Mutation = ( "no unusual effect", #"<table class="as">[Ability]</table>", #"<p class="mut">[SubAbility]</p>", "casts up to $Spell_Freq[rand @Spell_Freq] $Wizard School[rand @Wizard +_School] school spells as a natural ability |Dc=[Dice]| %Dc% {If~%Dc% +=1?time/times} (AorAn) $Time[rand @Time]<p class=muti>&#0134; see the + Wizard Spell progession for maximum spell level.</p>", "casts up to $Spell_Freq[rand @Spell_Freq] $Cleric Sphere[rand @Cleric +_Sphere] sphere spells as a natural ability |Dc=[Dice]| %Dc% {If~%Dc% +=1?time/times} (AorAn) $Time[rand @Time]<p class=muti>&#0134; see the + Priest Spell progession for maximum spell level.</p>", "$Resist[rand @Resist] to $Spells[rand @Spells]", "$Magic_Items[rand @Magic_Items]", "<p class=\"mut\">is $Other_Magic[rand @Other_Magic]</p>"' "$ImDm[rand @ImDm] $Weapon[rand @Weapon] weapons", "takes only magical damage", "knows one $LNW[rand @LNW] that parent knows", "knows all {Plural~$LNW[rand @LNW]} that parent knows", "unable to learn {Plural~$LNW[rand @LNW]} parent knows", "unable to learn any language other than racial language", "$PM[rand @PM]{Dice~1d4} on all non-weapon proficiency checks", "unable to learn $NWPlearn[rand @NWPlearn] non-weapon proficiencies", "unable to learn $WeapType[rand @WeapType] weapons", "can not use $WeapMat[rand @WeapMat] weapons" "born already at "ordinate($Dice[rand @Dice])" level", ##Don't know if + this will work. "unable to advance past "ordinate(roll '5d6')" level", ##Don't know if + this will work. "$PM[rand @PM]"roll '1d10'" $SATS[rand @SATS]", ##Don't know if this w +ill work. "a Wild Magic Surge accompanies $WMS[rand @WMS]", "attacks as a Warrior of the same level. If already a Warrior, attacks + at 1 level higher.", "can not make a Critical Hit", #"attracts these followers: <ul>{Loop~{Dice~2d6}}</ul>", ##Rangers fol +lowers will be in a seperate file, but it is not done yet. "repels all animals $radius", "backstabs as a thief of the same level. If already a thief, backstabs + at 1 level higher.", "turns undead as a priest of the same level. If already a priest, turn +s at 1 level higher.", #"Wild Psionic Talent: (Wild Psionic Talents random roll goes here, th +ere will be a loop)", ##Psionic Talents will be in a seperate file. "unable to use Psionics", #"<span class="bold">Special Attack:</span> $Attack[rand @Attack] (|Dc +=[Dice]|%Dc% {If~%Dc%=1?time/times} (AorAn) $Time[rand @Time])", "is "roll '1d50'"&#037; $Size[rand @Size] than average", ##Don't know +if this will work. "has $Body_Part[rand my @Body_Part]", "can change $BodyPart[rand @BodyPart] color at will to $Color", @BodyPart=roll '1d3'"s turn $Color when magic is used $radius", ##Don' +t know if this will work. @BodyPart=roll '3d2+1'" turns $Color when magic is used $radius", ##Do +n't know if this will work. "has (AorAn) $Aura[rand @Aura] aura", "communicates with $Things[rand @Things] $radius", "knows history of $Things[rand @Things] $radius", "is blessed", "is cursed", "touch $Touch[rand @Touch]", @SED=roll '1d3', ##Don't know if this will work. #"[Insanities]", ##Insanities will be in a seperate file. #"has characteristics of (AorAn) [All monsters]", ##All Monsters will +be in a seperate file. #"has lycanthropy as a [Lycanthrope]", ##Lycanthrope will be in a sepe +rate file. #"[SED] after seeing (AorAn) [All monsters] for a [Time={Dice~1d4+3}]" +, ##All Monsters will be in a seperate file. "is $Divine[rand @Divine] - character should be retired" ); print "<h1>Character Mutations</h1><h2>by Dawn M. Burge</h2><p class=\ +"mut\">All effects are cumulative, and one can be cancelled out by an +other.</p><div class=\"mut\"><ol>Loop=$Dice[rand @Dice],<li>$Mutation +[rand @Mutation]</li>}</ol></div>";
Update 1: Some of the smaller syntax errors fixed. Update 2: Some of the arrays have been altered.

Replies are listed 'Best First'.
Re^2: Creating a random generator
by Limbic~Region (Chancellor) on Sep 26, 2007 at 00:21 UTC

      Thank you for the fabulous breakdown of issues you see. Let me see if I understand them.

      The first item is that you suggested that I add -T to the shebang line. I was already told to add -w (after reading perlrun, I may possibly go to -W instead). Can both be added to the shebang?

      Do the following two items duplicate the same thing? If they do, I would choose to keep the first.

      use CGI; use CGI::Carp qw(fatalsToBrowser);
      print "content-type: text/html \n\n";

      I now only have the following in my code...

      my @Dice = qw(1d4 1d6 1d8 1d10 1d12 1d20);

      @Dice2 became redundant.

      You expressed concern for my variable names, with the example being @Radius and $radius. I have been using the capitalized version for the array in the original TableSmith version, and the lowercase version for the phrase fragment for a while now. I can tell the difference.

      All of the data in the script is static. As far as I know the arrays will only change if I think of something to add to them and write it into the code manually. The only thing that will change is the amount of times the user wants to run the script and the amount of times each random element will be called. The script as it is now is only a fragment of what is yet to come. I have a lot of markup to add to make this into a web page. I also have several other sub scripts to write that will be used by this one (but each of those must stand alone as well).

      The original way I wrote the array dealing with the colors was...

      my @Color = ( "<span class=\"mut\" style=\"color:#f00;\">red</span>", "<span class=\"mut\" style=\"color:#ff0;\">yellow</span>", "<span class=\"mut\" style=\"color:#0f0;\">green</span>", "<span class=\"mut\" style=\"color:#0ff;\">cyan</span>", "<span class=\"mut\" style=\"color:#00f;\">blue</span>", "<span class=\"mut\" style=\"color:#f0f;\">magenta</span>", "<span class=\"mut\" style=\"color:#fff;\">white</span>", "<span class=\"mut\" style=\"color:#000;\">black</span>" );
      I thought that this would save me a few bytes...
      my @Colors = ( "f00;\">red", "ff0;\">yellow", "0f0;\">green", "0ff;\">cyan", "00f;\">blue", "f0f;\">magenta", "fff;\">white", "000;\">black" ); my $Color = "<span class=\"mut\" style=\"color:#$Colors[rand @Colors]< +/span>";
      But you think a hash is better?
      my %Colors = ( red =>f00, yellow =>ff0, green =>0f0, cyan =>0ff, blue =>00f, magenta =>f0f, white =>fff, black =>000 );
      How would you make that randomly selected and inserted into the following?
      <span class="mut" style="color:(color code)">(color name)</span>
      As soon as I get the entire script working, I will be getting rid of all unnecessary whitespace from it. I just hope that this doesn't go above the amount of bytes I have alloted for it.
        Lady_Aleena,
        Can both be added to the shebang?

        Yes. With regards to -w, -W, and use warnings, You should read perlrun and compare it to warnings as typically they are not used in tandem.

        Do the following two items duplicate the same thing? If they do, I would choose to keep the first.

        No, they don't do the same thing. You should read the documentation for CGI and CGI::Carp to understand what both are doing and why you may need each of them.

        I now only have the following in my code...

        That's good. Removing redundant code makes the remaining code easier to understand. The point I was trying to make was more about how you were declaring the variables then having both though. The two lines of code I wrote to replace your original is much more succinct and clear. I know that you may not understand the map call but in the long run you will prefer to make perl do the work.

        You expressed concern for my variable names...I can tell the difference.

        Can the people you are asking for help tell the difference? If your project gains success and you choose to collaborate with others, will they be able to contribute? The point of writing maintainable code is very seldom about your ability to understand it.

        All of the data in the script is static....

        Then my point is very valid then. Separating your data from your code will make your code much easier to understand and manipulate. I would seriously consider storing all the data externally as I suggested. You will be amazed at how much easier your code is to read.

        The original way I wrote the array dealing with the colors was...I thought that this would save me a few bytes...But you think a hash is better?

        I think that you should use the data structure that best fits your data. If you want to have a relationship between a color name and the code to generate the color, then a hash better fits than an array. If you just want a list of values with no relationship then the array is fine. The important thing is choosing what best fits.

        How would you make that randomly selected and inserted into the following?

        I would probably do something like this (untested):

        sub get_random_color { my %color = ( red => f00, yellow => ff0, green => 0f0, cyan => 0ff, blue => 00f, magenta => f0f, white => fff, black => 000 ); my $choice = (keys %color)[rand keys %color]; return '<span class="mut" style="color:' . $color{$choice} . ';">' + . $choice . '</span>'; }

        Cheers - L~R

Re^2: Creating a random generator
by Anno (Deacon) on Sep 25, 2007 at 20:27 UTC
    First things first. You say

    Anywhere you see (AorAn) is where I hope the perl has a nice little way of looking at the first character of the following word and adding "a" or "an".

    If you don't expect too much, this substitution should do that. It changes th word "a" to "an" if the following word begins with a vowel character.

    s/\ba(?=\s+[AEIOUaeiou])/an/g
    It doesn't deal with "a unicorn" or "an hour" and other vagaries of pronunciation.

    As to your code, there's a lot of it and I haven't looked at every line by far. One thing that stands out is that there is little separation of code and data. You have a lot of global hashes and arrays, and later ones seem to rely on earlier ones in uncomfortable ways. Ultimately, these would belong in a single (or a few) configurable hashes, with the configuration data in an external file.

    Otherwise, your code has a massive amount of syntax errors, too many to correct on the fly. It will be nearly impossible to debug remotely, relying only on fatalsToBrowser. You must find a way to run your script locally from a shell so that you can eliminate syntax errors before commiting it to a web server (even a local web server), or indeed, for discussion among perl monks.

    Anno

Re^2: Creating a random generator
by ysth (Canon) on Sep 25, 2007 at 22:12 UTC
    Anywhere you see (AorAn) is where I hope the perl has a nice little way of looking at the first character of the following word and adding "a" or "an".
    Lingua::EN::Inflect