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.5 by root, Tue Jun 24 19:22:08 2008 UTC vs.
Revision 1.10 by root, Wed Jun 25 20:49:38 2008 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines