Add san() to the MoveSerializer interface, so other variants can call it.
[tagua/yd.git] / src / index.cpp
blobf4d5a119e4854387a6761e66c0d4e92d3f446de1
2 /*
3 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
4 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
12 #include <QStringList>
13 #include <KDebug>
14 #include "index.h"
16 Index::operator QString() const {
17 QString retv = QString::number(num_moves);
19 for(int i = 0; i < (int)nested.size(); i++)
20 retv += QString("_%1.%2").arg( nested[i].variation ).arg( nested[i].num_moves );
22 return retv;
25 Index Index::fromString(const QString& s) {
26 QStringList l = s.split("_");
27 if(l.isEmpty())
28 return Index(-1);
30 Index retv(l[0].toInt());
31 for(int i=1;i<l.size();i++) {
32 QStringList v = l[i].split(".");
33 if(v.size()!=2)
34 return Index(-1);
35 retv.nested.push_back(Ref(v[0].toInt(), v[1].toInt()));
37 return retv;
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 bool Index::atVariationStart() const {
50 return nested.size() && (nested.back().num_moves == 0);
53 Index Index::flipVariation(const Index& vstart, int v_id) const {
54 int s = vstart.nested.size();
55 if(s) {
56 if( (int)nested.size() < s
57 || vstart.num_moves != num_moves)
58 return *this;
60 for(int i=0;i<s-1;i++)
61 if(vstart.nested[i] != nested[i])
62 return *this;
64 if(vstart.nested[s-1].variation != nested[s-1].variation
65 || vstart.nested[s-1].num_moves > nested[s-1].num_moves)
66 return *this;
68 if(nested[s-1].num_moves > vstart.nested[s-1].num_moves) {
69 Index retv(num_moves);
70 for(int i=0;i<s;i++)
71 retv.nested.push_back(vstart.nested[i]);
72 retv.nested.push_back(Ref(v_id, nested[s-1].num_moves - vstart.nested[s-1].num_moves - 1));
73 for(int i=s;i<(int)nested.size();i++)
74 retv.nested.push_back(nested[i]);
75 return retv;
77 else if(nested[s-1].num_moves == vstart.nested[s-1].num_moves
78 && (int)nested.size() > s && nested[s].variation == v_id) {
79 Index retv(num_moves);
80 for(int i=0;i<s-1;i++)
81 retv.nested.push_back(vstart.nested[i]);
82 retv.nested.push_back(Ref(nested[s-1].variation, nested[s-1].num_moves + nested[s].num_moves + 1));
83 for(int i=s+1;i<(int)nested.size();i++)
84 retv.nested.push_back(nested[i]);
85 return retv;
87 else
88 return *this;
90 else if(num_moves > vstart.num_moves) {
91 Index retv(vstart.num_moves);
92 retv.nested.push_back(Ref(v_id,num_moves - vstart.num_moves - 1));
93 for(int i=0;i<(int)nested.size();i++)
94 retv.nested.push_back(nested[i]);
95 return retv;
97 else if(num_moves == vstart.num_moves
98 && nested.size() > 0 && nested[0].variation == v_id) {
99 Index retv(num_moves + nested[0].num_moves + 1);
100 for(int i=1;i<(int)nested.size();i++)
101 retv.nested.push_back(nested[i]);
102 return retv;
104 else
105 return *this;
108 Index Index::next(int variation_id, int num) const {
109 Index retv = *this;
110 if(variation_id != -1)
111 retv.nested.push_back( Ref(variation_id, num-1) );
112 else if(retv.nested.size() == 0)
113 retv.num_moves += num;
114 else
115 retv.nested.last().num_moves += num;
117 return retv;
120 Index Index::prev(int _num) const {
121 int num = _num;
122 Index retv = *this;
124 while(num) {
125 if(retv.nested.size() == 0) {
126 if(retv.num_moves < num) {
127 kError() << "Cannot rewind index" << *this << "by" << _num;
128 return Index(-1);
130 retv.num_moves -= num;
131 num = 0;
133 else {
134 if(retv.nested.last().num_moves >= num) {
135 retv.nested.last().num_moves -= num;
136 num = 0;
138 else {
139 num -= retv.nested.last().num_moves+1;
140 retv.nested.pop_back();
145 return retv;
148 Index Index::min(const Index& ix) const {
149 if(ix.num_moves != num_moves)
150 return Index( std::min(ix.num_moves, num_moves) );
152 Index retv(num_moves);
153 for(int i = 0; (i < (int)nested.size()) && (i < (int)ix.nested.size()); i++) {
154 if(nested[i].variation != ix.nested[i].variation)
155 break;
156 retv.nested.push_back(Ref(nested[i].variation,
157 std::min(ix.nested[i].num_moves, nested[i].num_moves) ));
158 if(ix.nested[i].num_moves != nested[i].num_moves)
159 break;
162 return retv;
165 std::pair<int, int> Index::stepsTo(const Index& ix) const {
166 int i;
167 int down = 0, up = 0;
168 bool branch = ix.num_moves != num_moves;
169 if(num_moves>ix.num_moves)
170 down += num_moves-ix.num_moves;
171 if(num_moves<ix.num_moves)
172 up += ix.num_moves-num_moves;
174 for(i = 0; (i < (int)nested.size()) && (i < (int)ix.nested.size()); i++) {
175 if(nested[i].variation != ix.nested[i].variation)
176 branch = true;
177 if(branch) {
178 down += nested[i].num_moves+1;
179 up += ix.nested[i].num_moves+1;
180 continue;
182 if(ix.nested[i].num_moves != nested[i].num_moves)
183 branch = true;
184 if(nested[i].num_moves>ix.nested[i].num_moves)
185 down += nested[i].num_moves-ix.nested[i].num_moves;
186 if(nested[i].num_moves<ix.nested[i].num_moves)
187 up += ix.nested[i].num_moves-nested[i].num_moves;
189 for(; i<(int)nested.size();i++)
190 down += nested[i].num_moves+1;
191 for(; i<(int)ix.nested.size();i++)
192 up += ix.nested[i].num_moves+1;
193 return std::pair<int,int>(down, up);
196 int Index::lastIndex() {
197 return nested.size() ? nested.back().num_moves : num_moves;
200 bool Index::mainLine() const {
201 return nested.empty();