#! /usr/bin/perl

# Copyright (C) 2018 Arne Wichmann
#
# This little thing is distributed under the GNU General Public License,
# version 2. If you need the license, ask your distributor for it.

# BUG: this is barely random
# one more try to improve that:
# srand (time ^ $$ ^ unpack "%L*", `ps axww | gzip -f`);
# srand (time ^ $$ ^ unpack "%L*", `head -c 100 /dev/urandom | gzip -f`);

use strict;

my($count)=shift;
my($subtable)=shift unless $count eq '-l';

# Initialisation, using a structure like Data::Dumper would generate
# using (hopefully, this is untested):
# my(@outdata)=($table);
# use Data::Dumper;
# $Data::Dumper::Indent=1;
# print Dumper \@outdata;
# exit 0;

our($VAR1);
for (@ARGV) { do "./$_"; }
our($table)=$VAR1->[0];

if ($count eq '-l') { print(join("\n",keys(%{$table})),"\n"); exit 0; }

while ($count--) {
  print join("\n",rolltable(@{$table->{$subtable}}));
  print "\n";
}

exit 0;

# gets array with weights and values
# gives rolled value
sub rolltable(@) {
  my($sum);
  my($nr)=d($sum=sumtable(@_));
  #print STDERR "$sum $nr ";
  $sum>0 or die "sum of table not positive";
  while (($nr-=shift)>0) { shift; }
  local($_)=$_[0];
  while (/\[([^\]]+)\]/) {
    my($sub)=$1;
    my($res);
    # eval is evil, but here it saves a lot. let's call it linguistic
    # reflection ;)
    # TODO: add some error handling - $sum can be invalid
    if ($sub=~s/^\&//) { $res=eval($sub); }
      else { $res=rolltable(@{$table->{$sub}}); }
    s/\[([^\]]+)\]/$res/;
  }
  return $_;
}

# gets array with weights and values
# gives sum of weights
sub sumtable(@) {
  my($nr)=0;
  while (@_) { $nr+=shift; shift; }
  return $nr;
}

sub d($;$) {
    my($num)=($#_?shift:1);
    my($size)=shift;
    my($res)=0;
    for(1..$num) {
        $res+=int(rand($size))+1;
    }
    return $res;
}

# this is for use in tables...
sub positive($) { return $_[0]>0?$_[0]:0;}

