Normalization: stable textual representation (same as serialize for now)
| 14 | |
| 15 | // Normalization: stable textual representation (same as serialize for now) |
| 16 | std::string normalize_ordering(const MoveType* moves, int num_moves, bool include_scores) { |
| 17 | // Create an index array and sort it deterministically by: |
| 18 | // 1) weight (descending) |
| 19 | // 2) suit (ascending) |
| 20 | // 3) rank (descending) |
| 21 | // 4) sequence (ascending) |
| 22 | std::vector<int> idx(num_moves); |
| 23 | for (int i = 0; i < num_moves; ++i) idx[i] = i; |
| 24 | |
| 25 | auto cmp = [&](int a, int b) { |
| 26 | // higher weight first |
| 27 | if (moves[a].weight != moves[b].weight) return moves[a].weight > moves[b].weight; |
| 28 | if (moves[a].suit != moves[b].suit) return moves[a].suit < moves[b].suit; |
| 29 | if (moves[a].rank != moves[b].rank) return moves[a].rank > moves[b].rank; |
| 30 | return moves[a].sequence < moves[b].sequence; |
| 31 | }; |
| 32 | |
| 33 | // stable sort to preserve original relative order when comparator reports equal |
| 34 | std::stable_sort(idx.begin(), idx.end(), cmp); |
| 35 | |
| 36 | std::ostringstream out; |
| 37 | out << "["; |
| 38 | for (int k = 0; k < num_moves; ++k) { |
| 39 | int i = idx[k]; |
| 40 | if (k) out << ", "; |
| 41 | out << "{"; |
| 42 | out << "\"suit\":" << moves[i].suit << ","; |
| 43 | out << "\"rank\":" << moves[i].rank; |
| 44 | if (include_scores) out << ",\"weight\":" << moves[i].weight; |
| 45 | out << "}"; |
| 46 | } |
| 47 | out << "]"; |
| 48 | return out.str(); |
| 49 | } |
| 50 | |
| 51 | // Initialize relRanks table and TrackType based on a given Pos (used by fuzz tests) |
| 52 | void init_rel_and_track(const Pos& tpos, RelRanksType* rel_table /* size 8192 assumed */, TrackType* track_p, |