This bit us. This bit us hard and I blame myself for not catching it. Looking at it after a good night's sleep sets off tons of loud, Star Trek-esque "red alert" klaxons. Why it's bad is left as an exercise for the reader.
################################################################################
# contract: Player, index -> Turn
# let the player take its turn and do validation/contract checking/timeouts
sub give_turn_to_player {
my ($self, $player, $index) = @_;
my $turn = Game::Turn->new({
index => $index,
player => $player,
admin => $self,
});
try {
local $SIG{ALRM} = sub {
throw Game::Exception::PlayerTimeout(
'Player timed out after '.PLAYER_TIMEOUT.' seconds' );
};
alarm PLAYER_TIMEOUT;
$player->is_taking_turn(1);
$player->take_turn($turn);
$player->is_taking_turn(0);
}
catch Game::Exception::ContractViolation with {
$self->kick_out_player($player, "You have violated a contract: ".shift);
return;
}
catch Game::Exception::PlayerTimeout with {
$self->kick_out_player($player, "You have timed out after ".PLAYER_TIMEOUT." seconds.");
return;
}
otherwise {
die "asking the player to take a turn failed: ".shift;
}
finally {
alarm 0;
};
unless ($turn->chosen_tile) {
$self->kick_out_player($player, "You have attempted to place an undefined tile.");
return;
}
return $turn;
}