RCRPG/Raku: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎Code: Correction)
(→‎{{header|Perl 6}}: Updated to work with the latest versions of Niecza and Rakudo. Various tweaks and enhancements)
Line 12: Line 12:
As with the [[RCRPG/Perl|Perl version]].
As with the [[RCRPG/Perl|Perl version]].
==Code==
==Code==
{{works with|niecza|v24}}
Note that this contains workarounds for bugs in [[niecza]] which aren't present in [[rakudo]]. (It hasn't been added to [[RCRPG]] yet, for this reason)
{{works with|niecza}}
{{works with|Rakudo|2013.05}}
<lang perl6># TODO: Z~, List.pick, fix xx
<lang perl6>
my %commands;
my %commands;
my %rooms;
my %rooms;
Line 21: Line 21:
my $stuff = [];
my $stuff = [];
my $equipped = '';
my $equipped = '';

sub zip($fun, \$l1, \$l2) {
my @cl2 = $l2;
map { $fun($_, shift @cl2) }, $l1;
}

sub serial_and(*@list) {
my @delims = map { ", " }, @list;
@delims[*-1] = "" if @delims >= 1;
@delims[*-2] = " and " if @delims >= 2;

join "", zip &infix:<~>, @list, @delims;
}


my $WHITE = "\e[0m";
my $WHITE = "\e[0m";
Line 40: Line 27:


my @random_items = < sledge ladder gold >;
my @random_items = < sledge ladder gold >;

my %dir_str =
my %dir_str =
up => 'in the ceiling',
up => 'in the ceiling',
down => 'in the floor',
down => 'in the floor',
map { ($_ => "to the $_") }, <north south east west>;
map { ($_ => "to the $_") }, <north south east west>;

my %dir_vec =
my %dir_vec =
up => [ 0, 0, 1],
up => [ 0, 0, 1],
Line 51: Line 40:
east => [ 1, 0, 0],
east => [ 1, 0, 0],
west => [-1, 0, 0];
west => [-1, 0, 0];

my %dir_rev = map { ($^a => $^b), $^b => $^a },
my %dir_rev = map { ($^a => $^b), $^b => $^a },
< north south east west up down >;
< north south east west up down >;


my class Room {
my class Room {
has $.stuff = (my $roll = 1.rand) > .25 ?? [@random_items.roll] !!
my $next = 0;
$roll > .85 ?? [@random_items.roll(2)] !! Nil;
has $.stuff = [@random_items[{ $next == $_ && ($next = 0); $next++ }]];
has $.name = "The Unnamed Room";
has $.name = "The Unnamed Room";
has $.links = [];
has $.links = [];
Line 67: Line 57:
say "There is an exit %dir_str{$.links[0]}.";
say "There is an exit %dir_str{$.links[0]}.";
} else {
} else {
say "There are exits {serial_and(@$.links)}.";
say "There are exits: {@$.links.join(', ')\
.subst(/','(<-[,]>+)$/,->$/{" and$0"})}.";
}
}
if $.stuff {
if $.stuff {
say "There is {serial_and(map { "a $_" }, @$.stuff)} here.";
say "There is {serial_and( @$.stuff )} here.";
} else {
} else {
say $BLUE, "There is nothing useful here you can take.", $WHITE;
say $BLUE, "There is nothing useful here you can take.", $WHITE;
Line 79: Line 70:
}
}


%rooms{"0 0 0"} = Room.new(name => 'The Start', stuff => [<sledge>]);
%rooms{"0 0 0"} = Room.new(name => 'The Start', stuff => [<sledge>]);
%rooms{"1 1 5"} = Room.new(name => 'The Prize Room', stuff =>
%rooms{"1 1 5"} = Room.new(name => 'The Prize Room', stuff => [<gold> xx 9]);

[<gold gold gold gold gold gold gold gold gold>]);
sub serial_and(*@list) {
my %stuff;
map { %stuff{$_}++ }, @list;
my $items = (map { "{%stuff{$_} > 1 ?? %stuff{$_} !! 'a'} $_" }, %stuff.keys).join: ', ';
$items.subst( /','(<-[,]>+)$ /, -> $/ {" and$0"} );
}


sub move($dir) {
sub move($dir) {
Line 87: Line 84:
say "There needs to be a ladder in the room before you can climb.";
say "There needs to be a ladder in the room before you can climb.";
} elsif grep $dir, @( %rooms{$room}.links ) {
} elsif grep $dir, @( %rooms{$room}.links ) {
$room = [ zip &infix:<+>, @$room, @(%dir_vec{$dir}) ];
$room = [ @$room Z+ @(%dir_vec{$dir}) ];
} else {
} else {
say "Your way is blocked.";
say "Your way is blocked.";
Line 113: Line 110:
if !(%dir_vec{$dir}:exists) {
if !(%dir_vec{$dir}:exists) {
say "I don't know that direction. Try: {sort keys %dir_vec}";
say "I don't know that direction. Try: {sort keys %dir_vec}";
}
elsif $equipped ne 'sledge' {
say "You accomplish nothing.";
}
}
elsif grep $dir, @( %rooms{$room}.links ) {
elsif grep $dir, @( %rooms{$room}.links ) {
say "You swing your sledge wildly.";
say "You swing {$equipped ?? "the $equipped" !! 'your fists'} wildly at the hole "
~ 'in the wall. It makes a nice breeze.';
}
elsif $equipped ne 'sledge' {
say "You swing {$equipped ?? "the $equipped" !! 'your fists'} around purposfully "
~ 'but accomplish nothing. Perhaps you should equip a better tool?';
}
}
else {
else {
my $r2 = [ zip &infix:<+>, @$room, @(%dir_vec{$dir}) ];
my $r2 = [ @$room Z+ @(%dir_vec{$dir}) ];
my $r2o = %rooms{$r2} //= Room.new;
my $r2o = %rooms{$r2} //= Room.new;
say "You bash until the surface crumbles, leaving a hole you can crawl through.";
say 'You bash until the surface crumbles, leaving a hole you can crawl through.';
push @( %rooms{$room}.links ), $dir;
push @( %rooms{$room}.links ), $dir;
push @( $r2o.links ), %dir_rev{$dir};
push @( $r2o.links ), %dir_rev{$dir};
Line 134: Line 133:
say "You're not carrying anything. Ask again later.";
say "You're not carrying anything. Ask again later.";
} else {
} else {
say "You have {serial_and(map { "a $_" }, @$stuff)}."
say "You have {serial_and( @$stuff )}."
}
}
};
};
Line 200: Line 199:
%commands{$c2} = %commands{$c1};
%commands{$c2} = %commands{$c1};
}
}
};

command [<exit quit>], "(leave Muddy)", 0,
{
print 'The Muddy walls dim. ';
say "You glance down as {serial_and( @$stuff )} clatter{@$stuff > 1 ?? 's' !! ''} to the floor then fades away." if @$stuff;
say 'It is as if you are awakening from a strange (and extremly low resolution) dream...';
exit;
};
};


Line 205: Line 212:
%rooms{$room}.greet;
%rooms{$room}.greet;


