2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
12 #include <QStringList>
15 Index::operator QString() const {
16 QString retv
= QString::number(num_moves
);
18 for(int i
= 0; i
< (int)nested
.size(); i
++)
19 retv
+= QString("_%1.%2").arg( nested
[i
].variation
).arg( nested
[i
].num_moves
);
24 Index
Index::fromString(const QString
& s
) {
25 QStringList l
= s
.split("_");
29 Index
retv(l
[0].toInt());
30 for(int i
=1;i
<l
.size();i
++) {
31 QStringList v
= l
[i
].split(".");
34 retv
.nested
.push_back(Ref(v
[0].toInt(), v
[1].toInt()));
39 /** returns the number of moves from the start of the game */
40 int Index::totalNumMoves() const {
43 for(int i
= 0; i
< (int)nested
.size(); i
++)
44 retv
+= nested
[i
].num_moves
+1;
49 /** true if this index is the first of a variation branch */
50 bool Index::atVariationStart() const {
51 return nested
.size() && (nested
[nested
.size()-1].num_moves
== 0);
55 Index
Index::flipVariation(const Index
& vstart
, int v_id
) const {
56 int s
= vstart
.nested
.size();
59 if( (int)nested
.size() < s
60 || vstart
.num_moves
!= num_moves
)
63 for(int i
=0;i
<s
-1;i
++)
64 if(vstart
.nested
[i
] != nested
[i
])
67 if(vstart
.nested
[s
-1].variation
!= nested
[s
-1].variation
68 || vstart
.nested
[s
-1].num_moves
> nested
[s
-1].num_moves
)
71 if(nested
[s
-1].num_moves
> vstart
.nested
[s
-1].num_moves
) {
72 Index
retv(num_moves
);
74 retv
.nested
.push_back(vstart
.nested
[i
]);
75 retv
.nested
.push_back(Ref(v_id
, nested
[s
-1].num_moves
- vstart
.nested
[s
-1].num_moves
- 1));
76 for(int i
=s
;i
<(int)nested
.size();i
++)
77 retv
.nested
.push_back(nested
[i
]);
80 else if(nested
[s
-1].num_moves
== vstart
.nested
[s
-1].num_moves
81 && (int)nested
.size() > s
&& nested
[s
].variation
== v_id
) {
82 Index
retv(num_moves
);
83 for(int i
=0;i
<s
-1;i
++)
84 retv
.nested
.push_back(vstart
.nested
[i
]);
85 retv
.nested
.push_back(Ref(nested
[s
-1].variation
, nested
[s
-1].num_moves
+ nested
[s
].num_moves
+ 1));
86 for(int i
=s
+1;i
<(int)nested
.size();i
++)
87 retv
.nested
.push_back(nested
[i
]);
93 else if(num_moves
> vstart
.num_moves
) {
94 Index
retv(vstart
.num_moves
);
95 retv
.nested
.push_back(Ref(v_id
,num_moves
- vstart
.num_moves
- 1));
96 for(int i
=0;i
<(int)nested
.size();i
++)
97 retv
.nested
.push_back(nested
[i
]);
100 else if(num_moves
== vstart
.num_moves
101 && nested
.size() > 0 && nested
[0].variation
== v_id
) {
102 Index
retv(num_moves
+ nested
[0].num_moves
+ 1);
103 for(int i
=1;i
<(int)nested
.size();i
++)
104 retv
.nested
.push_back(nested
[i
]);
111 /** Returns an index the point to the next position. If variation is != -1, you will be entering in the
112 sub-variation with this id instead of continuing in the current main line. You can also specify
113 the number of moves you want to go on (in the main line or in the specified variation) */
114 Index
Index::next(int variation_id
, int num
) const {
116 if(variation_id
!= -1)
117 retv
.nested
.push_back( Ref(variation_id
, num
-1) );
118 else if(retv
.nested
.size() == 0)
119 retv
.num_moves
+= num
;
121 retv
.nested
.rbegin()->num_moves
+= num
;
126 /** Returns an index pointing to the previous position (or to a position n moves back) */
127 Index
Index::prev(int _num
) const {
132 if(retv
.nested
.size() == 0) {
133 if(retv
.num_moves
< num
) {
134 std::cout
<< "--> Error in Index::prev! Cannot rewind index " << *this <<
135 " by " << _num
<< "!" << std::endl
;
138 retv
.num_moves
-= num
;
142 if(retv
.nested
.rbegin()->num_moves
>= num
) {
143 retv
.nested
.rbegin()->num_moves
-= num
;
147 num
-= retv
.nested
.rbegin()->num_moves
+1;
148 retv
.nested
.pop_back();
156 /** Returns an index that is the minimum of this index and the given one, ie the branch point
157 of the lines from start to the two indices. */
158 Index
Index::min(const Index
& ix
) const {
159 if(ix
.num_moves
!= num_moves
)
160 return Index( std::min(ix
.num_moves
, num_moves
) );
162 Index
retv(num_moves
);
163 for(int i
= 0; (i
< (int)nested
.size()) && (i
< (int)ix
.nested
.size()); i
++) {
164 if(nested
[i
].variation
!= ix
.nested
[i
].variation
)
166 retv
.nested
.push_back(Ref(nested
[i
].variation
,
167 std::min(ix
.nested
[i
].num_moves
, nested
[i
].num_moves
) ));
168 if(ix
.nested
[i
].num_moves
!= nested
[i
].num_moves
)
175 /** Returns the number of steps down and up you have to do to go from this index to the given one */
176 std::pair
<int, int> Index::stepsTo(const Index
& ix
) const {
178 int down
= 0, up
= 0;
179 bool branch
= ix
.num_moves
!= num_moves
;
180 if(num_moves
>ix
.num_moves
)
181 down
+= num_moves
-ix
.num_moves
;
182 if(num_moves
<ix
.num_moves
)
183 up
+= ix
.num_moves
-num_moves
;
185 for(i
= 0; (i
< (int)nested
.size()) && (i
< (int)ix
.nested
.size()); i
++) {
186 if(nested
[i
].variation
!= ix
.nested
[i
].variation
)
189 down
+= nested
[i
].num_moves
+1;
190 up
+= ix
.nested
[i
].num_moves
+1;
193 if(ix
.nested
[i
].num_moves
!= nested
[i
].num_moves
)
195 if(nested
[i
].num_moves
>ix
.nested
[i
].num_moves
)
196 down
+= nested
[i
].num_moves
-ix
.nested
[i
].num_moves
;
197 if(nested
[i
].num_moves
<ix
.nested
[i
].num_moves
)
198 up
+= ix
.nested
[i
].num_moves
-nested
[i
].num_moves
;
200 for(; i
<(int)nested
.size();i
++)
201 down
+= nested
[i
].num_moves
+1;
202 for(; i
<(int)ix
.nested
.size();i
++)
203 up
+= ix
.nested
[i
].num_moves
+1;
204 return std::pair
<int,int>(down
, up
);
207 /** returns the number of moves in the most nested variation */
208 int Index::lastIndex() {
209 return nested
.size() ? nested
[nested
.size()-1].num_moves
: num_moves
;