ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Games-Go-SimpleBoard/SimpleBoard.pm
(Generate patch)

Comparing Games-Go-SimpleBoard/SimpleBoard.pm (file contents):
Revision 1.6 by root, Tue Jun 24 23:19:24 2008 UTC vs.
Revision 1.10 by root, Wed Jun 25 20:49:38 2008 UTC

29 MARK_HOSHI # this is a hoshi point (not used much) 29 MARK_HOSHI # this is a hoshi point (not used much)
30 MARK_MOVE # this is a regular move 30 MARK_MOVE # this is a regular move
31 MARK_KO # this is a ko position 31 MARK_KO # this is a ko position
32 MARK_REDRAW # ignored, can be used for your own purposes 32 MARK_REDRAW # ignored, can be used for your own purposes
33 33
34 COLOUR_BLACK # used for $board->{last} 34 COLOUR_WHITE # guarenteed to be 0
35 COLOUR_WHITE # to mark the colour of the last move 35 COLOUR_BLACK # guarenteed to be 1
36 36
37 MOVE_HANDICAP # used as "x-coordinate" for handicap moves 37 MOVE_HANDICAP # used as "x-coordinate" for handicap moves
38 MOVE_PASS # can be used as "x-coordinate" for handicap moves 38 MOVE_PASS # can be used as "x-coordinate" for pass moves
39 39
40=head2 METHODS 40=head2 METHODS
41 41
42=over 4 42=over 4
43 43
52 52
53our $VERSION = '1.0'; 53our $VERSION = '1.0';
54 54
55our @EXPORT = qw( 55our @EXPORT = qw(
56 MARK_TRIANGLE MARK_SQUARE MARK_CIRCLE MARK_SMALL_B MARK_SMALL_W MARK_B 56 MARK_TRIANGLE MARK_SQUARE MARK_CIRCLE MARK_SMALL_B MARK_SMALL_W MARK_B
57 MARK_W MARK_GRAYED MARK_MOVE MARK_LABEL MARK_HOSHI MARK_KO 57 MARK_W MARK_GRAYED MARK_MOVE MARK_LABEL MARK_HOSHI MARK_KO MARK_CROSS
58 MARK_REDRAW 58 MARK_REDRAW
59 COLOUR_BLACK COLOUR_WHITE 59 COLOUR_BLACK COLOUR_WHITE
60 MOVE_HANDICAP MOVE_PASS 60 MOVE_HANDICAP MOVE_PASS
61); 61);
62 62
72sub MARK_GRAYED (){ 0x0080 } # in conjunction with MARK_[BW], grays the stone 72sub MARK_GRAYED (){ 0x0080 } # in conjunction with MARK_[BW], grays the stone
73sub MARK_LABEL (){ 0x0100 } 73sub MARK_LABEL (){ 0x0100 }
74sub MARK_HOSHI (){ 0x0200 } # this is a hoshi point (not used much) 74sub MARK_HOSHI (){ 0x0200 } # this is a hoshi point (not used much)
75sub MARK_MOVE (){ 0x0400 } # this is a regular move 75sub MARK_MOVE (){ 0x0400 } # this is a regular move
76sub MARK_KO (){ 0x0800 } # this is a ko position 76sub MARK_KO (){ 0x0800 } # this is a ko position
77sub MARK_CIRCLE (){ 0x1000 } 77sub MARK_CROSS (){ 0x1000 }
78sub MARK_REDRAW (){ 0x8000 } 78sub MARK_REDRAW (){ 0x8000 }
79 79
80sub COLOUR_BLACK (){ 0 }
81sub COLOUR_WHITE (){ 1 } 80sub COLOUR_WHITE (){ 0 }
81sub COLOUR_BLACK (){ 1 }
82 82
83sub MOVE_PASS (){ undef } 83sub MOVE_PASS (){ undef }
84sub MOVE_HANDICAP (){ -2 } 84sub MOVE_HANDICAP (){ -2 }
85 85
86=item my $board = new $size 86=item my $board = new $size
89 89
90C<< $board->{size} >> stores the board size. 90C<< $board->{size} >> stores the board size.
91 91
92C<< $board->{max} >> stores the maximum board coordinate (size-1). 92C<< $board->{max} >> stores the maximum board coordinate (size-1).
93 93
94C<< $board->{captures}[COLOUR] >> stores the number of captured stones for 94C<< $board->{captures}[COLOUR_xxx] >> stores the number of captured stones for
95the given colour. 95the given colour.
96
97C<< $board->{last} >> stores the colour of the last move that was played.
98 96
99C<< $board->{board} >> stores a two-dimensional array with board contents. 97C<< $board->{board} >> stores a two-dimensional array with board contents.
100 98
101=cut 99=cut
102 100
103sub new { 101sub new {
104 my $class = shift; 102 my $class = shift;
105 my $size = shift; 103 my $size = shift;
104
106 bless { 105 bless {
107 max => $size - 1, 106 max => $size - 1,
108 size => $size, 107 size => $size,
109 board => [map [(0) x $size], 1 .. $size], 108 board => [map [(0) x $size], 1 .. $size],
110 captures => [0, 0], # captures 109 captures => [0, 0], # captures
111 #timer => [], 110 #timer => [],
112 #score => [], 111 #score => [],
113 #last => COLOUR_...,
114 @_
115 }, 112 @_,
116 $class; 113 }, $class
117} 114}
118 115
119# inefficient and primitive, I hear you say? 116# inefficient and primitive, I hear you say?
120# well... you are right :) 117# well... you are right :)
121# use an extremely dumb floodfill algorithm to get rid of captured stones 118# use an extremely dumb floodfill algorithm to get rid of captured stones
161specified in C<$clr>, then setting bits specified in C<$set>. 158specified in C<$clr>, then setting bits specified in C<$set>.
162 159
163If C<$set> includes C<MARK_LABEL>, the label text must be given in 160If C<$set> includes C<MARK_LABEL>, the label text must be given in
164C<$label>. 161C<$label>.
165 162
166If C<$set> contains C<MARK_MOVE>, then a circle symbol will be placed 163If C<$set> contains C<MARK_MOVE> then surrounded stones will be removed
167at this coordinate. Also, surrounded stones will be removed from the
168board and (simple) Kos are detected and marked with square symbols and 164from the board and (simple) Kos are detected and marked with square
169C<MARK_KO>. The circle and square markings are removed with the next 165symbols and C<MARK_KO>, after removing other marking symbols. The
166markings are also removed with the next next update structure that uses
170update that uses C<MARK_MOVE>, so this flag is suited well for marking, 167C<MARK_MOVE>, so this flag is suited well for marking, well, moves. Note
171well, moves. Note that you can make invalid "moves" (such as suicide) and 168that you can make invalid "moves" (such as suicide) and C<update> will
172C<update> will try to cope with it. You can use C<is_valid_move> to avoid 169try to cope with it. You can use C<is_valid_move> to avoid making illegal
173making illegal moves. 170moves.
174 171
175For handicap "moves", currently only board sizes 9, 13 and 19 are 172For handicap "moves", currently only board sizes 9, 13 and 19 are
176supported and only handicap values from 2 to 9. The placement follows the 173supported and only handicap values from 2 to 9. The placement follows the
177IGS rules, if you want other placements, you have to set it up yourself. 174IGS rules, if you want other placements, you have to set it up yourself.
178 175
211 7 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,1)], 208 7 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,1)],
212 8 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,0 1,2 )], 209 8 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,0 1,2 )],
213 9 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,0 1,2 1,1)], 210 9 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,0 1,2 1,1)],
214); 211);
215 212
213our $mark_symbols = MARK_CIRCLE | MARK_SQUARE | MARK_TRIANGLE | MARK_CROSS | MARK_KO;
214
216sub update { 215sub update {
217 my ($self, $path) = @_; 216 my ($self, $path) = @_;
218 217
219 my $board = $self->{board}; 218 my $board = $self->{board};
220 219
221 for (@$path) { 220 for (@$path) {
222 my ($x, $y, $clr, $set, $label) = @$_; 221 my ($x, $y, $clr, $set, $label) = @$_;
223 222
224 my $nodemask =
225 $_ == $path->[-1]
226 ? ~0
227 : ~(MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL | MARK_KO);
228
229 if (!defined $x) { 223 if (!defined $x) {
224 $$_ &= ~$mark_symbols for @{ delete $self->{unmark} || [] };
230 # pass 225 # pass
231 $self->{last} = $set & MARK_B ? COLOUR_BLACK : COLOUR_WHITE;
232 226
233 } elsif ($x == MOVE_HANDICAP) { 227 } elsif ($x == MOVE_HANDICAP) {
228 $$_ &= ~$mark_symbols for @{ delete $self->{unmark} || [] };
229
234 # $y = #handicap stones 230 # $y = #handicap stones
235 my $c = $HANDICAP_COORD{$self->{size}} 231 my $c = $HANDICAP_COORD{$self->{size}}
236 or Carp::croak "$self->{size}: illegal board size for handicap"; 232 or Carp::croak "$self->{size}: illegal board size for handicap";
237 my $h = $HANDICAP_XY{$y} 233 my $h = $HANDICAP_XY{$y}
238 or Carp::croak "$y: illegal number of handicap stones"; 234 or Carp::croak "$y: illegal number of handicap stones";
241 my ($x, $y) = map $c->[$_], split /,/; 237 my ($x, $y) = map $c->[$_], split /,/;
242 $board->[$x][$y] = MARK_B | MARK_MOVE; 238 $board->[$x][$y] = MARK_B | MARK_MOVE;
243 } 239 }
244 240
245 } else { 241 } else {
246 $board->[$x][$y] = 242 my $space = \$board->[$x][$y];
247 $board->[$x][$y] 243
248 & ~$clr 244 $$space = $$space & ~$clr | $set;
249 | $set
250 & $nodemask;
251 245
252 $self->{label}[$x][$y] = $label if $set & MARK_LABEL; 246 $self->{label}[$x][$y] = $label if $set & MARK_LABEL;
253 247
254 if ($set & MARK_MOVE) { 248 if ($set & MARK_MOVE) {
255 $self->{last} = $set & MARK_B ? COLOUR_BLACK : COLOUR_WHITE; 249 $$_ &= ~$mark_symbols for @{ $self->{unmark} || [] };
250 @{ $self->{unmark} } = $space;
256 251
257 unless (${ $_->[5] ||= \my $hint }) { 252 unless (${ $_->[5] ||= \my $hint }) {
258 my ($own, $opp) = 253 my ($own, $opp) =
259 $set & MARK_B 254 $set & MARK_B
260 ? (MARK_B, MARK_W) 255 ? (MARK_B, MARK_W)
269 264
270 # keep only unique coordinates 265 # keep only unique coordinates
271 @capture = do { my %seen; grep !$seen{"$_->[0],$_->[1]"}++, @capture }; 266 @capture = do { my %seen; grep !$seen{"$_->[0],$_->[1]"}++, @capture };
272 267
273 # remove captured stones 268 # remove captured stones
274 $self->{captures}[$self->{last}] += @capture; 269 $self->{captures}[$own == MARK_B ? COLOUR_BLACK : COLOUR_WHITE] += @capture;
275 $self->{board}[$_->[0]][$_->[1]] &= ~(MARK_B | MARK_W | MARK_MOVE) 270 $self->{board}[$_->[0]][$_->[1]] = 0
276 for @capture; 271 for @capture;
277 272
278 $suicide += $self->capture ($own, $x, $y); 273 $suicide += $self->capture ($own, $x, $y);
279 274
280 ${ $_->[5] } ||= !(@capture || $suicide); 275 ${ $_->[5] } ||= !(@capture || $suicide);
288 $libs++ if $x < $self->{max} && !($board->[$x+1][$y] & $opp); 283 $libs++ if $x < $self->{max} && !($board->[$x+1][$y] & $opp);
289 $libs++ if $y > 0 && !($board->[$x][$y-1] & $opp); 284 $libs++ if $y > 0 && !($board->[$x][$y-1] & $opp);
290 $libs++ if $y < $self->{max} && !($board->[$x][$y+1] & $opp); 285 $libs++ if $y < $self->{max} && !($board->[$x][$y+1] & $opp);
291 286
292 if ($libs == 1) { 287 if ($libs == 1) {
293 $board->[$x][$y] = $board->[$x][$y] & ~MARK_CIRCLE | (MARK_KO & $nodemask); 288 $$space = $$space & ~$mark_symbols | MARK_KO;
289
294 ($x, $y) = @{$capture[0]}; 290 ($x, $y) = @{$capture[0]};
295 $board->[$x][$y] |= MARK_KO & $nodemask; 291 $board->[$x][$y] |= MARK_KO;
292
293 push @{ $self->{unmark} }, \$board->[$x][$y];
296 } 294 }
297 } 295 }
298 } 296 }
299 } 297 }
300 } 298 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines