| 555 | } |
| 556 | |
| 557 | size_t RenlibReader::processNode(Board &board, |
| 558 | Rule rule, |
| 559 | const LibNode *node, |
| 560 | std::function<CallbackFunc> &callback) |
| 561 | { |
| 562 | size_t nodeCount = 0; |
| 563 | LibNode siblingNode; |
| 564 | |
| 565 | do { |
| 566 | bool ignoreChildren = false; |
| 567 | if (node->move == Pos::PASS) { |
| 568 | if (board.passMoveCount() >= board.cellCount()) |
| 569 | throw std::runtime_error("too many pass move"); |
| 570 | board.move(rule, Pos::PASS); |
| 571 | } |
| 572 | else if (board.isInBoard(node->move)) { |
| 573 | if (board.isEmpty(node->move)) { |
| 574 | board.move(rule, node->move); |
| 575 | |
| 576 | // Call callback function for this node |
| 577 | if (callback) |
| 578 | callback(board, |
| 579 | node->hasTag(), |
| 580 | node->hasText() ? &node->text : nullptr, |
| 581 | node->hasComment() ? &node->comment : nullptr); |
| 582 | } |
| 583 | else { |
| 584 | // Ignore this invalid branch |
| 585 | ignoreChildren = true; |
| 586 | } |
| 587 | } |
| 588 | else |
| 589 | throw std::runtime_error("invalid move in lib"); |
| 590 | |
| 591 | // Recursive process all child nodes |
| 592 | if (node->hasChild()) { |
| 593 | if (hasNextNode()) { |
| 594 | LibNode childNode = readNode(); |
| 595 | nodeCount++; |
| 596 | |
| 597 | if (ignoreChildren) { |
| 598 | std::function<CallbackFunc> emptyCallback; |
| 599 | nodeCount += processNode(board, rule, &childNode, emptyCallback); |
| 600 | } |
| 601 | else |
| 602 | nodeCount += processNode(board, rule, &childNode, callback); |
| 603 | } |
| 604 | else |
| 605 | throw std::runtime_error("no left child node in lib"); |
| 606 | } |
| 607 | |
| 608 | // Undo the move |
| 609 | if (!ignoreChildren) |
| 610 | board.undo(rule); |
| 611 | |
| 612 | // Process next sibling node |
| 613 | if (node->hasSibling()) { |
| 614 | if (hasNextNode()) { |
nothing calls this directly
no test coverage detected