aboutsummaryrefslogtreecommitdiff
path: root/src/Openings.cpp
blob: 02a0ba5d228aed03faec9637ee666ce0ba3b7785 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "Openings.hpp"
#include <sstream>

/**
 * @brief Count the number of similar moves in between two lines
 * 
 * @param m1 
 * @param m2 
 * @return int 
 */
inline int CompareMainlines(const pgnp::HalfMove *m1,const  pgnp::HalfMove *m2){
    int count=0;
    const pgnp::HalfMove *n1=m1;
    const pgnp::HalfMove *n2=m2;
    while(n1 && n2 != nullptr){
        if(n1->move == n2->move)
            count++;
        else
            break;
        n1=n1->MainLine;
        n2=n2->MainLine;
    }
    return count;
}

Openings::Openings() {
    std::string tsv(a_tsv);
    LoadVolume(tsv,&A);
    tsv=std::string(b_tsv);
    LoadVolume(tsv,&B);
    tsv=std::string(c_tsv);
    LoadVolume(tsv,&C);
    tsv=std::string(d_tsv);
    LoadVolume(tsv,&D);
    tsv=std::string(e_tsv);
    LoadVolume(tsv,&E);
}

void Openings::SearchOpening(const pgnp::HalfMove *moves,std::string &name, std::string &eco){
    // Now goto the right volume
    std::vector<Volume*> vols={&A,&B,&C,&D,&E};
    if(moves->GetLength()>=2){
        if(moves->move == "e4"){
            if(moves->MainLine->move == "e6"|| moves->MainLine->move == "e5")
                vols={&C};
            else
                vols={&B};
        }
        // TODO: Improve volumes filtering
    }
    // Then search for opening name:
    int matches=0;
    for(Volume *v: vols){
        for(auto &entry: *v){
            std::string &eco_=std::get<0>(entry);
            std::string &name_=std::get<1>(entry);
            std::string &pgn_=std::get<2>(entry);
            pgnp::HalfMove *moves_=new pgnp::HalfMove();
            pgnp::ParseSANMoves(pgn_,moves_);
            int nmatches=CompareMainlines(moves,moves_);
            if(nmatches>matches && nmatches == moves_->GetLength()){
                name=name_;
                eco=eco_;
                matches=nmatches;
                if(moves->GetLength()==moves_->GetLength()){
                    delete moves_;
                    return;
                }
            }
            delete moves_;
        }
    }
}

void Openings::GuessOpening(const std::string &SANMoves, std::string &name, std::string &eco){
    pgnp::HalfMove *m=new pgnp::HalfMove();
    pgnp::ParseSANMoves(SANMoves,m);
    SearchOpening(m,name,eco);
    delete m;
}

void Openings::GuessOpening(const pgnp::HalfMove *moves, std::string &name, std::string &eco){
    SearchOpening(moves,name,eco);
}

void Openings::LoadVolume(const std::string &tsv, Volume *vol){
    std::istringstream f(tsv);
    std::string line;    
    while (std::getline(f, line)) {
        int eco=-1,name=-1,pgn=-1;
        for(int i=0;i<line.size();i++){
            if(line[i]=='\t'){
                if(eco == -1)
                    eco=i-1;
                else if(name==-1)
                    name=i-1;
                else
                    pgn=i;
            }
        }
        vol->push_back(std::make_tuple(
        line.substr(0,eco+1),
        line.substr(eco+2,name-eco-1),
        line.substr(name+2,pgn-name)));
    }
}