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
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.
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.
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/>.
25 #include <QStringList>
26 // #include <kdebug.h>
27 // #include <kstandarddirs.h>
37 void GameInfo::initializeAll(){
39 //making all list empty
41 while(m_capture_info.count())
42 m_capture_info.pop_front();
43 while(m_rotation_cup.count())
44 m_rotation_cup.pop_front();
48 void GameInfo::setGameInfo(QString file){
50 QString fileName = QString("/opt/mancala/data/rules/%1.xml").arg(file);
51 // kDebug() << "The GameInfo File Name: " << fileName;
52 if(fileName.isEmpty()) return;
54 QFile infoFile(fileName);
55 if (!infoFile.open(QFile::ReadOnly | QFile::Text)) return;
56 parseXmlFile(&infoFile);
60 //The parsing operation will be here
61 void GameInfo::parseXmlFile(QIODevice *device){
63 //kDebug() << "Starting of setGameInfo: " ;
75 else raiseError(QObject::tr("This is not the exact file Needed"));
79 //kDebug() << "Region: " << m_region;
80 //kDebug() << "Game Type: " << m_type;
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;
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;
94 // kDebug() << "Capture types: " << m_capture_types;
98 void GameInfo::parseGame(){
100 Q_ASSERT(isStartElement() && name() == "game");
108 if(isStartElement()){
110 if(name() == "type"){
111 QString typeString = readElementText();
112 if(typeString == "modern")
114 else if(typeString == "traditional")
115 m_type = TRADITIONAL;
116 else m_type = CUSTOM;
118 else if( name() == "region")
119 m_region = readElementText();
120 else if( name() == "board")
122 //Other Elements will be here
123 else if(name() == "rules")
126 // kDebug() << "Option that is not still handled";
133 void GameInfo::parseBoard(){
135 //kDebug() << " I am here to parseBoard() ";
136 //kDebug() << "Name is: " << name();
138 Q_ASSERT(isStartElement() && name() == "board");
143 //kDebug() << "Name is: " << name();
146 if(isStartElement()){
148 if(name() == "row_number"){
149 m_num_rows = readElementText().toInt();
152 else if(name() == "cup_per_row"){
153 m_cups_per_row = readElementText().toInt();
156 else if(name() == "kalah_number"){
157 m_num_kalahs = readElementText().toInt();
160 else if(name() == "initial_stone_number"){
161 m_initial_stones_per_cup = readElementText().toInt();
164 // kDebug() << "Option that is not still handled";
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];
177 void GameInfo::parseRules(){
179 Q_ASSERT( isStartElement() && name() == "rules");
184 if(isEndElement()) break;
186 if(isStartElement()){
188 if(name() == "sowing")
190 else if(name() == "capture")
192 else if(name() == "end_rule")
194 else if( name() == "special_rules")
197 // kDebug() << "Option that is not still handled";
204 void GameInfo::parseSowing(){
206 Q_ASSERT( isStartElement() && name() == "sowing");
208 //kDebug() << "I am here to parseSowing()";
210 //kDebug() << "Name is: " << name();
215 //kDebug() << "Name is: " << name();
216 if(isEndElement()) break;
218 if(isStartElement()){
220 if(name() == "rotation"){
222 //kDebug() << "found Rotation";
224 if(attributes().value("id") == "complicated"){
225 //kDebug() << "Attribute value: " << "complicated";
227 else if(attributes().value("id") == "anticlockwise"){
228 //kDebug() << "Attribute value: " << "anticlockwise";
229 m_rotation_type = GameInfo::ANTICLOCKWISE;
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;
241 else if( name() == "lap" ){
243 //kDebug() << "found lap -----------";
244 if(attributes().value("id") == "single"){
245 m_lap_style = GameInfo::SINGLE;
246 //kDebug() << "single Lap";
249 else if(attributes().value("id") == "multiple"){
250 //kDebug() << "lap Style:" << "multiple";
251 m_lap_style = GameInfo::MULTIPLE;
256 else if( name() == "min_stone_to_sow" )
257 m_min_stones_to_sow = readElementText().toInt();
259 else if( name() == "left_stone_to_cup" )
260 m_left_stone_to_cup = readElementText().toInt();
262 else if( name() == "omit_initial_cup" ){
263 if(readElementText() == "yes")
264 m_omit_initial_cup = true;
265 else m_omit_initial_cup = false;
268 else if( name() == "stones_to_kalah"){
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;
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;
284 else if(name() == "bonus_turn"){
286 if(readElementText() == "yes"){
287 //kDebug() << "Bonus Turn True";
290 else m_bonus_turn = false;
298 void GameInfo::parseCapture(){
300 Q_ASSERT(isStartElement() && name() == "capture");
302 //kDebug() << "I am in capture";
306 if(isEndElement()) break;
309 if(isStartElement()){
311 if( name() == "capture_type"){
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;
318 //kDebug() << "Capture types: " << m_capture_types;
320 else if(attributes().value("id") == "count"){
321 m_capture_types |= 2;
324 else if(attributes().value("id") == "series"){
325 m_capture_types |= 4;
326 parseSeriesCapture();
328 else if(attributes().value("id") == "pull_across"){
329 m_capture_types |= 16;
330 parsePullAcrossCapture();
339 void GameInfo::parseSpecialRules(){
341 Q_ASSERT(isStartElement() && name() == "special_rules");
343 //kDebug() << "I am in special rules";
348 if(isEndElement()) break;
351 if(isStartElement()){
353 if( name() == "empty_opponent" ){
354 if( readElementText() == "yes")
355 m_special_flags |= 1;
356 //kDebug() << "empty Opponent:" << (m_special_flags & 1);
358 else if( name() == "turn_passing" ){
359 if(readElementText() == "yes")
360 m_special_flags |= 2;
361 //kDebug() << "Turn Passing:" << (m_special_flags & 2);
363 else if( name() == "compulsory_move" ){
364 if(readElementText() == "yes")
365 m_special_flags |= 4;
366 //kDebug() << "Compulsory Moves:" << (m_special_flags & 4);
371 //kDebug() << "Special_Flags" << (m_special_flags & 1) << " " << (m_special_flags & 2) << " " << (m_special_flags & 4);
376 void GameInfo::parseEndRules(){
381 void GameInfo::parseLap(){
383 Q_ASSERT( isStartElement() && name() == "lap");
388 if(isEndElement()) break;
390 if(isStartElement()){
392 if( name() == "end_of_lap" && attributes().value("id") == "cup"){
393 //kDebug() << "Found cup in end_of_lap";
402 void GameInfo::parseLapEnd(){
404 Q_ASSERT( isStartElement() && name() == "end_of_lap" );
409 if(isEndElement()) break;
411 if(isStartElement()){
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;
418 else if( name() == "side"){
419 QString valueText = readElementText();
420 //kDebug() << "lap end side: " << valueText;
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;
427 m_side_to_end_lap = GameInfo::OPPONENT;
433 //rotation - complicated
434 void GameInfo::parseRotation(){
436 Q_ASSERT( isStartElement() && name() == "rotation" );
441 if(isEndElement()) break;
443 if(isStartElement()){
445 if( name() == "clockwise"){
448 int numCup;// = readElementText().toInt();
450 if(attributes().value("direction") == "left"){
451 numCup = readElementText().toInt();
453 upper = m_cups_per_row -1 ;
454 lower = 2 * m_cups_per_row -1;
456 for(j = 0 ; j < numCup ; ++j,--upper,--lower )
457 m_rotation_cup[upper] = m_rotation_cup[lower] = GameInfo::CLOCKWISE;
462 numCup = readElementText().toInt();
465 lower = m_cups_per_row;
467 for( j = 0 ; j < numCup; ++j,++upper,++lower)
468 m_rotation_cup[upper] = m_rotation_cup[lower] = GameInfo::CLOCKWISE;
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];
481 //capture parsings - CrossCapture
482 void GameInfo::parseCrossCapture(){
484 Q_ASSERT( isStartElement() && name() == "capture_type");
485 //kDebug() << "Now in CrossCapture:" << m_capture_types;
488 QList<int>stoneNumbers;
495 if(isEndElement()) break;
497 if(isStartElement()){
499 text = readElementText();
501 if( name() == "side"){
502 //kDebug() << "In side: " << text;
505 captureSide = GameInfo::OWN;
506 else if( text == "opponent")
507 captureSide = GameInfo::OPPONENT;
508 else if( text =="both")
509 captureSide = GameInfo::BOTH;
511 else if( name() == "myside_stone_no"){
513 list = text.split(',');
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());
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;
531 void GameInfo::parseCountCapture(){
533 Q_ASSERT( isStartElement() && name() == "capture_type");
535 //kDebug() << "I am in count capture";
539 QList<int>stoneNumbers;
545 if(isEndElement()) break;
546 if(isStartElement()){
548 text = readElementText();
550 if( name() == "side"){
551 //kDebug() << "In side: " << text;
554 captureSide = GameInfo::OWN;
555 else if( text == "opponent")
556 captureSide = GameInfo::OPPONENT;
557 else if( text =="both")
558 captureSide = GameInfo::BOTH;
560 else if( name() == "stones_in_cup"){
562 list = text.split(',');
564 if(list[0] == "number"){
565 stoneNumbers.append(GameInfo::NUMBER);
567 for(int i = 1 ; i < list.size() ; i++){
568 //kDebug() << list[i].toInt() << " ";
569 stoneNumbers.append(list[i].toInt());
572 else if(list[0] == "pattern"){
574 stoneNumbers.append(GameInfo::PATTERN);
576 if(list[1] == "even")
577 stoneNumbers.append(GameInfo::EVEN);
578 else if(list[1] == "odd")
579 stoneNumbers.append(GameInfo::ODD);
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;
593 void GameInfo::parseSeriesCapture(){
595 Q_ASSERT( isStartElement() && name() == "capture_type");
596 //kDebug() << "I am in series capture";
599 QList<int>stoneNumbers;//0-direction,1-grandslam option
602 //kDebug() << "StoneNumbers Now: " << stoneNumbers;
607 if(isEndElement()) break;
608 if(isStartElement()){
610 text = readElementText();
612 if( name() == "side"){
613 //kDebug() << "In side: " << text;
616 captureSide = GameInfo::OWN;
617 else if( text == "opponent")
618 captureSide = GameInfo::OPPONENT;
619 else if( text =="both")
620 captureSide = GameInfo::BOTH;
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);
629 else if( name() == "grandslam"){
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);
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;
648 void GameInfo::parsePullAcrossCapture(){
650 Q_ASSERT( isStartElement() && name() == "capture_type");
655 if(isEndElement()) break;
657 if(isStartElement()){