Code: Select all
#!/usr/bin/perl
use Image::Magick;
$sleeptime = 20;
$imgfile = '/tmp/sgfwallpaper.png';
$lines = 19;
$width = 1024;
$height = 600;
$yoffset = $height / 12;
$gridsize = ($height - $yoffset * 2) / ($lines - 1);
$xoffset = ($width - (($lines - 1) * $gridsize)) / 2;
$bg = '#ba6'; # background color
$lc = '#333'; # lines and hoshi
$bc = '#111'; # black stones
$wc = '#eff'; # white stones
$lw = $height / 500; # stroke width (lines & hoshi)
$gb = Image::Magick->new(size=>$width.'x'.$height);
$gb->ReadImage("canvas:$bg");
@goban = ();
@checked = ();
for ($i = 0; $i < $lines; $i++) {
for ($j = 0; $j < $lines; $j++) {
$goban[$i][$j] = 0;
$checked[$i][$j] = 0;
}
}
# draw_hoshi(x, y)
sub draw_hoshi{
my $x = $_[0] - 1;
my $y = $_[1] - 1;
$x = $xoffset + $x * $gridsize;
$y = $yoffset + $y * $gridsize;
$r = $y + $lw * 2;
$gb->Draw(primitive=>'circle',points=>"$x,$y $x,$r",fill=>$lc);
}
# draw_stone(color, x, y, x-off, y-off)
sub draw_stone{
my $f = $_[0];
my $x = $_[1];
my $y = $_[2];
my $xoff = $_[3];
my $yoff = $_[4];
$x = $xoffset + $x * $gridsize + $xoff;
$y = $yoffset + $y * $gridsize + $yoff;
$r = $y + ($gridsize / 2.1);
$gb->Draw(primitive=>'circle',points=>"$x,$y $x,$r",fill=>$f);
}
# liberties(x, y, color)
sub liberties{
my $x = $_[0];
my $y = $_[1];
my $f = $_[2];
my $lib = 0;
if ($checked[$x][$y]) {
return 0;
}
$checked[$x][$y] = 1;
if ($x > 0 and !$goban[$x - 1][$y]) {
$lib++;
}
if ($x < $lines - 1 and !$goban[$x + 1][$y]) {
$lib++;
}
if ($y > 0 and !$goban[$x][$y - 1]) {
$lib++;
}
if ($y < $lines - 1 and !$goban[$x][$y + 1]) {
$lib++;
}
if ($lib < 4) {
if ($y < $lines - 1 and $goban[$x][$y + 1] =~ /^$f/) {
$lib += liberties($x, $y + 1, $f);
}
if ($y > 0 and $goban[$x][$y - 1] =~ /^$f/) {
$lib += liberties($x, $y - 1, $f);
}
if ($x < $lines - 1 and $goban[$x + 1][$y] =~ /^$f/) {
$lib += liberties($x + 1, $y, $f);
}
if ($x > 0 and $goban[$x - 1][$y] =~ /^$f/) {
$lib += liberties($x - 1, $y, $f);
}
}
$checked[$x][$y] = 0;
return $lib;
}
# remove_stone(x, y, color)
sub remove_stone{
my $x = $_[0];
my $y = $_[1];
my $f = $_[2];
$goban[$x][$y] = 0;
if ($y < $lines - 1 and $goban[$x][$y + 1] =~ /^$f/) {
remove_stone($x, $y + 1, $f);
}
if ($y > 0 and $goban[$x][$y - 1] =~ /^$f/) {
remove_stone($x, $y - 1, $f);
}
if ($x < $lines - 1 and $goban[$x + 1][$y] =~ /^$f/) {
remove_stone($x + 1, $y, $f);
}
if ($x > 0 and $goban[$x - 1][$y] =~ /^$f/) {
remove_stone($x - 1, $y, $f);
}
}
# check_stone(x, y, color)
sub check_stone{
my $x = $_[0];
my $y = $_[1];
my $f = $_[2];
if (!liberties($x, $y, $f)) {
remove_stone($x, $y, $f);
}
}
# check_life(last_move_color, last_move_x, last_move_y)
sub check_life{
my $f = $_[0];
my $fm;
my $x = $_[1];
my $y = $_[2];
if ($f eq $bc) {
$fm = $wc;
} elsif ($f eq $wc) {
$fm = $bc;
}
if ($y < $lines - 1 and $goban[$x][$y + 1] =~ /^$fm/) {
check_stone($x, $y + 1, $fm);
}
if ($y > 0 and $goban[$x][$y - 1] =~ /^$fm/) {
check_stone($x, $y - 1, $fm);
}
if ($x < $lines - 1 and $goban[$x + 1][$y] =~ /^$fm/) {
check_stone($x + 1, $y, $fm);
}
if ($x > 0 and $goban[$x - 1][$y] =~ /^$fm/) {
check_stone($x - 1, $y, $fm);
}
check_stone($x, $y, $f);
}
# redraw()
sub redraw{
my $s;
$gb->Draw(primitive=>'rectangle', points=>"0,0 $width,$height", fill=>$bg);
for ($i = 0; $i < $lines; $i++) {
$ax = $xoffset + $i * $gridsize;
$ay = $yoffset;
$bx = $ax;
$by = $yoffset + ($lines - 1) * $gridsize;
$gb->Draw(primitive=>'line', points=>"$ax,$ay $bx,$by", stroke=>$lc, strokewidth=>$lw);
}
for ($i = 0; $i < $lines; $i++) {
$ax = $xoffset;
$ay = $yoffset + $i * $gridsize;
$bx = $width - $xoffset;
$by = $ay;
$gb->Draw(primitive=>'line', points=>"$ax,$ay $bx,$by", stroke=>$lc, strokewidth=>$lw);
}
draw_hoshi(4, 4);
draw_hoshi(4, 10);
draw_hoshi(4, 16);
draw_hoshi(10, 4);
draw_hoshi(10, 10);
draw_hoshi(10, 16);
draw_hoshi(16, 4);
draw_hoshi(16, 10);
draw_hoshi(16, 16);
for ($i = 0; $i < $lines; $i++) {
for ($j = 0; $j < $lines; $j++) {
if ($goban[$i][$j]) {
@s = split(':', $goban[$i][$j]);
draw_stone($s[0], $i, $j, $s[1], $s[2]);
}
}
}
}
$f = $bc;
while (<>) {
@sgf = split(';');
foreach (@sgf) {
if ($f) {
redraw();
$gb->Write($imgfile);
system("feh --bg-center $imgfile");
sleep($sleeptime);
}
$f = 0;
if (/\[[a-w]{2}\]/) {
if (/^B\[/ or /^AB\[/) {
$f = $bc;
} elsif (/^W\[/ or /^AW\[/) {
$f = $wc;
}
if ($f) {
$xoff = rand($lw * 2) - $lw;
$yoff = rand($lw * 2) - $lw;
s/[^\[]*\[//;
s/\].*//;
@k = split('');
$x = ord($k[0]) - ord('a');
$y = ord($k[1]) - ord('a');
$goban[$x][$y] = "$f:$xoff:$yoff";
check_life($f, $x, $y);
}
}
}
}