#!/usr/bin/perl -w
use strict;
my $amount = 100 * 1000;
#######################################################
my %realms =
(
"Fire" => 1,
"Cold" => 1,
"Lightning" => 1,
"Poison" => 2,
"Acid" => 3,
"Air" => 5,
"Earth" => 5,
"Mind" => 7,
"Shield" => 7,
"Chaos" => 7,
"Magic" => 10,
"Antimagic" => 10
);
my %powers =
(
"Fire" => {
"Add to Light" => 1,
"Slay Undead Brand" => 1,
"Fire Brand" => 1,
"Resist Fire" => 1,
"Fire Aura" => 1
},
"Cold" => {
"Cold Brand" => 1,
"Slay Dragon Brand" => 1,
"Slay Demon Brand" => 1,
"Resist Cold" => 1,
"Invisibility" => 1,
"Slow Digestion" => 1
},
"Lightning" => {
"Electricity Brand" => 1,
"Slay Evil Brand" => 1,
"Resist Electricity" => 1,
"Electric Aura" => 1,
"Random Teleportation" => 1
},
"Poison" => {
"Add to Charisma" => 1,
"Sustain Charisma" => 1,
"Poison Brand" => 1,
"Vampiric Brand" => 1,
"Slay Animal Brand" => 1,
"Resist Poison" => 1,
"Drain Experience" => 1,
"Sense Trolls" => 1,
"Sense Giants" => 1
},
"Acid" => {
"Add to Tunnelling" => 1,
"Acid Brand" => 1,
"Slay Animal Brand" => 1,
"Earthquake Brand" => 1,
"Resist Acid" => 1
},
"Air" => {
"Add to Wisdom" => 1,
"Add to Stealth" => 1,
"Add to Infravision" => 1,
"Add to Speed" => 1,
"Sustain Wisdom" => 1,
"Resist Light" => 1,
"Resist Dark" => 1,
"Resist Blindness" => 1,
"Levitation" => 1,
"See Invisible" => 1,
"Blessed" => 1,
"Sense Good" => 1
},
"Earth" => {
"Add to Strength" => 1,
"Add to Constitution" => 1,
"Add to Tunnelling" => 1,
"Add to Blows" => 1,
"Sustain Strength" => 1,
"Sustain Constitution" => 1,
"Slay Troll Brand" => 1,
"Slay Giant Brand" => 1,
"Earthquake Brand" => 1,
"Resist Fear" => 1,
"Resist Shards" => 1,
"Free Action" => 1,
"Regeneration" => 1,
"Sense Trolls" => 1,
"Sense Giants" => 1
},
"Mind" => {
"Add to Intelligence" => 1,
"Add to Searching" => 1,
"Sustain Intelligence" => 1,
"Resist Confusion" => 1,
"Resist Fear" => 1,
"Sense Orcs" => 1,
"Sense Trolls" => 1,
"Sense Giants" => 1,
"Sense Animals" => 1,
"Sense Uniques" => 1,
"Sense Spiders" => 1,
"Sense Demons" => 1
},
"Shield" => {
"Add to Dexterity" => 1,
"Sustain Dexterity" => 1,
"Resist Sound" => 1,
"Resist Nexus" => 1,
"Invisibility" => 1,
"Reflection" => 1,
"Hold Life" => 1,
"Regeneration" => 1
},
"Chaos" => {
"Chaos Brand" => 1,
"Earthquake Brand" => 1,
"Resist Chaos" => 1,
"Resist Disenchantment" => 1,
"Regeneration" => 1,
"Telepathy" => 1
},
"Magic" => {
"Add to Mana" => 1,
"Add to Spellpower" => 1,
"Cloning Brand" => 1,
"Resist Chaos" => 1,
"Resist Disenchantment" => 1,
"Wraithform" => 1,
"Precognition" => 1,
"Flight" => 1
},
"Antimagic" => {
"Add to Blows" => 1,
"Add to Speed" => 1,
"Add to Life" => 1,
"Vampiric Brand" => 1,
"Chaos Brand" => 1,
"Reflection" => 1,
"Free Action" => 1,
"Hold Life" => 1,
"No Teleportation" => 1,
"See Invisible" => 1,
"Anti-magic shell" => 1,
"Antimagic field 1" => 1,
"Antimagic field 2" => 1
}
);
my @realm_order =
(
"Fire",
"Cold",
"Lightning",
"Poison",
"Acid",
"Air",
"Earth",
"Mind",
"Shield",
"Chaos",
"Magic",
"Antimagic"
);
sub one_weapon {
my $i;
my $weap = {realms => [], points => 0, total_points => 0,
pval => 0, to_h => 0, to_d => 0, powers => [],
powers_avail => {}, failed_power_gains => 0};
my $chance;
for ($i = 1; $i < 50; $i++) {
$chance = int(rand(100));
if ($chance < 33) {
if (rand(100) < 50) {
$weap->{to_h}++;
}
else {
$weap->{to_h} += 2;
}
$weap->{to_d}++
}
elsif ($chance < 66) {
$weap->{points}++;
$weap->{total_points}++;
$weap->{to_h}++;
$chance = int(rand(100));
if ($chance < 40) {
gain_realm($weap);
} # gain realm
} # gain point
else {
if (@{$weap->{realms}} == 0) {
gain_realm($weap);
}
gain_power($weap);
if ($weap->{pval} < 5) {
if ($weap->{pval} == 0) {
$weap->{pval} = 1;
} # if ($weap->{pval} == 0)
else {
while (rand(100) < (20 - ($weap->{pval} * 2))) {
$weap->{pval}++;
}
if ($weap->{pval} >= 5) {
$weap->{pval} = 5;
$weap->{pval_maxed} = $i + 1;
}
} # $weap->{pval} > 0
} # if ($weap->{pval} < 5)
}
} # gain levels
return $weap;
} # one_weapon()
sub gain_realm {
my($weap) = @_;
my %available = %realms;
my($i, $realm);
for ($i = 0; $i < @{$weap->{realms}}; $i++) {
$realm = $weap->{realms}->[$i];
# Already have that realm?
delete($available{$realm});
}
# Get rid of too-expensive realms
foreach $realm (keys %available) {
if ($available{$realm} > $weap->{points}) {
delete($available{$realm});
}
}
return if keys(%available) == 0;
my @avail_arr = keys(%available);
$realm = $avail_arr[int(rand(@avail_arr))];
push(@{$weap->{realms}}, $realm);
$weap->{points} -= $realms{$realm};
# Add to list of available powers
my %new_powers = %{$powers{$realm}};
my $power;
foreach $power (keys(%new_powers)) {
$weap->{avail_powers}->{$power} = 1;
}
# But don't re-add to the available list powers we already have
foreach $power (@{$weap->{powers}}) {
delete($weap->{avail_powers}->{$power});
}
} # gain_realm()
sub gain_power {
my($weap) = @_;
my @avail = keys(%{$weap->{avail_powers}});
if (@avail == 0) {
$weap->{failed_power_gains}++;
return;
}
my $power = $avail[int(rand(@avail))];
push(@{$weap->{powers}}, $power);
delete($weap->{avail_powers}->{$power});
} # gain_realm()
#############################################
sub print_amount {
my $weapons = shift(@_);
my $func = shift(@_);
my($i, @levels, $num);
my $total = 0;
for ($i = 0; $i < $amount; $i++) {
$num = &$func($weapons->[$i], @_);
$total += $num;
$levels[$num]++;
}
print "Average value is ", $total / $amount, "\n\n";
for ($i = 0; $i < scalar(@levels); $i++) {
my $val = $levels[$i];
next if (!$val || $val == 0);
printf("%4i: %3i.%03i%%\n", $i, $val * 100 / $amount,
($val * 100 * 1000 / $amount) % 1000);
}
print "\n------------------------------------\n";
}
sub print_pct {
my $weapons = shift(@_);
my $func = shift(@_);
my($i, $num);
$num = 0;
for ($i = 0; $i < $amount; $i++) {
$num++ if &$func($weapons->[$i], @_);
}
printf("%3i.%03i%%", $num * 100 / $amount,
($num * 100 * 1000 / $amount) % 1000);
}
#####################################
#####################################
#####################################
# Main
my $i;
my @weapons;
for ($i = 0; $i < $amount; $i++) {
push(@weapons, one_weapon());
my $weap = $weapons[$i];
}
print "Simulated $amount sentient weapons.\n\n";
print "Percent of weapons which gained each realm: \n";
my %realms_gained;
my $realm;
for ($i = 0; $i < $amount; $i++) {
my $weap = $weapons[$i];
my $realm;
foreach $realm (@{$weap->{realms}}) {
$realms_gained{$realm}++;
}
}
foreach $realm (@realm_order) {
my $gained = $realms_gained{$realm} || 0;
printf("%-10s: %3i.%03i%%\n", $realm, $gained * 100 / $amount,
($gained * 100 * 1000 / $amount) % 1000);
}
print "\n------------------------------------\n";
#########
sub num_realms {
my($weap) = @_;
return scalar(@{$weap->{realms}});
}
print "\n Number of realms gained\n\n";
print_amount(\@weapons, \&num_realms);
#########
sub final_pval {
my($weap) = @_;
return $weap->{pval};
}
print "\n Final pval\n\n";
print_amount(\@weapons, \&final_pval);
#########
sub to_h_gained {
my($weap) = @_;
return $weap->{to_h};
}
print "\n to_h gained \n\n";
print_amount(\@weapons, \&to_h_gained);
#########
sub to_d_gained {
my($weap) = @_;
return $weap->{to_d};
}
print "\n to_d gained \n\n";
print_amount(\@weapons, \&to_d_gained);
#########
sub num_total_points {
my($weap) = @_;
return scalar($weap->{total_points});
}
print "\n Number of points acquired over 49 level gains\n\n";
print_amount(\@weapons, \&num_total_points);
#########
sub num_points_left {
my($weap) = @_;
return scalar($weap->{points});
}
print "\n Total number of points left unspent\n\n";
print_amount(\@weapons, \&num_points_left);
#########
print "\n";
sub realm_combos {
my($weap, $realms, $amnt) = @_;
my %realm_hash;
my $realm;
my $num = 0;
foreach $realm (@{$realms}) {
$realm_hash{$realm} = 1;
}
foreach $realm (@{$weap->{realms}}) {
$num++ if ($realm_hash{$realm});
}
return ($num == $amnt);
}
print "Weapons with only one of Fire, Cold or Lightning: ";
print_pct(\@weapons, \&realm_combos, ["Fire", "Cold", "Lightning"], 1);
print "\n";
print "Weapons with two of Fire, Cold or Lightning: ";
print_pct(\@weapons, \&realm_combos, ["Fire", "Cold", "Lightning"], 2);
print "\n";
print "Weapons with all of Fire, Cold and Lightning: ";
print_pct(\@weapons, \&realm_combos, ["Fire", "Cold", "Lightning"], 3);
print "\n";
print "Weapons with only one of Air or Earth: ";
print_pct(\@weapons, \&realm_combos, ["Air", "Earth"], 1);
print "\n";
print "Weapons with both Air and Earth: ";
print_pct(\@weapons, \&realm_combos, ["Air", "Earth"], 2);
print "\n";
print "Weapons with only one of Mind, Shield or Chaos: ";
print_pct(\@weapons, \&realm_combos, ["Mind", "Shield", "Chaos"], 1);
print "\n";
print "Weapons with two of Mind, Shield or Chaos: ";
print_pct(\@weapons, \&realm_combos, ["Mind", "Shield", "Chaos"], 2);
print "\n";
print "Weapons with all of Mind, Shield and Chaos: ";
print_pct(\@weapons, \&realm_combos, ["Mind", "Shield", "Chaos"], 3);
print "\n";
print "Weapons with only one of Magic or Antimagic: ";
print_pct(\@weapons, \&realm_combos, ["Magic", "Antimagic"], 1);
print "\n";
print "Weapons with both Magic and Antimagic: ";
print_pct(\@weapons, \&realm_combos, ["Magic", "Antimagic"], 2);
print "\n";
##########################################################################
##########################################################################
# Now do powers
print "\n##########################################\n";
sub num_powers {
my($weap) = @_;
return scalar(@{$weap->{powers}});
}
print "\n Number of powers acquired\n\n";
print_amount(\@weapons, \&num_powers);
###
sub failed_power_gains {
my($weap) = @_;
return $weap->{failed_power_gains};
}
print "\n Number of power gain attempts which failed \n\n";
print_amount(\@weapons, \&failed_power_gains);
###
my %power_count = ();
my $power;
for ($i = 0; $i < $amount; $i++) {
my $weap = $weapons[$i];
foreach $power (@{$weap->{powers}}) {
$power_count{$power}++;
}
}
print "Powers gained: \n\n";
foreach $power (sort(keys(%power_count))) {
my $val = $power_count{$power};
printf("%-22s: %3i.%03i%%\n", $power, $val * 100 / $amount,
($val * 100 * 1000 / $amount) % 1000);
}
Spoilers/Sentient Weapons/Statistics/stats.pl (last edited 2006-03-10 19:48:36 by KhymChanur)