ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/kgsueme/lib/KGS/Game/Tree.pm
Revision: 1.3
Committed: Thu May 29 12:19:11 2003 UTC (23 years, 5 months ago) by pcg
Branch: MAIN
Changes since 1.2: +28 -7 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 package KGS::Game::Tree;
2    
3     use KGS::Constants;
4    
5     # _should_ be unified, but the two types are slightly different
6     # (this really looks like a grown, as opposed to designed, protocol)
7     my %marker_type = (
8     triangle => MARK_TRIANGLE,
9     square => MARK_SQUARE,
10     circle => MARK_CIRCLE,
11     small_b => MARK_SMALL_B,
12     small_w => MARK_SMALL_W,
13     );
14    
15     # exclusion masks... the bit on the left excludes (removes) the ones on the right
16     my %exclude_type = (
17     &MARK_TRIANGLE => MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL,
18     &MARK_SQUARE => MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL,
19     &MARK_CIRCLE => MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL,
20     &MARK_LABEL => MARK_SQUARE | MARK_TRIANGLE | MARK_CIRCLE | MARK_LABEL,
21     &MARK_SMALL_B => MARK_SMALL_B | MARK_SMALL_W | MARK_B | MARK_W | MARK_MOVE,
22     &MARK_SMALL_W => MARK_SMALL_B | MARK_SMALL_W | MARK_B | MARK_W | MARK_MOVE,
23 pcg 1.3 &MARK_GRAY_B => MARK_B | MARK_W | MARK_MOVE | MARK_GRAY_B | MARK_GRAY_W,
24     &MARK_GRAY_W => MARK_B | MARK_W | MARK_MOVE | MARK_GRAY_B | MARK_GRAY_W,
25     &MARK_B => MARK_SMALL_B | MARK_SMALL_W | MARK_B | MARK_W | MARK_MOVE | MARK_GRAY_B | MARK_GRAY_W,
26     &MARK_W => MARK_SMALL_B | MARK_SMALL_W | MARK_B | MARK_W | MARK_MOVE | MARK_GRAY_B | MARK_GRAY_W,
27 pcg 1.1 );
28    
29     sub init_tree {
30     my ($self) = @_;
31     $self->{tree} = [ { id => 0 } ];
32     }
33    
34     sub update_tree {
35     my ($self, $tree) = @_;
36    
37     my $node = $self->{curnode};
38    
39     for (@$tree) {
40     my ($type, @arg) = @$_;
41     if ($type eq "add_child") {
42     $node = $self->{tree}[$arg[0] + 1]
43 pcg 1.3 or die "FATAL: referencing nonexistent node $arg[0]+1!";
44 pcg 1.1
45     my $new = { parent => $node->{id}, id => scalar @{$self->{tree}} };
46    
47     push @{$self->{tree}}, $new;
48     push @{$node->{children}}, $new->{id};
49    
50     $node = $new;
51    
52     } elsif (my $bit = $marker_type{$type}) {
53     my $ref = \$node->{"$arg[1],$arg[2]"};
54    
55     $$ref &= ~$exclude_type{$bit};
56     $$ref |= $bit if $arg[0] != 2;
57    
58     } elsif ($type eq "label") {
59     my $ref = \$node->{"$arg[1],$arg[2]"};
60    
61     $$ref &= $exclude_type{&MARK_LABEL};
62     delete $node->{"L$arg[1],$arg[2]"};
63    
64     if (length $arg[0]) {
65     $$ref |= MARK_LABEL;
66     $node->{"L$arg[1],$arg[2]"} = $arg[0];
67     }
68    
69 pcg 1.3 } elsif ($type eq "move" or $type eq "addstone" or $type eq "gray") {
70     my $bit = $arg[0] == 0 ? $bit | ($type eq "gray" ? MARK_GRAY_B : MARK_B)
71     : $arg[0] == 1 ? $bit | ($type eq "gray" ? MARK_GRAY_W : MARK_W)
72     : 0;
73    
74     my $ref = \$node->{"$arg[1],$arg[2]"};
75    
76     $$ref &= $exclude_type{$bit};
77     $$ref |= $bit | ($type eq "move" ? MARK_MOVE : 0);
78    
79 pcg 1.1 } elsif ($type eq "move" or $type eq "addstone") {
80     my $bit = $type eq "move" ? MARK_MOVE : 0;
81    
82     $bit = $arg[0] == 0 ? $bit | MARK_B
83     : $arg[0] == 1 ? $bit | MARK_W
84     : 0;
85    
86     my $ref = \$node->{"$arg[1],$arg[2]"};
87    
88     $$ref &= $exclude_type{&MARK_MOVE};
89     $$ref |= $bit;
90    
91     } elsif ($type eq "comment") {
92 pcg 1.3 $node->{comment} .= $arg[0];
93    
94     } elsif ($type eq "player") {
95     $node->{player}[$arg[0]] = $arg[1];
96 pcg 1.1
97 pcg 1.2 } elsif ($type eq "time_left") {
98 pcg 1.3 $node->{time}[$arg[0]] = [$arg[1], $arg[2]];
99    
100     } elsif ($type eq "more") {
101     $self->{more} = 1;
102     $self->msg(get_tree => channel => $self->{channel}, node => @{$self->{tree}} - 1);
103    
104     } elsif ($type eq "done") {
105     $self->{loaded} = 1;
106     # nop
107 pcg 1.2
108 pcg 1.1 } else {
109     warn "unknown node parameter $type (@arg), ignored\n";
110     }
111     }
112    
113     $self->{curnode} = $node;
114     }
115    
116     sub get_path {
117     my ($self) = @_;
118    
119     my @nodes;
120    
121     my $node = $self->{curnode};
122    
123     for(;;) {
124     push @nodes, $node;
125     last unless $node->{parent};
126     $node = $self->{tree}[$node->{parent}];
127     }
128    
129     [reverse @nodes];
130     }
131    
132     sub set_node {
133     my ($self, $node) = @_;
134    
135     $self->{curnode} = $self->{tree}[$node + 1]
136     or die "set_node to undefined tree node $node+1";
137     }
138    
139     1;
140