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.8 by root, Wed Jun 25 04:15:51 2008 UTC vs.
Revision 1.9 by root, Wed Jun 25 20:11:33 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
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_CROSS (){ 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 @_,
113 unmark => [],
116 $class; 114 }, $class
117} 115}
118 116
119# inefficient and primitive, I hear you say? 117# inefficient and primitive, I hear you say?
120# well... you are right :) 118# well... you are right :)
121# use an extremely dumb floodfill algorithm to get rid of captured stones 119# use an extremely dumb floodfill algorithm to get rid of captured stones
161specified in C<$clr>, then setting bits specified in C<$set>. 159specified in C<$clr>, then setting bits specified in C<$set>.
162 160
163If C<$set> includes C<MARK_LABEL>, the label text must be given in 161If C<$set> includes C<MARK_LABEL>, the label text must be given in
164C<$label>. 162C<$label>.
165 163
166If C<$set> contains C<MARK_MOVE>, then a circle symbol will be placed 164If 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 165from the board and (simple) Kos are detected and marked with square
169C<MARK_KO>. The circle and square markings are removed with the next 166symbols and C<MARK_KO>, after removing other marking symbols. The
167markings 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, 168C<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 169that 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 170try to cope with it. You can use C<is_valid_move> to avoid making illegal
173making illegal moves. 171moves.
174 172
175For handicap "moves", currently only board sizes 9, 13 and 19 are 173For handicap "moves", currently only board sizes 9, 13 and 19 are
176supported and only handicap values from 2 to 9. The placement follows the 174supported 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. 175IGS rules, if you want other placements, you have to set it up yourself.
178 176
211 7 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,1)], 209 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 )], 210 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)], 211 9 => [qw(0,2 2,0 0,0 2,2 0,1 2,1 1,0 1,2 1,1)],
214); 212);
215 213
214our $mark_symbols = MARK_CIRCLE | MARK_SQUARE | MARK_TRIANGLE | MARK_CROSS | MARK_KO;
215
216sub update { 216sub update {
217 my ($self, $path) = @_; 217 my ($self, $path) = @_;
218 218
219 my $board = $self->{board}; 219 my $board = $self->{board};
220 220
221 for (@$path) { 221 for (@$path) {
222 my ($x, $y, $clr, $set, $label) = @$_; 222 my ($x, $y, $clr, $set, $label) = @$_;
223 223
224 my $nodemask =
225 $_ == $path->[-1]
226 ? ~0
227 : ~(MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL | MARK_KO);
228
229 if (!defined $x) { 224 if (!defined $x) {
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) {
234 # $y = #handicap stones 228 # $y = #handicap stones
235 my $c = $HANDICAP_COORD{$self->{size}} 229 my $c = $HANDICAP_COORD{$self->{size}}
236 or Carp::croak "$self->{size}: illegal board size for handicap"; 230 or Carp::croak "$self->{size}: illegal board size for handicap";
241 my ($x, $y) = map $c->[$_], split /,/; 235 my ($x, $y) = map $c->[$_], split /,/;
242 $board->[$x][$y] = MARK_B | MARK_MOVE; 236 $board->[$x][$y] = MARK_B | MARK_MOVE;
243 } 237 }
244 238
245 } else { 239 } else {
246 $board->[$x][$y] = 240 my $space = \$board->[$x][$y];
247 $board->[$x][$y] 241
248 & ~$clr 242 $$space = $$space & ~$clr | $set;
249 | $set
250 & $nodemask;
251 243
252 $self->{label}[$x][$y] = $label if $set & MARK_LABEL; 244 $self->{label}[$x][$y] = $label if $set & MARK_LABEL;
253 245
254 if ($set & MARK_MOVE) { 246 if ($set & MARK_MOVE) {
255 $self->{last} = $set & MARK_B ? COLOUR_BLACK : COLOUR_WHITE; 247 $$_ &= ~$mark_symbols for @{ $self->{unmark} };
248 @{ $self->{unmark} } = $space;
256 249
257 unless (${ $_->[5] ||= \my $hint }) { 250 unless (${ $_->[5] ||= \my $hint }) {
258 my ($own, $opp) = 251 my ($own, $opp) =
259 $set & MARK_B 252 $set & MARK_B
260 ? (MARK_B, MARK_W) 253 ? (MARK_B, MARK_W)
269 262
270 # keep only unique coordinates 263 # keep only unique coordinates
271 @capture = do { my %seen; grep !$seen{"$_->[0],$_->[1]"}++, @capture }; 264 @capture = do { my %seen; grep !$seen{"$_->[0],$_->[1]"}++, @capture };
272 265
273 # remove captured stones 266 # remove captured stones
274 $self->{captures}[$self->{last}] += @capture; 267 $self->{captures}[$own == MARK_B ? COLOUR_BLACK : COLOUR_WHITE] += @capture;
275 $self->{board}[$_->[0]][$_->[1]] &= ~(MARK_B | MARK_W | MARK_MOVE) 268 $self->{board}[$_->[0]][$_->[1]] = 0
276 for @capture; 269 for @capture;
277 270
278 $suicide += $self->capture ($own, $x, $y); 271 $suicide += $self->capture ($own, $x, $y);
279 272
280 ${ $_->[5] } ||= !(@capture || $suicide); 273 ${ $_->[5] } ||= !(@capture || $suicide);
288 $libs++ if $x < $self->{max} && !($board->[$x+1][$y] & $opp); 281 $libs++ if $x < $self->{max} && !($board->[$x+1][$y] & $opp);
289 $libs++ if $y > 0 && !($board->[$x][$y-1] & $opp); 282 $libs++ if $y > 0 && !($board->[$x][$y-1] & $opp);
290 $libs++ if $y < $self->{max} && !($board->[$x][$y+1] & $opp); 283 $libs++ if $y < $self->{max} && !($board->[$x][$y+1] & $opp);
291 284
292 if ($libs == 1) { 285 if ($libs == 1) {
293 $board->[$x][$y] = $board->[$x][$y] & ~MARK_CIRCLE | (MARK_KO & $nodemask); 286 $$space = $$space & ~$mark_symbols | MARK_KO;
287
294 ($x, $y) = @{$capture[0]}; 288 ($x, $y) = @{$capture[0]};
295 $board->[$x][$y] |= MARK_KO & $nodemask; 289 $board->[$x][$y] |= MARK_KO;
290
291 push @{ $self->{unmark} }, \$board->[$x][$y];
296 } 292 }
297 } 293 }
298 } 294 }
299 } 295 }
300 } 296 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines