问题
this is the current state of my little unimportant async experiment. Can you spot any races or leaks? Common critique is also welcome.
class GameObject
{
has Int $.id;
has Int $.x is rw;
has Int $.y is rw;
has $.game;
has Int $.speed; #the higher the faster
multi method start( &action )
{
start {
loop {
&action();
await Promise.in( 1 / self.speed );
}
#$.game.remove-object( self );
}
}
method speed {
$!speed +
# 33% variation from the base speed in either direction
( -($!speed / 3).Int .. ($!speed / 3).Int ).pick
;
}
submethod DESTROY { say "DESTROY" }
}
role UnnecessaryViolence
{
has $.damage;
has $.hitpoints is rw;
has $.offense;
has $.defense;
method attack ( GameObject $target )
{
say "The {self.WHAT.perl} ({self.id}) attacks the {$target.WHAT.perl} ({$target.id})";
my $attacker = roll( $.offense, 1 .. 6 ).sum;
say "The {self.WHAT.perl} rolls $attacker";
my $defender = roll( $target.defense, 1 .. 6 ).sum;
say "The {$target.WHAT.perl} rolls $defender";
if $attacker > $defender
{
my $damage = ( 1 .. $!damage ).pick;
say "The {self.WHAT.perl} inflicts {$damage} damage";
$target.hitpoints -= $damage ;
}
if $target.hitpoints < 0
{
say "The {$target.WHAT.perl} is dead";
return True;
}
else
{
say "The {$target.WHAT.perl} has { $target.hitpoints } hitpoints left";
return False;
}
}
}
class Player is GameObject does UnnecessaryViolence
{
has $.name;
multi method start
{
say "A hero was born.";
self.start({
# say "The hero is moving";
# keyboard logic here, in the meantime random movement
$.game.channel.send( { object => self, x => (-1 .. 1).pick, y => (-1 .. 1).pick } );
});
}
}
class Monster is GameObject does UnnecessaryViolence
{
has $.species;
multi method start
{
say "A monster hatched.";
self.start({
# say "The monster {self.id} is moving";
# AI logic here, in the meantime random movement
$.game.channel.send( { object => self, x => (-1 .. 1).pick, y => (-1 .. 1).pick } );
});
}
}
class Game
{
my $idc = 0;
has GameObject @.objects is rw;
has Channel $.channel = .new;
method run{
self.setup;
self.mainloop;
}
method setup
{
self.add-object( Monster.new( :id(++$idc), :species("Troll"), :hitpoints(20), :damage(14), :offense(3), :speed(400), :defense(3), :x(4), :y(2), :game(self) ) );
self.add-object( Monster.new( :id(++$idc), :species("Troll"), :hitpoints(25), :damage(16), :offense(3), :speed(300), :defense(3), :x(3), :y(2), :game(self) ) );
self.add-object( Player.new( :id(++$idc), :name("Holli"), :hitpoints(50), :damage(60), :offense(4), :speed(200) :defense(2), :x(0), :y(0), :game(self) ) );
}
method add-object( GameObject $object )
{
@!objects.push( $object );
$object.start;
}
method remove-object( GameObject $object )
{
@!objects = @!objects.grep({ !($_ === $object) });
}
method mainloop
{
react {
whenever $.channel.Supply -> $event
{
self.process-movement( $event );
if self.game-is-over
{
"Game over. The {@!objects[0].WHAT.perl} has won".say;
$.channel.close;
done;
};
};
whenever Supply.interval(0.01) {
self.render;
}
}
}
method process-movement( $event )
{
#say "The {$event<object>.WHAT.perl} moves.";
given $event<object>
{
my $to-x = .x + $event<x>;
my $to-y = .y + $event<y>;
for @!objects -> $object
{
# we don't care abour ourselves
next
if $_ === $object;
# see if anything is where we want to be
if ( $to-x == $object.x && $to-y == $object.y )
{
# can't move, blocked by friendly
return
if $object.WHAT eqv .WHAT;
# we found a monster, see if we can
# kill it and move there
return
unless .attack( $object );
# Something just died
self.remove-object( $object );
last;
}
}
# we won the fight or the place is empty
# so let's move
.x = $to-x == 5 ?? -4 !!
$to-x == -5 ?? 4 !!
$to-x;
.y = $to-y == 5 ?? -4 !!
$to-y == -5 ?? 4 !!
$to-y;
}
}
method render
{
for @!objects -> $object {
"The {$object.WHAT.perl} is at {$object.x},{$object.y}".say;
}
}
method game-is-over {
return (@!objects.map({.WHAT})).unique.elems == 1;
}
}
Game.new.run;
来源:https://stackoverflow.com/questions/57562254/is-there-still-a-race-condition