mirror of https://github.com/pragma-/pbot.git
Plugins/Battleship: when sending initial boards, pause game until `pbot.output_queue_flushed` received; added `pause` and `unpause` commands
This commit is contained in:
parent
abaf0a29f0
commit
e21591fc06
|
@ -114,6 +114,11 @@ sub initialize {
|
||||||
|
|
||||||
# create game state machine
|
# create game state machine
|
||||||
$self->create_states;
|
$self->create_states;
|
||||||
|
|
||||||
|
# receive notification when all messages in IRC output queue have been sent
|
||||||
|
$self->{pbot}->{event_dispatcher}->register_handler(
|
||||||
|
'pbot.output_queue_flushed', sub { $self->on_output_queue_flushed(@_) }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unload {
|
sub unload {
|
||||||
|
@ -126,11 +131,30 @@ sub unload {
|
||||||
$self->end_game_loop;
|
$self->end_game_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# the game is paused at the beginning when sending the player boards to all
|
||||||
|
# the players and then resumed when the output queue has depleted. this prevents
|
||||||
|
# game events from queuing up while the board messages are being slowly
|
||||||
|
# trickled out to the ircd to avoid filling up its message queue (and getting
|
||||||
|
# disconnected with 'excess flood'). this event handler resumes the game once
|
||||||
|
# the boards have finished transmitting, unless the game was manually paused
|
||||||
|
# by a player.
|
||||||
|
sub on_output_queue_flushed {
|
||||||
|
my ($self) = @_; # we don't care about the other event arguments
|
||||||
|
|
||||||
|
print "BATTLESHIDFPF ADF!!\n";
|
||||||
|
|
||||||
|
# unless paused by a player, resume the game
|
||||||
|
if (not $self->{state_data}->{paused_by_player}) {
|
||||||
|
$self->{state_data}->{paused} = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
# `battleship` bot command
|
# `battleship` bot command
|
||||||
sub cmd_battleship {
|
sub cmd_battleship {
|
||||||
my ($self, $context) = @_;
|
my ($self, $context) = @_;
|
||||||
|
|
||||||
my $usage = "Usage: battleship challenge|accept|decline|ready|unready|bomb|board|score|players|join|quit|kick|abort; see also: battleship help <command>";
|
my $usage = "Usage: battleship challenge|accept|decline|ready|unready|bomb|board|score|players|pause|quit|kick|abort; see also: battleship help <command>";
|
||||||
|
|
||||||
# strip leading and trailing whitespace
|
# strip leading and trailing whitespace
|
||||||
$context->{arguments} =~ s/^\s+|\s+$//g;
|
$context->{arguments} =~ s/^\s+|\s+$//g;
|
||||||
|
@ -284,6 +308,21 @@ sub cmd_battleship {
|
||||||
return "/msg $channel $nick: The game has been aborted.";
|
return "/msg $channel $nick: The game has been aborted.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
when (['pause', 'unpause']) {
|
||||||
|
if ($command eq 'pause') {
|
||||||
|
$self->{state_data}->{paused} = 1;
|
||||||
|
|
||||||
|
# this pause was set by a player.
|
||||||
|
# this is used by on_output_queue_flushed() to know if it's okay to unpause automatically
|
||||||
|
$self->{state_data}->{paused_by_player} = 1;
|
||||||
|
} else {
|
||||||
|
$self->{state_data}->{paused} = 0;
|
||||||
|
$self->{state_data}->{paused_by_player} = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "/msg $channel $nick has " . ($self->{state_data}->{paused} ? 'paused' : 'unpaused') . " the game!";
|
||||||
|
}
|
||||||
|
|
||||||
when ('score') {
|
when ('score') {
|
||||||
if ($self->{current_state} ne 'move' and $self->{current_state} ne 'attack') {
|
if ($self->{current_state} ne 'move' and $self->{current_state} ne 'attack') {
|
||||||
return "There is no Battleship score to show right now.";
|
return "There is no Battleship score to show right now.";
|
||||||
|
@ -613,10 +652,6 @@ sub place_ship {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($self->check_ship_placement($x, $y, $o, $l)) {
|
if ($self->check_ship_placement($x, $y, $o, $l)) {
|
||||||
if ($self->{debug}) {
|
|
||||||
$self->{pbot}->{logger}->log("SUCCESS!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$o) {
|
if (!$o) {
|
||||||
$self->{vert}++;
|
$self->{vert}++;
|
||||||
|
|
||||||
|
@ -887,7 +922,7 @@ sub perform_attack {
|
||||||
$player->{sunk}++;
|
$player->{sunk}++;
|
||||||
$victim->{ships}--;
|
$victim->{ships}--;
|
||||||
|
|
||||||
my $length = $self->{board}->[$x][$y]->{length};
|
my $length = $self->{board}->[$x][$y]->{length};
|
||||||
|
|
||||||
my %ship_names = (
|
my %ship_names = (
|
||||||
5 => 'battleship',
|
5 => 'battleship',
|
||||||
|
@ -1144,6 +1179,11 @@ sub show_battlefield {
|
||||||
sub run_one_state {
|
sub run_one_state {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
|
# don't run a game loop if we're paused
|
||||||
|
if ($self->{state_data}->{paused}) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
# check for naughty or missing players
|
# check for naughty or missing players
|
||||||
my $players = 0;
|
my $players = 0;
|
||||||
|
|
||||||
|
@ -1225,8 +1265,10 @@ sub create_states {
|
||||||
|
|
||||||
# initialize state data
|
# initialize state data
|
||||||
$self->{state_data} = {
|
$self->{state_data} = {
|
||||||
players => [], # array of player data
|
players => [], # array of player data
|
||||||
ticks => 0, # number of ticks elapsed
|
ticks => 0, # number of ticks elapsed
|
||||||
|
paused => 0, # is the game paused?
|
||||||
|
paused_by_player => 0, # game was manually paused by a player
|
||||||
};
|
};
|
||||||
|
|
||||||
$self->{states} = {
|
$self->{states} = {
|
||||||
|
@ -1356,6 +1398,14 @@ sub state_genboard {
|
||||||
sub state_showboard {
|
sub state_showboard {
|
||||||
my ($self, $state) = @_;
|
my ($self, $state) = @_;
|
||||||
|
|
||||||
|
# pause the game to send the boards to all the players.
|
||||||
|
# this is due to output pacing; the messages are trickled out slowly
|
||||||
|
# to avoid overflowing the ircd's receive queue. we do not want the
|
||||||
|
# game state to advance while the messages are being sent out. the
|
||||||
|
# game will resume when the `pbot.output_queue_flushed` notification
|
||||||
|
# is received.
|
||||||
|
$state->{paused} = 1;
|
||||||
|
|
||||||
for (my $player = 0; $player < @{$state->{players}}; $player++) {
|
for (my $player = 0; $player < @{$state->{players}}; $player++) {
|
||||||
$self->send_message($self->{channel}, "Showing battlefield to $state->{players}->[$player]->{name}...");
|
$self->send_message($self->{channel}, "Showing battlefield to $state->{players}->[$player]->{name}...");
|
||||||
$self->show_battlefield($player);
|
$self->show_battlefield($player);
|
||||||
|
|
Loading…
Reference in New Issue