mirror of https://github.com/pragma-/pbot.git
Battleship: balanced board and queue commands
This commit is contained in:
parent
0243b4fd0f
commit
c1db40d216
|
@ -217,15 +217,30 @@ sub battleship_cmd {
|
||||||
when ('score') {
|
when ('score') {
|
||||||
if (@{$self->{state_data}->{players}} == 2) {
|
if (@{$self->{state_data}->{players}} == 2) {
|
||||||
my $buf;
|
my $buf;
|
||||||
$buf = sprintf("%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d; ",
|
|
||||||
|
my $p1sections = $self->count_ship_sections(1);
|
||||||
|
my $p2sections = $self->count_ship_sections(0);
|
||||||
|
|
||||||
|
my $p1win = "";
|
||||||
|
my $p2win = "";
|
||||||
|
|
||||||
|
if ($p1sections > $p2sections) {
|
||||||
|
$p1win = "$color{bold}$color{lightgreen} * $color{reset}";
|
||||||
|
$p2win = " ";
|
||||||
|
} elsif ($p1sections < $p2sections) {
|
||||||
|
$p1win = " ";
|
||||||
|
$p2win = "$color{bold}$color{lightgreen} * $color{reset}";
|
||||||
|
}
|
||||||
|
|
||||||
|
$buf = sprintf("$p1win%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d; ",
|
||||||
$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}, $p1sections);
|
||||||
$self->send_message($self->{channel}, $buf);
|
$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",
|
$buf = sprintf("$p2win%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}, $p2sections);
|
||||||
$self->send_message($self->{channel}, $buf);
|
$self->send_message($self->{channel}, $buf);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -289,18 +304,38 @@ sub battleship_cmd {
|
||||||
return "You are not playing in this game.";
|
return "You are not playing in this game.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($self->{state_data}->{current_player} != $player) {
|
if (not length $arguments) {
|
||||||
return "$nick: It is not your turn to attack!";
|
if (delete $self->{state_data}->{players}->[$player]->{location}) {
|
||||||
}
|
return "$nick: Attack location cleared.";
|
||||||
|
} else {
|
||||||
if ($self->{player}->[$player]->{done}) {
|
return "$nick: Usage: bomb <location>";
|
||||||
return "$nick: You have already attacked this turn.";
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($arguments !~ m/^[a-zA-Z][0-9]+$/) {
|
if ($arguments !~ m/^[a-zA-Z][0-9]+$/) {
|
||||||
return "$nick: Usage: battleship bomb <location>; <location> must be in the form of A15, B3, C9, etc.";
|
return "$nick: Usage: battleship bomb <location>; <location> must be in the form of A15, B3, C9, etc.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my ($x, $y);
|
||||||
|
($x) = uc($arguments) =~ m/^(.)/;
|
||||||
|
($y) = $arguments =~ m/^.(.*)/;
|
||||||
|
|
||||||
|
$x = ord($x) - 65;;
|
||||||
|
|
||||||
|
if ($x < 0 || $x > $self->{N_Y} || $y < 0 || $y > $self->{N_X}) {
|
||||||
|
return "$nick: Target out of range, try again.";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ($self->{state_data}->{current_player} != $player) {
|
||||||
|
$self->{state_data}->{players}->[$player]->{location} = $arguments;
|
||||||
|
return "$nick: You will attack $arguments when it is your turn.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($self->{player}->[$player]->{done}) {
|
||||||
|
return "$nick: You have already attacked this turn.";
|
||||||
|
}
|
||||||
|
|
||||||
if ($self->bomb($player, uc $arguments)) {
|
if ($self->bomb($player, uc $arguments)) {
|
||||||
if ($self->{player}->[$player]->{won}) {
|
if ($self->{player}->[$player]->{won}) {
|
||||||
$self->{previous_state} = $self->{current_state};
|
$self->{previous_state} = $self->{current_state};
|
||||||
|
@ -428,7 +463,7 @@ sub run_one_state {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not @{$self->{state_data}->{players}} == 2) {
|
if (not @{$self->{state_data}->{players}} == 2) {
|
||||||
$self->send_message($self->{channel}, "A player has left the game! The game is now over.");
|
$self->send_message($self->{channel}, "The game is now over.");
|
||||||
$self->{current_state} = 'nogame';
|
$self->{current_state} = 'nogame';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,10 +561,14 @@ sub create_states {
|
||||||
sub init_game {
|
sub init_game {
|
||||||
my ($self, $nick1, $nick2) = @_;
|
my ($self, $nick1, $nick2) = @_;
|
||||||
|
|
||||||
$self->{N_X} = 26;
|
$self->{N_X} = 20;
|
||||||
$self->{N_Y} = 5;
|
$self->{N_Y} = 6;
|
||||||
$self->{SHIPS} = 8;
|
$self->{SHIPS} = 8;
|
||||||
|
|
||||||
|
for (my $x = 0; $x < $self->{SHIPS}; $x++) {
|
||||||
|
$self->{ship_length}->[$x] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
$self->{board} = [];
|
$self->{board} = [];
|
||||||
|
|
||||||
$self->{player} = [
|
$self->{player} = [
|
||||||
|
@ -604,11 +643,12 @@ sub number {
|
||||||
return int(rand($upper - $lower)) + $lower;
|
return int(rand($upper - $lower)) + $lower;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub generate_ships {
|
sub generate_ship {
|
||||||
my ($self, $player) = @_;
|
my ($self, $player, $ship) = @_;
|
||||||
my ($x, $y, $o, $d, $i, $l);
|
my ($x, $y, $o, $d, $i, $l);
|
||||||
my ($yd, $xd) = (0, 0);
|
my ($yd, $xd) = (0, 0);
|
||||||
|
|
||||||
|
my $fail = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
$x = $self->number(0, $self->{N_Y});
|
$x = $self->number(0, $self->{N_Y});
|
||||||
$y = $self->number(0, $self->{N_X});
|
$y = $self->number(0, $self->{N_X});
|
||||||
|
@ -616,9 +656,13 @@ sub generate_ships {
|
||||||
$o = $self->number(1, 10) < 6;
|
$o = $self->number(1, 10) < 6;
|
||||||
$d = $self->number(1, 10) < 6;
|
$d = $self->number(1, 10) < 6;
|
||||||
|
|
||||||
$l = $self->number(3, 5);
|
if (not $self->{ship_length}->[$ship]) {
|
||||||
|
$l = $self->number(3, 6);
|
||||||
|
} else {
|
||||||
|
$l = $self->{ship_length}->[$ship];
|
||||||
|
}
|
||||||
|
|
||||||
$self->{pbot}->{logger}->log("generate ships player $player: $x,$y $o,$d $l\n");
|
$self->{pbot}->{logger}->log("generate ships player $player: ship $ship x,y: $x,$y o,d: $o,$d length: $l\n");
|
||||||
|
|
||||||
if ($self->check_ship($x, $y, $o, $d, $l)) {
|
if ($self->check_ship($x, $y, $o, $d, $l)) {
|
||||||
if (!$o) {
|
if (!$o) {
|
||||||
|
@ -643,7 +687,15 @@ sub generate_ships {
|
||||||
$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;
|
$self->{ship_length}->[$ship] = $l;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (++$fail >= 50) {
|
||||||
|
$self->{pbot}->{logger}->log("Failed to generate ship\n");
|
||||||
|
$self->send_message($self->{channel}, "Failed to place a ship. I cannot continue. Game over.");
|
||||||
|
$self->{current_state} = 'nogame';
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -659,9 +711,11 @@ sub generate_battlefield {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($x = 0; $x < $self->{SHIPS}; $x++) {
|
for ($x = 0; $x < $self->{SHIPS}; $x++) {
|
||||||
$self->generate_ships(0);
|
if (!$self->generate_ship(0, $x) || !$self->generate_ship(1, $x)) {
|
||||||
$self->generate_ships(1);
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub check_sunk {
|
sub check_sunk {
|
||||||
|
@ -996,6 +1050,19 @@ sub playermove {
|
||||||
return $state;
|
return $state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $player = $state->{current_player};
|
||||||
|
my $location = delete $state->{players}->[$player]->{location};
|
||||||
|
|
||||||
|
if (defined $location) {
|
||||||
|
if ($self->bomb($player, uc $location)) {
|
||||||
|
$self->{player}->[$player]->{done} = 1;
|
||||||
|
$self->{player}->[!$player]->{done} = 0;
|
||||||
|
$self->{state_data}->{current_player} = !$player;
|
||||||
|
$state->{result} = 'next';
|
||||||
|
return $state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($state->{ticks} % $tock == 0) {
|
if ($state->{ticks} % $tock == 0) {
|
||||||
$state->{tocked} = 1;
|
$state->{tocked} = 1;
|
||||||
if (++$state->{counter} > $state->{max_count}) {
|
if (++$state->{counter} > $state->{max_count}) {
|
||||||
|
@ -1024,7 +1091,7 @@ sub playermove {
|
||||||
sub checkplayer {
|
sub checkplayer {
|
||||||
my ($self, $state) = @_;
|
my ($self, $state) = @_;
|
||||||
|
|
||||||
if ($self->{player}->[$state->{current_player}]->{won}) {
|
if ($self->{player}->[0]->{won} or $self->{player}->[1]->{won}) {
|
||||||
$state->{result} = 'sunk';
|
$state->{result} = 'sunk';
|
||||||
} else {
|
} else {
|
||||||
$state->{result} = 'next';
|
$state->{result} = 'next';
|
||||||
|
@ -1036,16 +1103,30 @@ sub gameover {
|
||||||
my ($self, $state) = @_;
|
my ($self, $state) = @_;
|
||||||
if ($state->{ticks} % 2 == 0) {
|
if ($state->{ticks} % 2 == 0) {
|
||||||
$self->show_battlefield(3);
|
$self->show_battlefield(3);
|
||||||
my $buf;
|
|
||||||
$buf = sprintf("%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d",
|
my $p1sections = $self->count_ship_sections(1);
|
||||||
|
my $p2sections = $self->count_ship_sections(0);
|
||||||
|
|
||||||
|
my $p1win = "";
|
||||||
|
my $p2win = "";
|
||||||
|
|
||||||
|
if ($p1sections > $p2sections) {
|
||||||
|
$p1win = "$color{bold}$color{lightgreen} * $color{reset}";
|
||||||
|
$p2win = " ";
|
||||||
|
} elsif ($p1sections < $p2sections) {
|
||||||
|
$p1win = " ";
|
||||||
|
$p2win = "$color{bold}$color{lightgreen} * $color{reset}";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $buf = sprintf("$p1win%s: bombs: %d, hits: %d, misses: %d, enemy ships sunk: %d, enemy sections destroyed: %d, own sections intact: %d",
|
||||||
$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}, $p1sections);
|
||||||
$self->send_message($self->{channel}, $buf);
|
$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",
|
$buf = sprintf("$p2win%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}, $p2sections);
|
||||||
$self->send_message($self->{channel}, $buf);
|
$self->send_message($self->{channel}, $buf);
|
||||||
$self->send_message($self->{channel}, "Game over!");
|
$self->send_message($self->{channel}, "Game over!");
|
||||||
$state->{players} = [];
|
$state->{players} = [];
|
||||||
|
|
Loading…
Reference in New Issue