#!/usr/bin/perl # Calulate the odds of the wolves winning a game of werewolf. # # Bruno Wolff III # July 9, 2001 # Updated July 21, 2001 # # Assume no Seer information is available until he reveals it publically. # Once this happens the wolves will kill him. If he is picked to be lynched, # he will go public and not be lynched. He will be believed when he goes # public. He will voluntarily go public when it makes sense to do so. # The state subscripts for $win are: # Number of unidentified human villagers # Number of identified human villagers # Number of unidentified wolves # Number of identified wolves # Number of Seers. (When Seer goes public, treat him as a normal identified # human as the wolves will target him next. So the identify information # can only be used if Seer count is 0 for purposes of lynching.) # Next stage to occur (0 - Lynch, 1 - Seer divination, 2 - Wolf dinner) $| = 1; $play = 0; while ($play < 1) { print STDERR "Up to how many players? "; $play = ; chop $play; $play =~ s/ //g; if ($play !~ m/^\d+$/ || $play < 1) { $play = 0; print STDERR "Invalid number of players.\n"; } } $wolf = 0; while ($wolf < 1) { print STDERR "Up to how many wolves? "; $wolf = ; chop $wolf; $wolf =~ s/ //g; if ($wolf !~ m/^\d+$/ || $wolf < 1 || $wolf >= $play) { $wolf = 0; print STDERR "Invalid number of wolves.\n"; } } for ($h=0; $h<=$play; $h++) { for ($w=0; $w<=$play-$h; $w++) { for ($s=0; $s<=1 && $s<=$h; $s++) { for ($v=0; $v<=$h-$s; $v++) { $vid = $h - $s - $v; for ($wun=0; $wun<=$w; $wun++) { $wid = $w - $wun; # The wolves win when all of the people are dead. if ($h == 0) { $win[$v][$vid][$wun][$wid][$s][0] = 1; $win[$v][$vid][$wun][$wid][$s][1] = 1; $win[$v][$vid][$wun][$wid][$s][2] = 1; } # The people win when all of the wolves are dead. elsif ($w == 0) { $win[$v][$vid][$wun][$wid][$s][0] = 0; $win[$v][$vid][$wun][$wid][$s][1] = 0; $win[$v][$vid][$wun][$wid][$s][2] = 0; } else { # Lynch # Kill wolf if known, otherwise choose randomly from unidentified villagers # and unidentified wolves if Seer revealed information, otherwise pick # random player, but give Seer a chance to reveal stuff. # If there are as many wolves as humans, only humans will get lynched. # (There should only be an odd number of players at this step or the # vote could deadlock.) if ($w >= $h) { $win[$v][$vid][$wun][$wid][$s][0] = ( ($v ? $v * $win[$v-1][$vid][$wun][$wid][$s][1] : 0) + ($vid ? $vid * $win[$v][$vid-1][$wun][$wid][$s][1] : 0) + ($s ? $s * $win[$v][$vid][$wun][$wid][$s-1][1] : 0)) / $h; } elsif ($s == 0) { if ($wid >= 1) { $win[$v][$vid][$wun][$wid][$s][0] = $win[$v][$vid][$wun][$wid-1][$s][1]; } else { $win[$v][$vid][$wun][$wid][$s][0] = ( ($v ? $v * $win[$v-1][$vid][$wun][$wid][$s][1] : 0) + ($wun ? $wun * $win[$v][$vid][$wun-1][$wid][$s][1] : 0)) / ($v + $wun); } } else { $wi = 0; if ($wid > 0) { $wi = $win[$v][$vid][$wun][$wid-1][$s][1]; $wi = $win[$v][$vid+1][$wun][$wid-1][$s-1][1] if $win[$v][$vid+1][$wun][$wid-1][$s-1][1] < $wi; } $vi = 0; if ($vid > 0) { $vi = $win[$v][$vid-1][$wun][$wid][$s][1]; $vi = $win[$v][$vid+1][$wun][$wid][$s-1][0] if $win[$v][$vid+1][$wun][$wid][$s-1][0] < $vi; } $si = $win[$v][$vid+1][$wun][$wid][$s-1][0]; if ($v + $wun > 0) { $u = (($v ? $v * $win[$v-1][$vid][$wun][$wid][$s][1] : 0) + ($wun ? $wun * $win[$v][$vid][$wun-1][$wid][$s][1] : 0)) / ($v + $wun); $u = $win[$v][$vid+1][$wun][$wid][$s-1][0] if $win[$v][$vid+1][$wun][$wid][$s-1][0] < $u; $win[$v][$vid][$wun][$wid][$s][0] = ($wid * $wi + $s * $si + $vid * $vi + ($v + $wun) * $u) / ($h + $w); } } # Hunt # The wolves will eat a random person unless there are an odd number of # players. (This should only happen the first night.) This means that # the hunt calculation needs to be done after the lynch calculation. # Wolves will eat identified villagers first. A Seer that goes public # can be treated as an identified villager. # If a Seer gets eaten here, he doesn't get to spill the beans. if (($h + $w) % 2 == 1) { $win[$v][$vid][$wun][$wid][$s][2] = $win[$v][$vid][$wun][$wid][$s][0]; } else { if ($s == 0 and $vid > 0) { $win[$v][$vid][$wun][$wid][$s][2] = $win[$v][$vid-1][$wun][$wid][$s][0]; } else { $win[$v][$vid][$wun][$wid][$s][2] = ( ($v ? $v * $win[$v-1][$vid][$wun][$wid][$s][0] : 0) + ($vid ? $vid * $win[$v][$vid-1][$wun][$wid][$s][0] : 0) + ($s ? $s * $win[$v+$vid][0][$wun+$wid][0][$s-1][0] : 0)) / $h } } # Divination # The Seer (if any) chooses to learn about an unidentified human or wolf. # This must be the last thing checked since the character counts might # not change and the hunt value needs to be already calculated. # Once there are as many wolves as people the seer no longer matters. # However we can't let the identified wolves keep increasing since we # assume there can only be one for efficiancy. if ($s == 0 || $v + $wun == 0 || $w >= $h) { $win[$v][$vid][$wun][$wid][$s][1] = $win[$v][$vid][$wun][$wid][$s][2]; } else { $win[$v][$vid][$wun][$wid][$s][1] = ( ($v ? $v * $win[$v-1][$vid+1][$wun][$wid][$s][2] : 0) + ($wun ? $wun * $win[$v][$vid][$wun-1][$wid+1][$s][2] : 0)) / ($v + $wun); } } } } } } } print " Wolves - Odds of wolves winning - Without seer / With seer\n"; print "Players "; for ($i = 1; $i<=$wolf; $i++) { printf " %-7d ", $i; } print "\n"; for ($j = 2; $j<=$play; $j++) { printf "%-7d", $j; for ($i=1; $i<=$wolf; $i++) { if ($j <= $i) { print " "; } else { printf " %7.5f/%7.5f", $win[$j-$i][0][$i][0][0][1], $win[$j-$i-1][0][$i][0][1][1]; } } print "\n"; }