remove old files add new sources
[mancala] / src / GameInfo.cpp
1 /*
2 Mancala - A Historical Board Game
3 Copyright (C) 2009-2010 A.H.M.Mahfuzur Rahman 65mahfuz90@gmail.com
4 Copyright (c) 2010 Reto Zingg g.d0b3rm4n@gmail.com
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
21 #include "GameInfo.h"
22
23 #include <math.h>
24 #include <QFile>
25 #include <QStringList>
26 // #include <kdebug.h>
27 // #include <kstandarddirs.h>
28
29
30
31 GameInfo::GameInfo(){
32
33     initializeAll();
34
35 }
36
37 void GameInfo::initializeAll(){
38
39     //making all list empty
40     m_capture_types = 0;
41     while(m_capture_info.count())
42         m_capture_info.pop_front();
43     while(m_rotation_cup.count())
44         m_rotation_cup.pop_front();
45
46 }
47
48 void GameInfo::setGameInfo(QString file){
49
50     QString fileName = QString("/opt/mancala/data/rules/%1.xml").arg(file);
51 //    kDebug() << "The GameInfo File Name: " << fileName;
52     if(fileName.isEmpty()) return;
53
54     QFile infoFile(fileName);
55     if (!infoFile.open(QFile::ReadOnly | QFile::Text)) return;
56     parseXmlFile(&infoFile);
57
58 }
59
60 //The parsing operation will be here
61 void GameInfo::parseXmlFile(QIODevice *device){
62
63     //kDebug() << "Starting of setGameInfo: " ;
64     setDevice(device);
65
66
67     while(!atEnd()){
68         readNext();
69
70         if(isStartElement()){
71
72             if(name() == "game"){
73                 parseGame();
74             }
75             else raiseError(QObject::tr("This is not the exact file Needed"));
76         }
77     }
78
79     //kDebug() << "Region: " << m_region;
80     //kDebug() << "Game Type: " << m_type;
81
82     //kDebug() << "Row Number " << m_num_rows;
83     //kDebug() << "Cup Per Row " << m_cups_per_row;
84     //kDebug() << "Kalah Number " << m_num_kalahs;
85     //kDebug() << "Initial Stone Per Row " << m_initial_stones_per_cup;
86
87     //kDebug() << "Sowing Information: --------------";
88     //kDebug() << "Minimum stone to sow:" << m_min_stones_to_sow;
89     //kDebug() << "Left Stone to Cup:" << m_left_stone_to_cup;
90     //kDebug() << "Omit Initial Cup:" << m_omit_initial_cup;
91     //kDebug() << "stones to kalah:" << m_stones_to_kalah;
92     //kDebug() << "Bonus Turn" << m_bonus_turn;
93
94 //    kDebug() << "Capture types: " << m_capture_types;
95
96 }
97
98 void GameInfo::parseGame(){
99
100     Q_ASSERT(isStartElement() && name() == "game");
101
102     while(!atEnd()){
103         readNext();
104
105         if(isEndElement())
106             break;
107
108         if(isStartElement()){
109
110             if(name() == "type"){
111                 QString typeString = readElementText();
112                 if(typeString == "modern")
113                     m_type = MODERN;
114                 else if(typeString == "traditional")
115                     m_type = TRADITIONAL;
116                 else m_type = CUSTOM;
117             }
118             else if( name() == "region")
119                 m_region = readElementText();
120             else if( name() == "board")
121                 parseBoard();
122             //Other Elements will be here
123             else if(name() == "rules")
124                 parseRules();
125             else {
126                 // kDebug() << "Option that is not still handled";
127             }
128         }
129     }
130
131 }
132
133 void GameInfo::parseBoard(){
134
135     //kDebug() << " I am here to parseBoard() ";
136     //kDebug() << "Name is: " << name();
137
138     Q_ASSERT(isStartElement() && name() == "board");
139
140     while(!atEnd()){
141         readNext();
142
143         //kDebug() << "Name is: " << name();
144         if(isEndElement())
145             break;
146         if(isStartElement()){
147
148             if(name() == "row_number"){
149                 m_num_rows = readElementText().toInt();
150             }
151
152             else if(name() == "cup_per_row"){
153                 m_cups_per_row = readElementText().toInt();
154             }
155
156             else if(name() == "kalah_number"){
157                 m_num_kalahs = readElementText().toInt();
158             }
159
160             else if(name() == "initial_stone_number"){
161                 m_initial_stones_per_cup = readElementText().toInt();
162             }
163             else {
164                 // kDebug() << "Option that is not still handled";
165             }
166         }
167     }
168
169     //setCupRotation (default anticlockwise)
170     for(int i = 0 ; i < m_num_rows * m_cups_per_row ; i++){
171         m_rotation_cup << GameInfo::ANTICLOCKWISE;
172         ////kDebug() << "Cup: " << i << " rotation: " << m_rotation_cup[i];
173     }
174
175 }
176
177 void GameInfo::parseRules(){
178
179     Q_ASSERT( isStartElement() && name() == "rules");
180
181     while(!atEnd()){
182         readNext();
183
184         if(isEndElement()) break;
185
186         if(isStartElement()){
187
188             if(name() == "sowing")
189                 parseSowing();
190             else if(name() == "capture")
191                 parseCapture();
192             else if(name() == "end_rule")
193                 parseEndRules();
194             else if( name() == "special_rules")
195                 parseSpecialRules();
196             else {
197                 // kDebug() << "Option that is not still handled";
198             }
199         }
200     }
201
202 }
203
204 void GameInfo::parseSowing(){
205
206     Q_ASSERT( isStartElement() && name() == "sowing");
207
208     //kDebug() << "I am here to parseSowing()";
209
210     //kDebug() << "Name is: " << name();
211
212     while(!atEnd()){
213         readNext();
214
215         //kDebug() << "Name is: " << name();
216         if(isEndElement()) break;
217
218         if(isStartElement()){
219
220             if(name() == "rotation"){
221
222                 //kDebug() << "found Rotation";
223
224                 if(attributes().value("id") == "complicated"){
225                     //kDebug() << "Attribute value: " << "complicated";
226                 }
227                 else if(attributes().value("id") == "anticlockwise"){
228                     //kDebug() << "Attribute value: " << "anticlockwise";
229                     m_rotation_type = GameInfo::ANTICLOCKWISE;
230                 }
231                 else{
232                     m_rotation_type = GameInfo::CLOCKWISE;
233                     //kDebug() << "Attribute value: " << "clockwise";
234                     //set Cup Rotation Info - clockwise
235                     for(int i = 0 ; i < m_num_rows * m_cups_per_row ; i++)
236                         m_rotation_cup << GameInfo::ANTICLOCKWISE;
237                 }
238                 parseRotation();
239             }
240
241             else if( name() == "lap" ){
242
243                 //kDebug() << "found lap -----------";
244                 if(attributes().value("id") == "single"){
245                     m_lap_style = GameInfo::SINGLE;
246                     //kDebug() << "single Lap";
247                 }
248
249                 else if(attributes().value("id") == "multiple"){
250                     //kDebug() << "lap Style:" << "multiple";
251                     m_lap_style = GameInfo::MULTIPLE;
252                 }
253                 parseLap();
254             }
255
256             else if( name() == "min_stone_to_sow" )
257                 m_min_stones_to_sow = readElementText().toInt();
258
259             else if( name() == "left_stone_to_cup" )
260                 m_left_stone_to_cup = readElementText().toInt();
261
262             else if( name() == "omit_initial_cup" ){
263                 if(readElementText() == "yes")
264                     m_omit_initial_cup = true;
265                 else m_omit_initial_cup = false;
266             }
267
268             else if( name() == "stones_to_kalah"){
269
270                 //If it is necessary that readElementText() will be used more than once then
271                 //assign it to a QString
272                 QString valueText = readElementText();
273                 //kDebug() << "The valueText is: " << valueText;
274
275                 if( valueText == "none")
276                     m_stones_to_kalah = GameInfo::NONE;
277                 else if( valueText == "both" )
278                     m_stones_to_kalah = GameInfo::BOTH;
279                 else if( valueText == "own" )
280                     m_stones_to_kalah = GameInfo::OWN;
281                 else if( valueText == "opponent")
282                     m_stones_to_kalah = GameInfo::OPPONENT;
283             }
284             else if(name() == "bonus_turn"){
285
286                 if(readElementText() == "yes"){
287                     //kDebug() << "Bonus Turn True";
288                     m_bonus_turn = true;
289                 }
290                 else m_bonus_turn = false;
291             }
292         }
293
294     }
295 }
296
297 //capture
298 void GameInfo::parseCapture(){
299
300     Q_ASSERT(isStartElement() && name() == "capture");
301
302     //kDebug() << "I am in capture";
303     while(!atEnd()){
304         readNext();
305
306         if(isEndElement()) break;
307
308
309         if(isStartElement()){
310
311             if( name() == "capture_type"){
312
313                 if(attributes().value("id") == "cross"){
314                     //kDebug() << "Caputure type: cross :" << m_capture_types;
315                     m_capture_types |= 1;
316                     //kDebug() << "Capture types: " << m_capture_types;
317                     parseCrossCapture();
318                     //kDebug() << "Capture types: " << m_capture_types;
319                 }
320                 else if(attributes().value("id") == "count"){
321                     m_capture_types |= 2;
322                     parseCountCapture();
323                 }
324                 else if(attributes().value("id") == "series"){
325                     m_capture_types |= 4;
326                     parseSeriesCapture();
327                 }
328                 else if(attributes().value("id") == "pull_across"){
329                     m_capture_types |= 16;
330                     parsePullAcrossCapture();
331                 }
332             }
333         }
334     }
335
336 }
337
338 //special rules
339 void GameInfo::parseSpecialRules(){
340
341     Q_ASSERT(isStartElement() && name() == "special_rules");
342
343     //kDebug() << "I am in special rules";
344
345     while(!atEnd()){
346         readNext();
347
348         if(isEndElement()) break;
349
350         m_special_flags = 0;
351         if(isStartElement()){
352
353             if( name() == "empty_opponent" ){
354                 if( readElementText() == "yes")
355                     m_special_flags |= 1;
356                 //kDebug() << "empty Opponent:" << (m_special_flags & 1);
357             }
358             else if( name() == "turn_passing" ){
359                 if(readElementText() == "yes")
360                     m_special_flags |= 2;
361                 //kDebug() << "Turn Passing:" << (m_special_flags & 2);
362             }
363             else if( name() == "compulsory_move" ){
364                 if(readElementText() == "yes")
365                     m_special_flags |= 4;
366                 //kDebug() << "Compulsory Moves:" << (m_special_flags & 4);
367             }
368         }
369
370     }
371     //kDebug() << "Special_Flags" << (m_special_flags & 1) << " " << (m_special_flags & 2) << " " << (m_special_flags & 4);
372 }
373
374
375 //end_rule
376 void GameInfo::parseEndRules(){
377
378 }
379
380 //lap
381 void GameInfo::parseLap(){
382
383     Q_ASSERT( isStartElement() && name() == "lap");
384
385     while(!atEnd()){
386         readNext();
387
388         if(isEndElement()) break;
389
390         if(isStartElement()){
391
392             if( name() == "end_of_lap" && attributes().value("id") == "cup"){
393                 //kDebug() << "Found cup in end_of_lap";
394                 parseLapEnd();
395             }
396         }
397
398     }
399 }
400
401 //lap_end
402 void GameInfo::parseLapEnd(){
403
404     Q_ASSERT( isStartElement() && name() == "end_of_lap" );
405
406     while(!atEnd()){
407         readNext();
408
409         if(isEndElement()) break;
410
411         if(isStartElement()){
412
413             if( name() == "stone_no"){
414                 m_stones_to_end_lap = readElementText().toInt();
415                 //kDebug() << "Stone in cup to end lap: " << m_stones_to_end_lap;
416             }
417
418             else if( name() == "side"){
419                 QString valueText = readElementText();
420                 //kDebug() << "lap end side: " << valueText;
421
422                 if( valueText == "both")
423                     m_side_to_end_lap = GameInfo::BOTH;
424                 else if( valueText == "own")
425                     m_side_to_end_lap = GameInfo::OWN;
426                 else
427                     m_side_to_end_lap = GameInfo::OPPONENT;
428             }
429         }
430     }
431 }
432
433 //rotation - complicated
434 void GameInfo::parseRotation(){
435
436     Q_ASSERT( isStartElement() && name() == "rotation" );
437
438     while(!atEnd()){
439         readNext();
440
441         if(isEndElement()) break;
442
443         if(isStartElement()){
444
445             if( name() == "clockwise"){
446
447                 int upper,j,lower;
448                 int numCup;// = readElementText().toInt();
449
450                 if(attributes().value("direction") == "left"){
451                     numCup = readElementText().toInt();
452
453                     upper = m_cups_per_row -1 ;
454                     lower = 2 * m_cups_per_row -1;
455
456                     for(j = 0 ; j < numCup ; ++j,--upper,--lower )
457                         m_rotation_cup[upper] = m_rotation_cup[lower] = GameInfo::CLOCKWISE;
458
459
460                 }
461                 else{
462                     numCup = readElementText().toInt();
463
464                     upper = 0;
465                     lower = m_cups_per_row;
466
467                     for( j = 0 ; j < numCup; ++j,++upper,++lower)
468                         m_rotation_cup[upper] = m_rotation_cup[lower] = GameInfo::CLOCKWISE;
469                 }
470             }
471
472             //            kDebug() << "All cup rotation type:";
473             //            for( int i = 0 ; i < m_cups_per_row * m_num_rows ; i++ ){
474             //                kDebug() << "Cup: " << i << m_rotation_cup[i];
475             //            }
476
477         }
478     }
479 }
480
481 //capture parsings - CrossCapture
482 void GameInfo::parseCrossCapture(){
483
484     Q_ASSERT( isStartElement() && name() == "capture_type");
485     //kDebug() << "Now in CrossCapture:" << m_capture_types;
486
487     Side captureSide;
488     QList<int>stoneNumbers;
489     QString text;
490     QStringList list;
491
492     while(!atEnd()){
493         readNext();
494
495         if(isEndElement()) break;
496
497         if(isStartElement()){
498
499             text = readElementText();
500
501             if( name() == "side"){
502                 //kDebug() << "In side: " << text;
503
504                 if( text == "own")
505                     captureSide = GameInfo::OWN;
506                 else if( text == "opponent")
507                     captureSide = GameInfo::OPPONENT;
508                 else if( text =="both")
509                     captureSide = GameInfo::BOTH;
510             }
511             else if( name() == "myside_stone_no"){
512
513                 list = text.split(',');
514
515                 //kDebug() << "Putting to List:";
516                 for( int i = 0 ; i < list.size() ; i++ ){
517                     //kDebug() << list[i].toInt() << " ";
518                     stoneNumbers.append(list[i].toInt());
519                 }
520             }
521
522         }
523     }
524
525     //inserting to m_capture_info
526     m_capture_info.append( qMakePair(captureSide,stoneNumbers) );
527     //kDebug() << "Side:" << m_capture_info[0].first << " stoneNumbers: " << m_capture_info[0].second;
528
529 }
530
531 void GameInfo::parseCountCapture(){
532
533     Q_ASSERT( isStartElement() && name() == "capture_type");
534
535     //kDebug() << "I am in count capture";
536
537     Side captureSide;
538     QString text;
539     QList<int>stoneNumbers;
540     QStringList list;
541
542     while(!atEnd()){
543         readNext();
544
545         if(isEndElement()) break;
546         if(isStartElement()){
547
548             text = readElementText();
549
550             if( name() == "side"){
551                 //kDebug() << "In side: " << text;
552
553                 if( text == "own")
554                     captureSide = GameInfo::OWN;
555                 else if( text == "opponent")
556                     captureSide = GameInfo::OPPONENT;
557                 else if( text =="both")
558                     captureSide = GameInfo::BOTH;
559             }
560             else if( name() == "stones_in_cup"){
561
562                 list = text.split(',');
563
564                 if(list[0] == "number"){
565                     stoneNumbers.append(GameInfo::NUMBER);
566
567                     for(int i = 1 ; i < list.size() ; i++){
568                         //kDebug() << list[i].toInt() << " ";
569                         stoneNumbers.append(list[i].toInt());
570                     }
571                 }
572                 else if(list[0] == "pattern"){
573
574                     stoneNumbers.append(GameInfo::PATTERN);
575
576                     if(list[1] == "even")
577                         stoneNumbers.append(GameInfo::EVEN);
578                     else if(list[1] == "odd")
579                         stoneNumbers.append(GameInfo::ODD);
580                 }
581
582             }
583
584         }
585
586     }
587
588     //(side,countCaptureType(pattern or specific),stone numbers or pattern)
589     m_capture_info.append( qMakePair(captureSide,stoneNumbers) );
590     //kDebug() << "Side:" << m_capture_info[0].first << " stoneNumbers: " << m_capture_info[0].second;
591 }
592
593 void GameInfo::parseSeriesCapture(){
594
595     Q_ASSERT( isStartElement() && name() == "capture_type");
596     //kDebug() << "I am in series capture";
597
598     Side captureSide;
599     QList<int>stoneNumbers;//0-direction,1-grandslam option
600     QString text;
601
602     //kDebug() << "StoneNumbers Now: " << stoneNumbers;
603
604     while(!atEnd()){
605         readNext();
606
607         if(isEndElement()) break;
608         if(isStartElement()){
609
610             text = readElementText();
611
612             if( name() == "side"){
613                 //kDebug() << "In side: " << text;
614
615                 if( text == "own")
616                     captureSide = GameInfo::OWN;
617                 else if( text == "opponent")
618                     captureSide = GameInfo::OPPONENT;
619                 else if( text =="both")
620                     captureSide = GameInfo::BOTH;
621             }
622             else if( name() == "direction"){
623                 if(text == "following") //0
624                     stoneNumbers.append(GameInfo::FOLLOWING);
625                 else if(text == "preceding") //1
626                     stoneNumbers.append(GameInfo::PRECEDING);
627
628             }
629             else if( name() == "grandslam"){
630
631                 if(text == "penalty")
632                     stoneNumbers.append(GameInfo::PENALTY);
633                 else if(text == "capture")
634                     stoneNumbers.append(GameInfo::CAPTURE);
635                 else if(text == "no_capture")
636                     stoneNumbers.append(GameInfo::NO_CAPTURE);
637                 else stoneNumbers.append(GameInfo::INVALID);
638             }
639         }
640
641     }
642     //kDebug() << "stoneNumbers Now:" << stoneNumbers;
643     m_capture_info.append( qMakePair(captureSide,stoneNumbers) );
644     //kDebug() << "Side:" << m_capture_info[1].first << " direction " << m_capture_info[1].second;
645 }
646
647
648 void GameInfo::parsePullAcrossCapture(){
649
650     Q_ASSERT( isStartElement() && name() == "capture_type");
651
652     while(!atEnd()){
653         readNext();
654
655         if(isEndElement()) break;
656
657         if(isStartElement()){
658
659         }
660     }
661
662 }