3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-10-31 09:09:32 +01:00

Battleship improvements

This commit is contained in:
Pragmatic Software 2018-07-01 17:01:18 -07:00
parent b64758869e
commit 3298f5a27b

View File

@ -11,14 +11,8 @@ use feature 'switch';
no if $] >= 5.018, warnings => "experimental::smartmatch"; no if $] >= 5.018, warnings => "experimental::smartmatch";
use Carp (); use Carp ();
use DBI;
use JSON;
use Time::Duration qw/concise duration/; use Time::Duration qw/concise duration/;
use Data::Dumper;
$Data::Dumper::Useqq = 1;
sub new { sub new {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH'; Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref $_[1] eq 'HASH';
my ($class, %conf) = @_; my ($class, %conf) = @_;
@ -39,12 +33,8 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) });
$self->{leaderboard_filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/battleship/battleshiplb.sqlite3';
$self->create_database;
$self->create_states;
$self->{channel} = '##battleship'; $self->{channel} = '##battleship';
$self->create_states;
} }
sub unload { sub unload {
@ -72,47 +62,6 @@ sub on_departure {
return 0; return 0;
} }
sub create_database {
my $self = shift;
eval {
$self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{leaderboard_filename}", "", "", { RaiseError => 1, PrintError => 0, AutoInactiveDestroy => 1 }) or die $DBI::errstr;
$self->{dbh}->do(<<SQL);
CREATE TABLE IF NOT EXISTS Leaderboard (
userid NUMERIC,
created_on NUMERIC,
wins NUMERIC,
highscore NUMERIC,
avgscore NUMERIC
)
SQL
$self->{dbh}->disconnect;
};
$self->{pbot}->{logger}->log("Battleship create database failed: $@") if $@;
}
sub dbi_begin {
my ($self) = @_;
eval {
$self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{leaderboard_filename}", "", "", { RaiseError => 1, PrintError => 0, AutoInactiveDestroy => 1 }) or die $DBI::errstr;
};
if ($@) {
$self->{pbot}->{logger}->log("Error opening Battleship database: $@");
return 0;
} else {
return 1;
}
}
sub dbi_end {
my ($self) = @_;
$self->{dbh}->disconnect;
}
my %color = ( my %color = (
white => "\x0300", white => "\x0300",
black => "\x0301", black => "\x0301",
@ -217,7 +166,7 @@ sub battleship_cmd {
} }
} }
when ('quit') { when ($_ eq 'decline' or $_ eq 'quit' or $_ eq 'forfeit' or $_ eq 'concede') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host); my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $removed = 0; my $removed = 0;
@ -254,11 +203,13 @@ sub battleship_cmd {
$self->{player}->[0]->{nick}, $self->{player}->[0]->{bombs}, $self->{player}->[0]->{nick}, $self->{player}->[0]->{bombs},
$self->{player}->[0]->{hit}, $self->{player}->[0]->{miss}, $self->{player}->[0]->{hit}, $self->{player}->[0]->{miss},
$self->{player}->[0]->{sunk}, $self->{player}->[0]->{destroyed}, $self->count_ship_sections(1)); $self->{player}->[0]->{sunk}, $self->{player}->[0]->{destroyed}, $self->count_ship_sections(1));
$buf .= sprintf("%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d", $self->send_message($self->{channel}, $buf);
$buf = sprintf("%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d",
$self->{player}->[1]->{nick}, $self->{player}->[1]->{bombs}, $self->{player}->[1]->{nick}, $self->{player}->[1]->{bombs},
$self->{player}->[1]->{hit}, $self->{player}->[1]->{miss}, $self->{player}->[1]->{hit}, $self->{player}->[1]->{miss},
$self->{player}->[1]->{sunk}, $self->{player}->[1]->{destroyed}, $self->count_ship_sections(0)); $self->{player}->[1]->{sunk}, $self->{player}->[1]->{destroyed}, $self->count_ship_sections(0));
return $buf; $self->send_message($self->{channel}, $buf);
return;
} else { } else {
return "There is no game going on right now."; return "There is no game going on right now.";
} }
@ -333,12 +284,17 @@ sub battleship_cmd {
} }
} }
when ('board') { when ($_ eq 'specboard' or $_ eq 'board') {
if ($self->{current_state} eq 'nogame' or $self->{current_state} eq 'accept' if ($self->{current_state} eq 'nogame' or $self->{current_state} eq 'accept'
or $self->{current_state} eq 'genboard' or $self->{current_state} eq 'gameover') { or $self->{current_state} eq 'genboard' or $self->{current_state} eq 'gameover') {
return "$nick: There is no board to show right now."; return "$nick: There is no board to show right now.";
} }
if ($_ eq 'specboard') {
$self->show_battlefield(2);
return;
}
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host); my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
for (my $i = 0; $i < 2; $i++) { for (my $i = 0; $i < 2; $i++) {
if ($self->{state_data}->{players}->[$i]->{id} == $id) { if ($self->{state_data}->{players}->[$i]->{id} == $id) {
@ -575,7 +531,7 @@ sub count_ship_sections {
$sections++; $sections++;
} }
} else { } else {
if ($self->{board}->[$x][$y] eq '|' || $self->{board}->[$x][$y] eq '-') { if ($self->{board}->[$x][$y] eq '|' || $self->{board}->[$x][$y] eq '') {
$sections++; $sections++;
} }
} }
@ -659,7 +615,7 @@ sub generate_ships {
} }
for (my $i = 0; $i < $l; $i++) { for (my $i = 0; $i < $l; $i++) {
$self->{board}->[$x += $o ? $xd : 0][$y += $o ? 0 : $yd] = $player ? ($o ? 'I' : '=') : ($o ? '|' : '-'); $self->{board}->[$x += $o ? $xd : 0][$y += $o ? 0 : $yd] = $player ? ($o ? 'I' : '=') : ($o ? '|' : '');
} }
return; return;
@ -714,9 +670,9 @@ sub check_sunk {
return 1; return 1;
} }
when ($_ eq '-' or $_ eq '=') { when ($_ eq '' or $_ eq '=') {
for ($i = $y + 1; $i < $self->{N_X}; $i++) { for ($i = $y + 1; $i < $self->{N_X}; $i++) {
if (($self->{board}->[$x][$i] eq '-' && $player) || ($self->{board}->[$x][$i] eq '=' && !$player)) { if (($self->{board}->[$x][$i] eq '' && $player) || ($self->{board}->[$x][$i] eq '=' && !$player)) {
return 0; return 0;
} }
@ -726,7 +682,7 @@ sub check_sunk {
} }
for ($i = $y - 1; $i >= 0; $i--) { for ($i = $y - 1; $i >= 0; $i--) {
if (($self->{board}->[$x][$i] eq '-' && $player) || ($self->{board}->[$x][$i] eq '=' && !$player)) { if (($self->{board}->[$x][$i] eq '' && $player) || ($self->{board}->[$x][$i] eq '=' && !$player)) {
return 0; return 0;
} }
@ -765,7 +721,7 @@ sub bomb {
$hit = 1; $hit = 1;
} }
} else { } else {
if ($self->{board}->[$x][$y] eq '|' || $self->{board}->[$x][$y] eq '-') { if ($self->{board}->[$x][$y] eq '|' || $self->{board}->[$x][$y] eq '') {
$hit = 1; $hit = 1;
} }
} }
@ -804,7 +760,7 @@ sub bomb {
if ($sunk) { if ($sunk) {
$self->{player}->[$player]->{sunk}++; $self->{player}->[$player]->{sunk}++;
my $remaining = $self->count_ship_sections($player); my $remaining = $self->count_ship_sections($player);
$self->send_message($self->{channel}, "$nick1 has sunk ${nick2}'s ship! $remaining ship section" . ($remaining != 1 ? 's' : '') . " remaining!"); $self->send_message($self->{channel}, "$color{red}$nick1 has sunk ${nick2}'s ship! $remaining ship section" . ($remaining != 1 ? 's' : '') . " remaining!$color{reset}");
if ($remaining == 0) { if ($remaining == 0) {
$self->send_message($self->{channel}, "$nick1 has WON the game of Battleship!"); $self->send_message($self->{channel}, "$nick1 has WON the game of Battleship!");
@ -824,14 +780,28 @@ sub show_battlefield {
$self->{pbot}->{logger}->log("showing battlefield for player $player\n"); $self->{pbot}->{logger}->log("showing battlefield for player $player\n");
$buf = sprintf("$color{cyan} 123456789$color{yellow}0$color{cyan}123456789$color{yellow}0$color{cyan}123456$color{reset}\n"); $buf = "$color{cyan} ";
for($x = 1; $x < $self->{N_X} + 1; $x++) {
if ($x % 10 == 0) {
$buf .= $color{yellow};
$buf .= $x % 10;
$buf .= ' ';
$buf .= $color{cyan};
} else {
$buf .= $x % 10;
$buf .= ' ';
}
}
$buf .= "\n";
for ($y = 0; $y < $self->{N_Y}; $y++) { for ($y = 0; $y < $self->{N_Y}; $y++) {
$buf .= sprintf("$color{cyan}%c ", 97 + $y); $buf .= sprintf("$color{cyan}%c ", 97 + $y);
for ($x = 0; $x < $self->{N_X}; $x++) { for ($x = 0; $x < $self->{N_X}; $x++) {
if ($player == 0) { if ($player == 0) {
if ($self->{board}->[$y][$x] eq 'I' || $self->{board}->[$y][$x] eq '=') { if ($self->{board}->[$y][$x] eq 'I' || $self->{board}->[$y][$x] eq '=') {
$buf .= "$color{blue}~"; $buf .= "$color{blue}~ ";
next; next;
} else { } else {
if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') { if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') {
@ -839,15 +809,16 @@ sub show_battlefield {
} elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') { } elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') {
$buf .= "$color{cyan}"; $buf .= "$color{cyan}";
} elsif ($self->{board}->[$y][$x] eq '~') { } elsif ($self->{board}->[$y][$x] eq '~') {
$buf .= "$color{blue}"; $buf .= "$color{blue}~ ";
next;
} else { } else {
$buf .= "$color{white}"; $buf .= "$color{white}";
} }
$buf .= $self->{board}->[$y][$x]; $buf .= "$self->{board}->[$y][$x] ";
} }
} elsif ($player == 1) { } elsif ($player == 1) {
if ($self->{board}->[$y][$x] eq '|' || $self->{board}->[$y][$x] eq '-') { if ($self->{board}->[$y][$x] eq '|' || $self->{board}->[$y][$x] eq '') {
$buf .= "$color{blue}~"; $buf .= "$color{blue}~ ";
next; next;
} else { } else {
if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') { if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') {
@ -855,16 +826,17 @@ sub show_battlefield {
} elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') { } elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') {
$buf .= "$color{cyan}"; $buf .= "$color{cyan}";
} elsif ($self->{board}->[$y][$x] eq '~') { } elsif ($self->{board}->[$y][$x] eq '~') {
$buf .= "$color{blue}"; $buf .= "$color{blue}~ ";
next;
} else { } else {
$buf .= "$color{white}"; $buf .= "$color{white}";
} }
$buf .= $self->{board}->[$y][$x]; $buf .= "$self->{board}->[$y][$x] ";
} }
} elsif ($player == 2) { } elsif ($player == 2) {
if ($self->{board}->[$y][$x] eq '|' || $self->{board}->[$y][$x] eq '-' if ($self->{board}->[$y][$x] eq '|' || $self->{board}->[$y][$x] eq ''
|| $self->{board}->[$y][$x] eq 'I' || $self->{board}->[$y][$x] eq '=') { || $self->{board}->[$y][$x] eq 'I' || $self->{board}->[$y][$x] eq '=') {
$buf .= "$color{blue}~"; $buf .= "$color{blue}~ ";
next; next;
} else { } else {
if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') { if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') {
@ -872,11 +844,12 @@ sub show_battlefield {
} elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') { } elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') {
$buf .= "$color{cyan}"; $buf .= "$color{cyan}";
} elsif ($self->{board}->[$y][$x] eq '~') { } elsif ($self->{board}->[$y][$x] eq '~') {
$buf .= "$color{blue}"; $buf .= "$color{blue}~ ";
next;
} else { } else {
$buf .= "$color{white}"; $buf .= "$color{white}";
} }
$buf .= $self->{board}->[$y][$x]; $buf .= "$self->{board}->[$y][$x] ";
} }
} else { } else {
if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') { if ($self->{board}->[$y][$x] eq '1' || $self->{board}->[$y][$x] eq '2') {
@ -884,11 +857,12 @@ sub show_battlefield {
} elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') { } elsif ($self->{board}->[$y][$x] eq 'o' || $self->{board}->[$y][$x] eq '*') {
$buf .= "$color{cyan}"; $buf .= "$color{cyan}";
} elsif ($self->{board}->[$y][$x] eq '~') { } elsif ($self->{board}->[$y][$x] eq '~') {
$buf .= "$color{blue}"; $buf .= "$color{blue}~ ";
next;
} else { } else {
$buf .= "$color{white}"; $buf .= "$color{white}";
} }
$buf .= $self->{board}->[$y][$x]; $buf .= "$self->{board}->[$y][$x] ";
} }
} }
$buf .= "$color{reset}\n"; $buf .= "$color{reset}\n";