use List::Util qw( sum ); sub simulate_mayhem { my @shipsInCombat = @_; # Initiative levels for each ship. # This is a parallel array to @shipsInCombat. my @ship_initiatives = map { $_->{thruster} * 2 + 1; } @shipsInCombat; while ( my $total_initiative = sum @ship_initiatives ) { my $chosen_initiative = rand $total_initiative; my $initiative_sum = 0; # Required - can't use the loop var after the loop # See PBP 6.9. Non-Lexical Loop Iterators my $chosen_ship_number; for my $ship_number ( 0 .. $#shipsInCombat ) { $initiative_sum += $ship_initiatives[$ship_number]; next if $initiative_sum <= $chosen_initiative; $chosen_ship_number = $ship_number; last; } die "Can't happen" if not defined $chosen_ship_number; my $chosen_ship = $shipsInCombat[$chosen_ship_number]; ship_does_something($chosen_ship); # Now reduce that ship to 0, so it cannot be picked again. $ship_initiatives[$chosen_ship_number] = 0; # If you want, you can recalculate {thruster} on any ship # affected by ship_does_something(), as long as you have a # way of tracking the ones that had used their initiative, # and force it back to 0. ### $ship_numbers_that_used_initiative{$chosen_ship_number} = 1; ### recalc_thrusters(\@shipsToAct); ### @ship_initiatives = map { ### $_->{thruster} * 2 + 1; ### } @shipsInCombat; ### ship_initiatives[$_] = 0 for keys %ship_numbers_that_used_initiative; } } # Loop exits when all ships have 0 initiative.