Removed 'image' test (superseeded by 'luaimage' test)
[tagua/yd.git] / src / index.cpp
blob5352b72b4a4545f7a2ce6753630bcc294ad8a35b
1 /*
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.
9 */
11 #include <iostream>
12 #include <QStringList>
13 #include "index.h"
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 );
21 return retv;
24 Index Index::fromString(const QString& s) {
25 QStringList l = s.split("_");
26 if(l.isEmpty())
27 return Index(-1);
29 Index retv(l[0].toInt());
30 for(int i=1;i<l.size();i++) {
31 QStringList v = l[i].split(".");
32 if(v.size()!=2)
33 return Index(-1);
34 retv.nested.push_back(Ref(v[0].toInt(), v[1].toInt()));
36 return retv;
39 /** returns the number of moves from the start of the game */
40 int Index::totalNumMoves() const {
41 int retv = num_moves;
43 for(int i = 0; i < (int)nested.size(); i++)
44 retv += nested[i].num_moves+1;
46 return retv;
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);
54 /** flip variation */
55 Index Index::flipVariation(const Index& vstart, int v_id) const {
56 int s = vstart.nested.size();
57 if(s)
59 if( (int)nested.size() < s
60 || vstart.num_moves != num_moves)
61 return *this;
63 for(int i=0;i<s-1;i++)
64 if(vstart.nested[i] != nested[i])
65 return *this;
67 if(vstart.nested[s-1].variation != nested[s-1].variation
68 || vstart.nested[s-1].num_moves > nested[s-1].num_moves)
69 return *this;
71 if(nested[s-1].num_moves > vstart.nested[s-1].num_moves) {
72 Index retv(num_moves);
73 for(int i=0;i<s;i++)
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]);
78 return retv;
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]);
88 return retv;
90 else
91 return *this;
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]);
98 return retv;
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]);
105 return retv;
107 else
108 return *this;
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 {
115 Index retv = *this;
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;
120 else
121 retv.nested.rbegin()->num_moves += num;
123 return retv;
126 /** Returns an index pointing to the previous position (or to a position n moves back) */
127 Index Index::prev(int _num) const {
128 int num = _num;
129 Index retv = *this;
131 while(num) {
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;
136 return Index(-1);
138 retv.num_moves -= num;
139 num = 0;
141 else {
142 if(retv.nested.rbegin()->num_moves >= num) {
143 retv.nested.rbegin()->num_moves -= num;
144 num = 0;
146 else {
147 num -= retv.nested.rbegin()->num_moves+1;
148 retv.nested.pop_back();
153 return retv;
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)
165 break;
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)
169 break;
172 return retv;
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 {
177 int i;
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)
187 branch = true;
188 if(branch) {
189 down += nested[i].num_moves+1;
190 up += ix.nested[i].num_moves+1;
191 continue;
193 if(ix.nested[i].num_moves != nested[i].num_moves)
194 branch = true;
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;