#!/usr/bin/perl use strict; use Games::Dice qw(roll); use Data::Dumper; my %Data; my %field_func = ( # functions cited in the data file roll => \&roll, radius => sub { "in a " . Random( "Radius" ) . " radius" }, ); sub Random # selection of an element from a list { my ( $ary_name ) = @_; my $ary_size = scalar @{$Data{$ary_name}}; return $Data{$ary_name}[ rand( $ary_size ) ]; } sub DataString # applies string replacements where needed { local $_ = shift; while ( /(([@&])_(\S+))/ ) { my ( $source, $rep_type, $src_name ) = ( $1, $2, $3 ); my $rep_str; if ( $rep_type eq '@' ) { # need to choose randomly from another array $rep_str = DataString( Random( $src_name )); } else { # need to get a value from a function call my ( $func, @args ) = split /[=,]/, $src_name; $rep_str = $field_func{$func}->( @args ); } s/\Q$source\E/$rep_str/; } return $_; } # here is where we read the data file of array definitions; # the following block limits the scope for playing with $/ { $/ = ""; # input record separator set to "paragraph mode" while () { next unless ( /^\w+:/ ); chomp; my ( $ary_name, @vals ) = split /\s*[:|]\s*/; $Data{$ary_name} = \@vals; } } # here is where we run the selection (10 times, in this case, # but you can play with the control loop) print DataString( Random( 'Mutation' ))."\n" for ( 1..10 ); # the rest is the sample data file __DATA__ # sample data file based on data snippets from the OP: AbilityName: strength | dexterity | constitution | intelligence | wisdom | charisma Class: Warrior | Rogue | Priest | Wizard | Psionist WeapType: bludgeoning | piercing | slashing | missile WeapMat: bone | metal | stone | wooden Dice: 1d4 | 1d6 | 1d8 | 1d10 | 1d12 | 1d20 Eff3: Acid | Cold | Electricity | Fire | Energy Drain | Gas | Poison | Sonic Radius: 1' or Touch | 5' | 10' | 20' | 50' | 100' Resist: immune | is &_roll=1d100 % magic resistant | has no resistance Spells: all spells | all Wizard spells | all Priest spells | @_Eff3 NWPlearn: @_AbilityName based | @_Class specific Mutation: no unusual effect | general ability | has little @_AbilityName compared to @_Class | @_Resist to @_Spells | unable to learn @_NWPlearn non-weapon proficiencies | unable to learn @_WeapType weapons | cannot use @_WeapMat weapons # end of sample data file