Spaces:
Running on Zero
Running on Zero
File size: 10,838 Bytes
2cf2375 | 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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | #include "StateIndex.h"
#include "Solver.h"
#include "Compressor.h"
#include "Inference.h"
#include <iostream>
#include <fstream>
#include <string>
#include <filesystem>
#include <chrono>
using namespace Bestemshe;
void PrintUsage() {
std::cout << "========================================================\n"
<< " BESTEMSHE HPC ENGINE (God Algorithm / ZSTD Edition) \n"
<< "========================================================\n"
<< "Usage:\n"
<< " ./bestemshe --solve-pair <M> <K1> <K2>\n"
<< " ./bestemshe --verify-pair <M> <K1> <K2>\n"
<< " ./bestemshe --compress <input.raw> <output.bin>\n"
<< " ./bestemshe --decompress <input.bin> <output.raw> <expected_bytes>\n"
<< " ./bestemshe --root\n"
<< "========================================================\n";
}
int main(int argc, char* argv[]) {
StateIndex::InitCombinatorics();
if (argc < 2) {
PrintUsage();
return 1;
}
std::string mode = argv[1];
if (mode == "--solve-pair" && argc == 5) {
uint8_t M = std::stoi(argv[2]);
uint16_t K1 = std::stoi(argv[3]);
uint16_t K2 = std::stoi(argv[4]);
std::cout << "[RUNNING] Solving Pair (" << K1 << "," << K2 << ") in Layer M = " << static_cast<int>(M) << "...\n";
InferenceEngine db;
RetrogradeSolver solver(M, &db);
solver.solve_pair_lock_free(K1, K2);
}
else if (mode == "--verify-pair" && argc == 5) {
uint8_t M = std::stoi(argv[2]);
uint16_t K1 = std::stoi(argv[3]);
uint16_t K2 = std::stoi(argv[4]);
std::cout << "[RUNNING] Verifying Pair (" << K1 << "," << K2 << ") in Layer M = " << static_cast<int>(M) << "...\n";
InferenceEngine db;
RetrogradeSolver solver(M, &db);
solver.verify_pair_consistency(K1, K2);
}
else if (mode == "--compress" && argc == 4) {
std::string in_raw = argv[2];
std::string out_bin = argv[3];
std::cout << "[RUNNING] Compressing " << in_raw << " -> " << out_bin << " (ZSTD L19)...\n";
Compressor::CompressMicroLayer(in_raw, out_bin); // Defaults to 32MB blocks
}
else if (mode == "--decompress" && argc == 5) {
std::string in_bin = argv[2];
std::string out_raw = argv[3];
size_t expected_bytes = std::stoull(argv[4]);
std::cout << "[RUNNING] Decompressing " << in_bin << " -> " << out_raw << "...\n";
// 33554432 bits = 4194304 bytes per block
std::vector<uint8_t> raw = Compressor::DecompressMicroLayer(in_bin, 4194304, expected_bytes);
if (!raw.empty()) {
std::ofstream out(out_raw, std::ios::binary);
out.write(reinterpret_cast<const char*>(raw.data()), raw.size());
std::cout << "[SUCCESS] Decompressed.\n";
}
}
else if (mode == "--root" && argc == 2) {
std::cout << "========================================================\n"
<< " BESTEMSHE GAME-THEORETIC SOLUTION FINDER \n"
<< "========================================================\n";
// Define the exact starting board of Bestemshe
State root;
root.M = 0; root.K_self = 0; root.K_opp = 0;
for (int i = 0; i < 10; ++i) root.board[i] = 5;
uint64_t root_idx = StateIndex::IndexState(root);
InferenceEngine db;
auto t_start = std::chrono::high_resolution_clock::now();
GameValue result = db.query_state(0, 0, root_idx);
auto t_end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> d_query = t_end - t_start;
std::cout << "Result for First Player (Player 1): ";
if (result == GameValue::WIN) std::cout << "\033[1;32mWIN (P1 forces a win)\033[0m\n";
else if (result == GameValue::LOSS) std::cout << "\033[1;31mLOSS (P2 forces a win)\033[0m\n";
else if (result == GameValue::DRAW) std::cout << "\033[1;33mDRAW (Perfect play is a draw)\033[0m\n";
else std::cout << "\033[1;31mUNKNOWN (Error: Layer 0 not fully solved/loaded!)\033[0m\n";
std::cout << "--------------------------------------------------------\n";
std::cout << "Root Query Execution Time: " << d_query.count() << " seconds\n";
std::cout << "========================================================\n";
}else if (mode == "--analyze") {
State s;
// Accept either a custom board, or default to the starting position
if (argc == 14) {
s.K_self = static_cast<uint8_t>(std::stoi(argv[2]));
s.K_opp = static_cast<uint8_t>(std::stoi(argv[3]));
s.M = s.K_self + s.K_opp;
for (int i = 0; i < 10; ++i) s.board[i] = static_cast<uint8_t>(std::stoi(argv[4 + i]));
} else if (argc == 2) {
s.M = 0; s.K_self = 0; s.K_opp = 0;
for (int i = 0; i < 10; ++i) s.board[i] = 5;
} else {
std::cout << "Usage: ./bestemshe --analyze [OR] ./bestemshe --analyze K1 K2 p0..p9\n";
return 1;
}
InferenceEngine db;
int ply = 0;
while (true) {
bool is_p1_turn = (ply % 2 == 0);
std::string current_player = is_p1_turn ? "Player 1 (White)" : "Player 2 (Black)";
// 1. Construct Absolute Board for Fixed Human Perspective
uint8_t abs_board[10];
int abs_k1, abs_k2;
if (is_p1_turn) {
for (int i = 0; i < 10; ++i) abs_board[i] = s.board[i];
abs_k1 = s.K_self;
abs_k2 = s.K_opp;
} else {
for (int i = 0; i < 5; ++i) {
abs_board[i] = s.board[i + 5]; // P1's pits are in 5-9 of canonical state
abs_board[i + 5] = s.board[i]; // P2's pits are in 0-4 of canonical state
}
abs_k1 = s.K_opp;
abs_k2 = s.K_self;
}
std::cout << "\n========================================================\n"
<< " BESTEMSHE ORACLE: PLY " << ply << " | " << current_player << " to move\n"
<< "========================================================\n";
std::cout << " [P2 Kazan (Black): " << abs_k2 << "]\n\n";
std::cout << " (9) (8) (7) (6) (5) <- P2 Pits\n ";
for (int i = 9; i >= 5; --i) printf("[%2d] ", (int)abs_board[i]);
std::cout << "\n\n ";
for (int i = 0; i < 5; ++i) printf("[%2d] ", (int)abs_board[i]);
std::cout << "\n (0) (1) (2) (3) (4) <- P1 Pits\n\n";
std::cout << " [P1 Kazan (White): " << abs_k1 << "]\n";
std::cout << "--------------------------------------------------------\n";
std::cout << "EVALUATING MOVES (1-0 = P1 Wins, 0-1 = P2 Wins)\n";
int start_move = is_p1_turn ? 0 : 5;
int end_move = is_p1_turn ? 4 : 9;
bool has_moves = false;
for (int abs_move = start_move; abs_move <= end_move; ++abs_move) {
int canonical_move = is_p1_turn ? abs_move : (abs_move - 5);
if (s.board[canonical_move] == 0) {
std::cout << "Move " << abs_move << ": INVALID (Empty pit)\n";
continue;
}
has_moves = true;
State next_s;
bool empties;
ExecuteMoveAndFlip(s, canonical_move, next_s, empties);
std::string result_str;
if (empties || next_s.K_opp >= 26) {
if (is_p1_turn) result_str = "\033[1;32m1-0 (P1 forces WIN - Immediate)\033[0m";
else result_str = "\033[1;31m0-1 (P2 forces WIN - Immediate)\033[0m";
} else {
uint64_t next_idx = StateIndex::IndexState(next_s);
GameValue val = db.query_state(next_s.M, next_s.K_opp, next_idx);
if (val == GameValue::DRAW) {
result_str = "\033[1;33m0.5-0.5 (Forced DRAW)\033[0m";
} else if (val == GameValue::UNKNOWN) {
result_str = "\033[1;31mUNKNOWN (Error: Layer missing)\033[0m";
} else {
bool next_player_wins = (val == GameValue::WIN);
bool p1_wins = is_p1_turn ? !next_player_wins : next_player_wins;
if (p1_wins) result_str = "\033[1;32m1-0 (P1 forces WIN)\033[0m";
else result_str = "\033[1;31m0-1 (P2 forces WIN)\033[0m";
}
}
std::cout << "Move " << abs_move << ": " << result_str << "\n";
}
if (!has_moves) {
std::cout << "\n*** No valid moves. Game Over. ***\n";
break;
}
std::cout << "--------------------------------------------------------\n";
int chosen_abs_move = -1;
int chosen_canonical = -1;
while (true) {
std::cout << "Enter move (" << start_move << "-" << end_move << ") or 'q' to quit: ";
std::string input;
if (!(std::cin >> input) || input == "q") {
std::cout << "Exiting Oracle.\n";
return 0;
}
try {
chosen_abs_move = std::stoi(input);
if (chosen_abs_move >= start_move && chosen_abs_move <= end_move) {
chosen_canonical = is_p1_turn ? chosen_abs_move : (chosen_abs_move - 5);
if (s.board[chosen_canonical] > 0) break;
}
} catch (...) {}
std::cout << "Invalid move. Try again.\n";
}
// Execute chosen move and update canonical state
bool empties;
ExecuteMoveAndFlip(s, chosen_canonical, s, empties);
if (empties || s.K_opp >= 26) {
std::cout << "\n========================================================\n";
std::cout << "*** GAME OVER: " << current_player << " Wins! ***\n";
std::cout << "========================================================\n";
break;
}
ply++;
}
}
else {
PrintUsage();
return 1;
}
return 0;
} |