From f1171346f4edc9a7617c66ebf9d4c7fa993f0ba6 Mon Sep 17 00:00:00 2001 From: Marius Gavrilescu Date: Mon, 26 Aug 2013 23:13:06 +0300 Subject: [PATCH] Initial commit --- Changes | 4 + MANIFEST | 17 ++ Makefile.PL | 26 ++ README | 27 ++ lib/Mafia.pm | 576 +++++++++++++++++++++++++++++++++++++ t/00-use.t | 6 + t/examples.t | 19 ++ t/examples/Newbie-0001.out | 15 + t/examples/Newbie-0001.pl | 21 ++ t/examples/Newbie-0002.out | 15 + t/examples/Newbie-0002.pl | 21 ++ t/examples/Newbie-0003.out | 15 + t/examples/Newbie-0003.pl | 21 ++ t/examples/Newbie-0004.out | 24 ++ t/examples/Newbie-0004.pl | 28 ++ t/examples/Newbie-0005.out | 15 + t/examples/Newbie-0005.pl | 22 ++ 17 files changed, 872 insertions(+) create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 Makefile.PL create mode 100644 README create mode 100644 lib/Mafia.pm create mode 100644 t/00-use.t create mode 100644 t/examples.t create mode 100644 t/examples/Newbie-0001.out create mode 100644 t/examples/Newbie-0001.pl create mode 100644 t/examples/Newbie-0002.out create mode 100644 t/examples/Newbie-0002.pl create mode 100644 t/examples/Newbie-0003.out create mode 100644 t/examples/Newbie-0003.pl create mode 100644 t/examples/Newbie-0004.out create mode 100644 t/examples/Newbie-0004.pl create mode 100644 t/examples/Newbie-0005.out create mode 100644 t/examples/Newbie-0005.pl diff --git a/Changes b/Changes new file mode 100644 index 0000000..4ecf2c3 --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension Mafia. + +0.001 Mon 26 Aug 23:07:19 EEST 2013 + - Initial release diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..10b7764 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,17 @@ +Changes +Makefile.PL +MANIFEST +README +t/00-use.t +t/examples.t +t/examples/Newbie-0005.out +t/examples/Newbie-0003.pl +t/examples/Newbie-0001.out +t/examples/Newbie-0004.pl +t/examples/Newbie-0003.out +t/examples/Newbie-0001.pl +t/examples/Newbie-0004.out +t/examples/Newbie-0002.pl +t/examples/Newbie-0005.pl +t/examples/Newbie-0002.out +lib/Mafia.pm diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..ebf1e0c --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,26 @@ +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Mafia', + VERSION_FROM => 'lib/Mafia.pm', + ABSTRACT_FROM => 'lib/Mafia.pm', + AUTHOR => 'Marius Gavrilescu ', + MIN_PERL_VERSION => '5.14.0', + LICENSE => 'perl', + PREREQ_PM => { + Storable => 0, + }, + BUILD_REQUIRES => { + File::Basename => 0, + File::Slurp => 0, + }, + META_ADD => { + resources => { + repository => { + url => 'http://git.ieval.ro/git/mafia.git', + web => 'http://git.ieval.ro/?p=mafia.git', + type => 'git', + } + } + } +); diff --git a/README b/README new file mode 100644 index 0000000..7af06e0 --- /dev/null +++ b/README @@ -0,0 +1,27 @@ +Mafia version 0.001 +=================== + +Mafia.pm is a Perl extension for easily moderating Mafia games. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + +* File::Slurp (only for testing) + +COPYRIGHT AND LICENCE + +Copyright (C) 2013 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.14.2 or, +at your option, any later version of Perl 5 you may have available. diff --git a/lib/Mafia.pm b/lib/Mafia.pm new file mode 100644 index 0000000..e984481 --- /dev/null +++ b/lib/Mafia.pm @@ -0,0 +1,576 @@ +package Mafia; + +use 5.014000; +use strict; +use warnings; +use parent qw/Exporter/; + +use constant; +use Storable qw/dclone/; + +our $VERSION = '0.001'; + +sub defconst { constant->import($_ => $_) for @_ } + +BEGIN { + # Roles + defconst qw/vanilla goon doctor vigilante roleblocker jailkeeper gunsmith tracker watcher bodyguard rolecop cop sk hider/; + + # Factions + defconst qw/mafia town/; + + # Extra traits + defconst qw/miller godfather weak macho bulletproof/; + + # Messages + defconst qw/MSG_NIGHT MSG_DAY MSG_PLAYERS_ALIVE MSG_DEATH MSG_GUNCHECK MSG_NORESULT MSG_TRACK MSG_WATCH MSG_COP MSG_ROLECOP/; + + # Action types + defconst qw/ACT_KILL ACT_LYNCH ACT_PROTECT ACT_GUARD ACT_ROLEBLOCK ACT_GUNCHECK ACT_TRACK ACT_WATCH ACT_ROLECOP ACT_COP ACT_TRACK_RESULT ACT_WATCH_RESULT ACT_HIDE/; +} + +use constant +{ + townie => town, + ROLE => [vanilla, goon, doctor, vigilante, roleblocker, jailkeeper, gunsmith, tracker, watcher, bodyguard, rolecop, cop, sk, hider], + FACTION => [mafia, town], + FLAG => [miller, godfather, weak, macho, bulletproof], + ACTION_ORDER => [ACT_HIDE, ACT_ROLEBLOCK, ACT_PROTECT, ACT_GUARD, ACT_GUNCHECK, ACT_ROLECOP, ACT_COP, ACT_TRACK, ACT_WATCH, ACT_KILL, ACT_LYNCH, ACT_TRACK_RESULT, ACT_WATCH_RESULT], + INVESTIGATIVE_ACTIONS => [ACT_GUNCHECK, ACT_TRACK, ACT_WATCH, ACT_ROLECOP, ACT_COP], + GUNROLES => [vigilante, gunsmith], +}; + +our @EXPORT = do { + no strict 'refs'; + grep { $_ !~ [qw/import/] and exists &$_ } keys %{__PACKAGE__ . '::'}; +}; + +################################################## Helper subs + +sub import { + strict->import; + goto &Exporter::import; +} + +my (%players, %tplayers, @actions); +my $daycnt = 0; +my $nightcnt = 0; +my $isday = 0; +my $first = 1; + +sub clean{ + %players = (); + %tplayers = (); + @actions = (); + $daycnt = 0; + $nightcnt = 0; + $isday = 0; + $first = 1; +} + +sub uniq { + my %hash = map { $_ => 1 } @_; + keys %hash +} + +sub phase { + return "Day $daycnt" if $isday; + return "Night $nightcnt" unless $isday; +} + +sub rolename { + my %player = %{$players{$_[0]}}; + my ($faction, $role) = ($player{faction}, $player{role}); + if (defined $faction && $faction eq town && $role eq vanilla){ + undef $faction; + $role = 'Vanilla Townie'; + }; + my @tokens = (); + push @tokens, ucfirst $faction if $faction; + for my $flag (@{FLAG()}) { + push @tokens, ucfirst $flag if $player{$flag} + } + push @tokens, ucfirst $role unless $role eq goon && $player{godfather}; + "@tokens" +} + +sub msg { + my ($type, @args) = @_; + given ($type){ + when (MSG_NIGHT) { + my ($night) = @args; + say '' unless $first; + $first = 0; + say "It is Night $night"; + } + + when (MSG_DAY) { + my ($day) = @args; + say '' unless $first; + $first = 0; + say "It is Day $day"; + } + + when (MSG_PLAYERS_ALIVE) { + @args = sort @args; + say "Players alive: ", join ', ', @args + } + + when (MSG_DEATH) { + my %args = @args; + my ($who, $reason) = @args{'target', 'reason'}; + my $phase = phase; + my $rolename = rolename $who; + say "$who ($rolename) — $reason $phase"; + } + + when (MSG_GUNCHECK) { + my %args = @args; + my ($gunsmith, $who, $hasgun) = @args{'source', 'target', 'result'}; + say "$gunsmith: $who has a gun" if $hasgun; + say "$gunsmith: $who does not have a gun" unless $hasgun; + } + + when (MSG_NORESULT) { + my %args = @args; + my ($who) = $args{'source'}; + say "$who: No result" + } + + when (MSG_TRACK) { + my %args = @args; + my ($tracker, $who, $result) = @args{'source', 'target', 'result'}; + my @result = @{$result}; + local $, = ', '; + say "$tracker: $who did not visit anyone" unless scalar @result; + say "$tracker: $who visited: @result" if scalar @result; + } + + when (MSG_WATCH) { + my %args = @args; + my ($watcher, $who, $result) = @args{'source', 'target', 'result'}; + my @result = @{$result}; + local $, = ', '; + say "$watcher: $who was not visited by anyone" unless scalar @result; + say "$watcher: $who was visited by: @result" if scalar @result; + } + + when (MSG_ROLECOP) { + my %args = @args; + my ($rolecop, $who, $role) = @args{'source', 'target', 'result'}; + say "$rolecop: $who\'s role is: $role" + } + + when (MSG_COP) { + my %args = @args; + my ($cop, $who, $ismafia) = @args{'source', 'target', 'result'}; + say "$cop: $who is mafia" if $ismafia; + say "$cop: $who is not mafia" unless $ismafia; + } + } +} + +sub putaction { + my ($delay, $type, %args) = @_; + $actions[$delay]->{$type} //= []; + if (exists $args{target} && exists $args{source} && $players{$args{target}}{faction} eq mafia && $players{$args{source}}{weak}) { + putaction($delay, ACT_KILL, target => $args{source}, reason => 'targeted scum'); + } + push $actions[$delay]->{$type}, \%args +} + +sub doaction { + my ($type, $args) = @_; + my %args = %$args; + my $source = $args{source}; + my $target = $args{target}; + if (defined $source && defined $target) { + # Watcher and tracker variables + $tplayers{$source}{targets} //= []; + push $tplayers{$source}{targets}, $target; + $tplayers{$target}{sources} //= []; + push $tplayers{$target}{sources}, $source; + + # Copy this action to everybody hiding behind $target + if (exists $tplayers{$target}{hiders}) { + for my $target (@{$tplayers{$target}{hiders}}) { + my %args = %args; + $args{target} = $target; + $args{hidepierce} = 1; + doaction($type, \%args); + } + } + + # Check if the action should be blocked + my $strongkill = $type eq ACT_KILL && $args{strong}; + my $roleblocked = $tplayers{$source}{roleblocked}; + my $hidden = $tplayers{$target}{hidden}; + my $hidepierce = $args{hidepierce}; + if ($source && (( $roleblocked && !$strongkill ) || ($hidden && !$hidepierce) )) { + msg MSG_NORESULT, %args if $type ~~ INVESTIGATIVE_ACTIONS; + return + } + } + + + given ($type) { + when(ACT_KILL) { + break if $tplayers{$target}{bulletproof} && defined $source; + if ($tplayers{$target}{guard_count} && defined $source) { + $tplayers{$target}{guard_count}--; + # Copy this action to the first guard + $args{target} = shift $tplayers{$target}{guards}; + @_ = ($type, %args); + goto &doaction; + } + if ($tplayers{$target}{protection} && !$args{strong}) { + $tplayers{$target}{protection}--; + break + } + msg MSG_DEATH, %args; + delete $players{$target} + } + + when(ACT_LYNCH){ + if ($tplayers{$target}{guard_count}) { + $tplayers{$target}{guard_count}--; + $args{target} = shift $tplayers{$target}{guards}; + $target=$args{target}; + } + if ($tplayers{$target}{protection}) { + $tplayers{$target}{protection}--; + break + } + msg MSG_DEATH, %args, reason => 'lynched'; + delete $players{$target} + } + + when(ACT_PROTECT){ + my $count = $args{count} // 1; + $tplayers{$target}{protection} += $count unless $tplayers{$target}{macho} + } + + when(ACT_ROLEBLOCK){ + $tplayers{$target}{roleblocked} = 1 + } + + when(ACT_GUNCHECK){ + my $role = $players{$target}{role}; + my $hasgun = $role ~~ GUNROLES || ($players{$target}{faction} eq mafia && $role ne doctor); + msg MSG_GUNCHECK, %args, result => $hasgun + } + + when(ACT_TRACK_RESULT){ + msg MSG_TRACK, %args, result => [ uniq @{$tplayers{$target}{targets} // []} ]; + } + + when(ACT_WATCH_RESULT){ + msg MSG_WATCH, %args, result => [ uniq @{$tplayers{$target}{sources} // []} ]; + } + + when(ACT_GUARD){ + $tplayers{$target}{guard_count}++; + $tplayers{$target}{guards} //= []; + push $tplayers{$target}{guards}, $source; + } + + when(ACT_ROLECOP){ + my $result = $players{$target}{role}; + $result = vanilla if $result eq goon; + msg MSG_ROLECOP, %args, result => ucfirst $result + } + + when(ACT_COP){ + my $result = $players{$target}{faction} eq mafia; + $result = 1 if $players{$target}{miller}; + $result = 0 if $players{$target}{godfather}; + msg MSG_COP, %args, result => $result + } + + when(ACT_HIDE){ + $tplayers{$source}{hidden} = 1; + $tplayers{$target}{hiders} //= []; + push $tplayers{$target}{hiders}, $source + } + } +} + +sub process_phase_change { + %tplayers = %{dclone \%players}; + my $actions = shift @actions; + for my $type(@{ACTION_ORDER()}) { + doaction $type, $_ for @{$actions->{$type}} + } +} + +################################################## User subs + +sub player { + my ($name, @args) = @_; + my %player; + for my $trait (@args) { + given ($trait) { + $player{role} = $trait when ROLE; + $player{faction} = $trait when FACTION; + $player{$trait} = 1 when FLAG; + } + } + + $players{$name} = \%player; +} + +sub day { + process_phase_change; + $isday = 1; + msg MSG_DAY, ++$daycnt; + msg MSG_PLAYERS_ALIVE, keys %players; +} + +sub night { + process_phase_change; + $isday = 0; + msg MSG_NIGHT, ++$nightcnt; + msg MSG_PLAYERS_ALIVE, keys %players; +} + +sub lynch { + my ($who) = @_; + putaction 0, ACT_LYNCH, target => $who; +} + +sub factionkill { + my ($killer, $who, $reason, @args) = @_; + putaction 0, ACT_KILL, target => $who, source => $killer, reason => $reason, @args; +} + +sub protect { + my ($doctor, $who) = @_; + putaction 0, ACT_PROTECT, target => $who, source => $doctor; +} + +sub vig { + my ($vig, $who, $reason, @args) = @_; + putaction 0, ACT_KILL, target => $who, source => $vig, reason => $reason, @args; +} + +sub roleblock { + my ($roleblocker, $who) = @_; + putaction 0, ACT_ROLEBLOCK, target => $who, source => $roleblocker; +} + +sub jailkeep { + my ($jailkeeper, $who) = @_; + putaction 0, ACT_ROLEBLOCK, target => $who, source => $jailkeeper; + putaction 0, ACT_PROTECT, target => $who, source => $jailkeeper, count => 1000; +} + +sub guncheck { + my ($gunsmith, $who) = @_; + putaction 0, ACT_GUNCHECK, target => $who, source => $gunsmith; +} + +sub track { + my ($tracker, $who) = @_; + putaction 0, ACT_TRACK, target => $who, source => $tracker; + putaction 0, ACT_TRACK_RESULT, target => $who, source => $tracker; +} + +sub watch { + my ($watcher, $who) = @_; + putaction 0, ACT_WATCH, target => $who, source => $watcher; + putaction 0, ACT_WATCH_RESULT, target => $who, source => $watcher; +} + +sub guard { + my ($guard, $who) = @_; + putaction 0, ACT_GUARD, target => $who, source => $guard; +} + +sub rolecopcheck { + my ($rolecop, $who) = @_; + putaction 0, ACT_ROLECOP, target => $who, source => $rolecop; +} + +sub copcheck { + my ($cop, $who) = @_; + putaction 0, ACT_COP, target => $who, source => $cop; +} + +sub skill { + my ($sk, $who, $reason, @args) = @_; + putaction 0, ACT_KILL, target => $who, source => $sk, reason => $reason, @args; +} + +sub hide { + my ($hider, $who) = @_; + putaction 0, ACT_HIDE, target => $who, source => $hider; +} + +1; +__END__ + +=head1 NAME + +Mafia - easily moderate Mafia games + +=head1 SYNOPSIS + + #!/usr/bin/perl -w + use Mafia; + + player 'Banana Bob', cop, town; + player 'Dragon Phoenix', vanilla, townie; + player 'Gammie', mafia, goon; + player 'gslamm', vanilla, townie; + player 'Untrod Tripod', mafia, goon; + player 'Werebear', vanilla, townie; + player 'willows_weep', town, doctor; + + day; + lynch 'Untrod Tripod'; + + night; + factionkill 'Gammie', 'willows_weep', 'shot'; + copcheck 'Banana Bob', 'gslamm'; + + day; + lynch 'Gammie'; + + night; + +=head1 DESCRPTION + +Mafia.pm is a Perl extension for easily moderating Mafia games. You don't even need to know Perl to use it (see L<"WHAT YOU NEED TO KNOW"> for details). + +=head1 WHAT YOU NEED TO KNOW + +A typical script starts with the following two lines + + #!/usr/bin/perl -w + use Mafia; + +The rest of the script is a series of function calls that describe the players and their actions. + +A function call looks like this: + + function_name first_argument, second_argument, ... + +Each argument is either a number, a string (which is a sequence of characters between single or double quotes, such as C<'badguy'>, C<'qwrf'>) or a constant (such as C, C, C). + +Example calls: + + player 'Somebody', mafia, goon; # player is the function, 'Somebody' is a string, mafia and goon are constants. + lynch 'Nobody'; # lynch is the function, 'Nobody' is a string. + day; # day is the function. There are no arguments. + +=head1 FUNCTIONS + +=over + +=item B I, I, ... + +Defines a new player named I and its traits (role, faction, role modifiers). + +Roles: C. + +Factions: C. C is a synonim for C. + +Other attributes: C + +These traits may be specified in any order. + +Example usage: + + player 'alice', town, bulletproof, miller, vigilante; # Alice is a NK-Immune Miller Vig + player 'bob', town, weak, doctor; # Bob is a Town Weak Doctor + player 'eve', mafia, godfather, goon; # Eve is a Mafia Godfather + +=item B + +Defines the start of a new Day. All actions in the previous Night are now resolved. + +=item B + +Defines the start of a new Night. All actions in the previous Day are now resolved. + +=item B I + +Notes that I was lynched. + +=item B I, I, I, [ strong => 1 ] + +Notes that I killed I with flavour I. Append C<< strong => 1 >> if the kill should ignore roleblocks and doctor/jailkeeper protections. Use this for mafia kills. + +Example usage: + + factionkill 'eve', 'alice', 'strangled to death'; + factionkill 'eve', 'bob', 'brutally murdered', strong => 1; # This is a strongman kill + +=item B I, I + +Notes that I protected I. + +=item B I, I, I, [ strong => 1 ] + +Notes that I killed I with flavour I. Append C<< strong => 1 >> if the kill should ignore roleblocks and doctor/jailkeeper protections. Use this for Vigilante/Juggernaut kills. + +Example usage: + + vig 'chuck', 'bob', 'shot'; + vig 'chuck', 'bob', 'shot seven times', strong => 1; # This is a Juggernaut (Strongman Vigilante) kill + +=item B I, I + +Notes that I roleblocked I. + +=item B I, I + +Notes that I roleblocked and protected I. + +=item B I, I + +Notes that I checked if I has a gun. + +=item B I, I + +Notes that I tracked I. + +=item B I, I + +Notes that I watched I. + +=item B I, I + +Notes that I guarded I + +=item B I, I + +Notes that I checked the role of I + +=item B I, I + +Notes that I checked whether I is mafia. + +=item B I, I, I, [ strong => 1 ] + +Notes that I killed player with flavour I. Append C<< strong => 1 >>> if the kill should ignore roleblocks and doctor/jailkeeper protections. Use this for Serial Killer kills. + +=item B I, I + +Notes that I hid behind I. + +=back + +=head1 AUTHOR + +Marius Gavrilescu, Emarius@ieval.roE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2013 by Marius Gavrilescu + +This library is free software; you can redistribute it and/or modify +it under the same terms as Perl itself, either Perl version 5.14.2 or, +at your option, any later version of Perl 5 you may have available. + + +=cut diff --git a/t/00-use.t b/t/00-use.t new file mode 100644 index 0000000..8155abd --- /dev/null +++ b/t/00-use.t @@ -0,0 +1,6 @@ +#!/usr/bin/perl -wT +use v5.14; +use warnings; + +use Test::More tests => 1; +BEGIN { use_ok('Mafia') }; diff --git a/t/examples.t b/t/examples.t new file mode 100644 index 0000000..b97b8e7 --- /dev/null +++ b/t/examples.t @@ -0,0 +1,19 @@ +#!/usr/bin/perl -w +use File::Basename qw/fileparse/; +use File::Slurp qw/read_file/; +use Mafia; + +my @examples; +BEGIN { @examples = map { s/\.pl//r } glob 't/examples/*.pl' }; +use Test::More tests => scalar @examples; + +for my $example (@examples) { + my $out; + close STDOUT; + open STDOUT, '>', \$out; + clean; + + my $ok = read_file "$example.out"; + eval scalar read_file "$example.pl"; + is $out, $ok, scalar fileparse $example +} diff --git a/t/examples/Newbie-0001.out b/t/examples/Newbie-0001.out new file mode 100644 index 0000000..4a79ecf --- /dev/null +++ b/t/examples/Newbie-0001.out @@ -0,0 +1,15 @@ +It is Day 1 +Players alive: MeMe, PrettyPrincess, Stewie, ZONEACE, fgdtdtdtdr, rite, shadyforce +fgdtdtdtdr (Town Doctor) — lynched Day 1 + +It is Night 1 +Players alive: MeMe, PrettyPrincess, Stewie, ZONEACE, rite, shadyforce +ZONEACE: rite is not mafia +MeMe (Vanilla Townie) — shot Night 1 + +It is Day 2 +Players alive: PrettyPrincess, Stewie, ZONEACE, rite, shadyforce +ZONEACE (Town Cop) — lynched Day 2 + +It is Night 2 +Players alive: PrettyPrincess, Stewie, rite, shadyforce diff --git a/t/examples/Newbie-0001.pl b/t/examples/Newbie-0001.pl new file mode 100644 index 0000000..1886515 --- /dev/null +++ b/t/examples/Newbie-0001.pl @@ -0,0 +1,21 @@ +use Mafia; + +player fgdtdtdtdr => doctor, town; +player MeMe => vanilla, townie; +player PrettyPrincess => mafia, goon; +player rite => vanilla, townie; +player shadyforce => vanilla, townie; +player Stewie => mafia, goon; +player ZONEACE => town, cop; + +day; +lynch 'fgdtdtdtdr'; + +night; +factionkill Stewie => MeMe => 'shot'; +copcheck ZONEACE => 'rite'; + +day; +lynch 'ZONEACE'; + +night; diff --git a/t/examples/Newbie-0002.out b/t/examples/Newbie-0002.out new file mode 100644 index 0000000..927abd6 --- /dev/null +++ b/t/examples/Newbie-0002.out @@ -0,0 +1,15 @@ +It is Day 1 +Players alive: Banana Bob, Dragon Phoenix, Gammie, Untrod Tripod, Werebear, gslamm, willows_weep +Untrod Tripod (Mafia Goon) — lynched Day 1 + +It is Night 1 +Players alive: Banana Bob, Dragon Phoenix, Gammie, Werebear, gslamm, willows_weep +Banana Bob: gslamm is not mafia +willows_weep (Town Doctor) — shot Night 1 + +It is Day 2 +Players alive: Banana Bob, Dragon Phoenix, Gammie, Werebear, gslamm +Gammie (Mafia Goon) — lynched Day 2 + +It is Night 2 +Players alive: Banana Bob, Dragon Phoenix, Werebear, gslamm diff --git a/t/examples/Newbie-0002.pl b/t/examples/Newbie-0002.pl new file mode 100644 index 0000000..b8ea2e9 --- /dev/null +++ b/t/examples/Newbie-0002.pl @@ -0,0 +1,21 @@ +use Mafia; + +player 'Banana Bob', cop, town; +player 'Dragon Phoenix', vanilla, townie; +player 'Gammie', mafia, goon; +player 'gslamm', vanilla, townie; +player 'Untrod Tripod', mafia, goon; +player 'Werebear', vanilla, townie; +player 'willows_weep', town, doctor; + +day; +lynch 'Untrod Tripod'; + +night; +factionkill 'Gammie', 'willows_weep', 'shot'; +copcheck 'Banana Bob', 'gslamm'; + +day; +lynch 'Gammie'; + +night; diff --git a/t/examples/Newbie-0003.out b/t/examples/Newbie-0003.out new file mode 100644 index 0000000..89cae87 --- /dev/null +++ b/t/examples/Newbie-0003.out @@ -0,0 +1,15 @@ +It is Day 1 +Players alive: Bloojay, Kerplunk, QX, Stimpy, Talitha, max22, nard054 +Stimpy (Vanilla Townie) — lynched Day 1 + +It is Night 1 +Players alive: Bloojay, Kerplunk, QX, Talitha, max22, nard054 +max22: Kerplunk is not mafia +Bloojay (Town Doctor) — shot Night 1 + +It is Day 2 +Players alive: Kerplunk, QX, Talitha, max22, nard054 +nard054 (Vanilla Townie) — lynched Day 2 + +It is Night 2 +Players alive: Kerplunk, QX, Talitha, max22 diff --git a/t/examples/Newbie-0003.pl b/t/examples/Newbie-0003.pl new file mode 100644 index 0000000..ad507bb --- /dev/null +++ b/t/examples/Newbie-0003.pl @@ -0,0 +1,21 @@ +use Mafia; + +player Bloojay => town, doctor; +player Kerplunk => vanilla, townie; +player max22 => town, cop; +player nard054 => vanilla, townie; +player QX => mafia, goon; +player Stimpy => vanilla, townie; +player Talitha => mafia, goon; + +day; +lynch 'Stimpy'; + +night; +factionkill Talitha => 'Bloojay', 'shot'; +copcheck max22 => 'Kerplunk'; + +day; +lynch 'nard054'; + +night; diff --git a/t/examples/Newbie-0004.out b/t/examples/Newbie-0004.out new file mode 100644 index 0000000..8a5ff81 --- /dev/null +++ b/t/examples/Newbie-0004.out @@ -0,0 +1,24 @@ +It is Day 1 +Players alive: Just_nigel, Phoebus, Smoke_Bandit, Someone, Sugar, Yggdrasil, tehgood +tehgood (Vanilla Townie) — lynched Day 1 + +It is Night 1 +Players alive: Just_nigel, Phoebus, Smoke_Bandit, Someone, Sugar, Yggdrasil +Yggdrasil: Sugar is not mafia +Sugar (Town Doctor) — shot Night 1 + +It is Day 2 +Players alive: Just_nigel, Phoebus, Smoke_Bandit, Someone, Yggdrasil +Phoebus (Mafia Goon) — lynched Day 2 + +It is Night 2 +Players alive: Just_nigel, Smoke_Bandit, Someone, Yggdrasil +Yggdrasil: Just_nigel is not mafia +Yggdrasil (Town Cop) — shot Night 2 + +It is Day 3 +Players alive: Just_nigel, Smoke_Bandit, Someone +Smoke_Bandit (Vanilla Townie) — lynched Day 3 + +It is Night 3 +Players alive: Just_nigel, Someone diff --git a/t/examples/Newbie-0004.pl b/t/examples/Newbie-0004.pl new file mode 100644 index 0000000..c110918 --- /dev/null +++ b/t/examples/Newbie-0004.pl @@ -0,0 +1,28 @@ +use Mafia; + +player Sugar => town, doctor; +player tehgood => vanilla, townie; +player Yggdrasil => town, cop; +player Smoke_Bandit => vanilla, townie; +player Someone => mafia, goon; +player Just_nigel => vanilla, townie; +player Phoebus => mafia, goon; + +day; +lynch 'tehgood'; + +night; +copcheck Yggdrasil => 'Sugar'; +factionkill Someone => 'Sugar', 'shot'; + +day; +lynch 'Phoebus'; + +night; +copcheck Yggdrasil => 'Just_nigel'; +factionkill Someone => 'Yggdrasil', 'shot'; + +day; +lynch 'Smoke_Bandit'; + +night; diff --git a/t/examples/Newbie-0005.out b/t/examples/Newbie-0005.out new file mode 100644 index 0000000..91071b8 --- /dev/null +++ b/t/examples/Newbie-0005.out @@ -0,0 +1,15 @@ +It is Day 1 +Players alive: EnPaceRequiescat, Fishbulb, Flying Dutchman, Might Raven, Morpheus, Mr_Gnome_It_All, Vraak X +Flying Dutchman (Vanilla Townie) — lynched Day 1 + +It is Night 1 +Players alive: EnPaceRequiescat, Fishbulb, Might Raven, Morpheus, Mr_Gnome_It_All, Vraak X +Vraak X: Fishbulb is not mafia +Fishbulb (Vanilla Townie) — shot Night 1 + +It is Day 2 +Players alive: EnPaceRequiescat, Might Raven, Morpheus, Mr_Gnome_It_All, Vraak X +Mr_Gnome_It_All (Vanilla Townie) — lynched Day 2 + +It is Night 2 +Players alive: EnPaceRequiescat, Might Raven, Morpheus, Vraak X diff --git a/t/examples/Newbie-0005.pl b/t/examples/Newbie-0005.pl new file mode 100644 index 0000000..6e895ef --- /dev/null +++ b/t/examples/Newbie-0005.pl @@ -0,0 +1,22 @@ +use Mafia; + +player EnPaceRequiescat => mafia, goon; +player Fishbulb => vanilla, townie; +player 'Flying Dutchman' => vanilla, townie; +player 'Might Raven' => mafia, goon; +player Morpheus => doctor, town; +player Mr_Gnome_It_All => vanilla, townie; +player 'Vraak X' => town, cop; + +day; +lynch 'Flying Dutchman'; + +night; +factionkill EnPaceRequiescat => 'Fishbulb', 'shot'; +copcheck 'Vraak X' => 'Fishbulb'; +protect Morpheus => 'Vraak X'; + +day; +lynch 'Mr_Gnome_It_All'; + +night; -- 2.39.2