for $*IN.lines -> $in {
while my $in = $*IN.get {
my @args = $in.words;
my @args = $in.words;
if @args && %commands{lc @args[0]} -> $fun {
if @args && %commands{lc @args[0]} -> $fun {
$fun(|@args);
$fun(|@args);

Revision as of 22:00, 7 June 2013

RCRPG/Raku is part of RCRPG. You may find other members of RCRPG at Category:RCRPG.

This Perl 6 version of RCRPG implements a text interface.

Language Idioms

TODO: Note idioms and interesting language features employed.

Commands

As with the Perl version.

Use

As with the Perl version.

Code

Works with: niecza version v24
Works with: Rakudo version 2013.05

<lang perl6> my %commands; my %rooms;

my $room = [0,0,0]; my $stuff = []; my $equipped = ;

my $WHITE = "\e[0m"; my $GREEN = "\e[32m"; my $BLUE = "\e[34m";

my @random_items = < sledge ladder gold >;

my %dir_str =

   up      => 'in the ceiling',
   down    => 'in the floor',
   map { ($_ => "to the $_") }, <north south east west>;

my %dir_vec =

   up      => [ 0, 0, 1],
   down    => [ 0, 0,-1],
   north   => [ 0, 1, 0],
   south   => [ 0,-1, 0],
   east    => [ 1, 0, 0],
   west    => [-1, 0, 0];

my %dir_rev = map { ($^a => $^b), $^b => $^a },

   < north south east west up down >;

my class Room {

   has $.stuff = (my $roll = 1.rand) > .25 ?? [@random_items.roll] !! 
                     $roll > .85 ?? [@random_items.roll(2)] !! Nil;
   has $.name  = "The Unnamed Room";
   has $.links = [];
   method greet() {
       say "You are in room ($room), $.name";
       if !$.links {
           say "There are no exits from this room.  Perhaps you need to make one?";
       } elsif $.links == 1 {
           say "There is an exit %dir_str{$.links[0]}.";
       } else {
           say "There are exits: {@$.links.join(', ')\
                .subst(/','(<-[,]>+)$/,->$/{" and$0"})}.";
       }
       if $.stuff {
           say "There is {serial_and( @$.stuff )} here.";
       } else {
           say $BLUE, "There is nothing useful here you can take.", $WHITE;
       }
       say $GREEN, "Try 'help' for help\n", $WHITE;
       print ">";
   }

}

%rooms{"0 0 0"} = Room.new(name => 'The Start', stuff => [<sledge>]); %rooms{"1 1 5"} = Room.new(name => 'The Prize Room', stuff => [<gold> xx 9]);

sub serial_and(*@list) {

   my %stuff;
   map { %stuff{$_}++ }, @list;
   my $items = (map { "{%stuff{$_} > 1 ?? %stuff{$_} !! 'a'} $_" }, %stuff.keys).join: ', ';
   $items.subst( /','(<-[,]>+)$ /, -> $/ {" and$0"} );

}

sub move($dir) {

   if $dir eq 'up' && !grep 'ladder', @( %rooms{$room}.stuff ) {
       say "There needs to be a ladder in the room before you can climb.";
   } elsif grep $dir, @( %rooms{$room}.links ) {
       $room = [ @$room Z+ @(%dir_vec{$dir}) ];
   } else {
       say "Your way is blocked.";
   }

}

sub command(@names, $help, $ct, $sub) {

   sub parser(*@bits) {
       if @bits[0] eq '_help' || (@bits - 1) !~~ $ct {
           say "Usage: {@names.join('|')} $help";
       } else {
           shift @bits;
           $sub.(|@bits);
       }
   }
   for @names { %commands{$_} = &parser }

}

for <north south east west up down> -> $dir {

   command [$dir, substr($dir,0,1)], , 0, { move($dir) };

}

command [<attack a>], "(direction)", 1,

   -> $dir {
       if !(%dir_vec{$dir}:exists) {
           say "I don't know that direction.  Try: {sort keys %dir_vec}";
       }
       elsif grep $dir, @( %rooms{$room}.links ) {
           say "You swing {$equipped ?? "the $equipped" !! 'your fists'} wildly at the hole "
               ~ 'in the wall. It makes a nice breeze.';
       }
       elsif $equipped ne 'sledge' {
           say "You swing {$equipped ?? "the $equipped" !! 'your fists'} around purposfully "
               ~ 'but accomplish nothing. Perhaps you should equip a better tool?';
       }
       else {
           my $r2 = [ @$room Z+ @(%dir_vec{$dir}) ];
           my $r2o = %rooms{$r2} //= Room.new;
           say 'You bash until the surface crumbles, leaving a hole you can crawl through.';
           push @( %rooms{$room}.links ), $dir;
           push @( $r2o.links ), %dir_rev{$dir};
       }
   };

command [<inventory inv i>], "", 0,

   {
       if !$stuff {
           say "You're not carrying anything.  Ask again later.";
       } else {
           say "You have {serial_and( @$stuff )}."
       }
   };

command [<name>], "(New name of room)", 1 .. *,

   -> *@names { %rooms{$room}.name = ~@names };

command [<equip>], "(itemname)", 1,

   -> $item {
       if grep $item, @$stuff {
           $equipped = $item;
           say "You equipped your $item.  Put it to good use.";
       } else {
           say "You don't have one of those.  Try 'i' to see what you have.";
       }
   };

sub move_items(@from, @to, @filters) {

   sub ok($item) { ?grep { $_ eq 'all' || $_ eq $item }, @filters }
   my @move = grep &ok, @from;
   push @to, @move;
   @from = grep { !ok($_) }, @from;
   if $equipped && !grep $equipped, @$stuff {
       say "You dropped the item you were using.";
       $equipped = ;
   }
   @move == 0 ?? False !! @move > 1 ?? "{+@move} items" !! "1 item";

}

command [<take>], '{all|(itemname)}', 1 .. *,

   -> *@filters {
       if move_items(%rooms{$room}.stuff, $stuff, @filters) -> $things {
           say "You took $things.";
       } else {
           say "There aren't any of those here.";
       }
   };

command [<drop>], '{all|(itemname)}', 1 .. *,

   -> *@filters {
       if move_items($stuff, %rooms{$room}.stuff, @filters) -> $things {
           say "You dropped $things.";
       } else {
           say "You don't have any of those.";
       }
   };

command [<help>], "(command name) ... But you apparently discovered that.",

   0..1, -> $command? {
       if defined $command {
           %commands{$command}.("_help");
       } else {
           say "Valid commands are: ", [ sort keys %commands ];
       }
   };

command [<alias>], "(existing command name) (additional name for command)",

   2, -> $c1, $c2 {
       if %commands{$c2}:exists {
           say "Can't redefine an existing command!";
       } else {
           %commands{$c2} = %commands{$c1};
       }
   };

command [<exit quit>], "(leave Muddy)", 0,

   {
      print 'The Muddy walls dim. ';
      say "You glance down as {serial_and( @$stuff )} clatter{@$stuff > 1 ?? 's'  !! } to the floor then fades away." if @$stuff;
      say 'It is as if you are awakening from a strange (and extremly low resolution) dream...';
      exit;
   };

say "Welcome to Muddy. It's kinda like a MUD, but it lacks multiple players..."; %rooms{$room}.greet;

while my $in = $*IN.get { my @args = $in.words;

   if @args && %commands{lc @args[0]} -> $fun {
       $fun(|@args);
   } else {
       say "That didn't make any sense.  Try 'help'";
   }
   %rooms{$room}.greet;

} </lang>