]> git.sesse.net Git - stockfish/blobdiff - src/main.cpp
Return the entire PV, and in slightly more parseable form.
[stockfish] / src / main.cpp
index 33a8f523da763ba9b8347e51962d0b3f350072ba..4be9aaf3fac5727e1db8833d8acbab4d4929275c 100644 (file)
@@ -39,6 +39,7 @@ using grpc::ServerBuilder;
 using grpc::ServerContext;
 using grpc::Status;
 using grpc::StatusCode;
+using namespace hashprobe;
 
 class HashProbeImpl final : public HashProbe::Service {
 public:
@@ -49,15 +50,54 @@ public:
                if (!pos.pos_is_ok()) {
                        return Status(StatusCode::INVALID_ARGUMENT, "Invalid FEN");
                }
+
+               bool invert = (pos.side_to_move() == BLACK);
+               Search::StateStackPtr setup_states = Search::StateStackPtr(new std::stack<StateInfo>);
+
+               HashProbeLine *root_line = response->add_line();
+               ProbeMove(&pos, setup_states.get(), invert, root_line);
+
+               MoveList<LEGAL> moves(pos);
+               for (const ExtMove* em = moves.begin(); em != moves.end(); ++em) {
+                       HashProbeLine *line = response->add_line();
+                       FillMove(em->move, line->mutable_move());
+                       setup_states->push(StateInfo());
+                       pos.do_move(em->move, setup_states->top(), pos.gives_check(em->move, CheckInfo(pos)));
+                       ProbeMove(&pos, setup_states.get(), !invert, line);
+                       pos.undo_move(em->move);
+               }
+
+               return Status::OK;
+       }
+
+       void FillMove(Move move, HashProbeMove* decoded) {
+               if (!is_ok(move)) return;
+
+               Square from = from_sq(move);
+               Square to = to_sq(move);
+
+               if (type_of(move) == CASTLING) {
+                       to = make_square(to > from ? FILE_G : FILE_C, rank_of(from));
+               }
+                       
+               decoded->set_from_sq(UCI::square(from));
+               decoded->set_to_sq(UCI::square(to));
+
+               if (type_of(move) == PROMOTION) {
+                       decoded->set_promotion(std::string() + " PNBRQK"[promotion_type(move)]);
+               }
+       }
+
+       void ProbeMove(Position* pos, std::stack<StateInfo>* setup_states, bool invert, HashProbeLine* response) {
                bool found;
-               TTEntry *entry = TT.probe(pos.key(), found);
+               TTEntry *entry = TT.probe(pos->key(), found);
                response->set_found(found);
                if (found) {
                        Value value = entry->value();
                        Value eval = entry->eval();
                        Bound bound = entry->bound();
 
-                       if (pos.side_to_move() == BLACK) {
+                       if (invert) {
                                value = -value;
                                eval = -eval;
                                if (bound == BOUND_UPPER) {
@@ -67,13 +107,27 @@ public:
                                }
                        }
 
-                       response->set_move(entry->move());
                        response->set_depth(entry->depth());
                        response->set_eval(eval);
                        response->set_value(value);
-                       response->set_bound(HashProbeResponse::ValueBound(bound));
+                       response->set_bound(HashProbeLine::ValueBound(bound));
+
+                       // Follow the PV until we hit an illegal move.
+                       std::stack<Move> pv;
+                       while (found && is_ok(entry->move())) {
+                               FillMove(entry->move(), response->add_pv());
+                               pv.push(entry->move());
+                               setup_states->push(StateInfo());
+                               pos->do_move(entry->move(), setup_states->top(), pos->gives_check(entry->move(), CheckInfo(*pos)));
+                               entry = TT.probe(pos->key(), found);
+                       }
+
+                       // Unroll the PV back again, so the Position object remains unchanged.
+                       while (!pv.empty()) {
+                               pos->undo_move(pv.top());
+                               pv.pop();
+                       }
                }
-               return Status::OK;
        }
 };