Format code to tabs

This commit is contained in:
Matúš Púll 2025-07-26 09:31:27 +02:00
parent 4b7fe1fc5f
commit 14a0336886

View file

@ -26,286 +26,288 @@ tile pas(int t) { return (t % 2) ? p1 : p2; }
#define IMG_COUNT 2 #define IMG_COUNT 2
array<Texture2D, IMG_COUNT> textures; array<Texture2D, IMG_COUNT> textures;
void prepareTextures() { void prepareTextures() {
const char* paths[] = {"img/circle.png", "img/cross.png"}; const char* paths[] = {"img/circle.png", "img/cross.png"};
for(int i = 0; i < IMG_COUNT; i++) { for(int i = 0; i < IMG_COUNT; i++) {
Image img; Image img;
img = LoadImage(paths[i]); img = LoadImage(paths[i]);
textures[i] = LoadTextureFromImage(img); textures[i] = LoadTextureFromImage(img);
} }
} }
void renderImage(tile t, Rectangle dst, Color color = WHITE) { void renderImage(tile t, Rectangle dst, Color color = WHITE) {
if(t == fr || t == tie) return; if(t == fr || t == tie) return;
Texture tex = textures[t-1]; Texture tex = textures[t-1];
Rectangle src = {0, 0, (float)tex.width, (float)tex.height}; Rectangle src = {0, 0, (float)tex.width, (float)tex.height};
DrawTexturePro(textures[t-1], src, dst, {0,0}, 0, color); DrawTexturePro(textures[t-1], src, dst, {0,0}, 0, color);
} }
struct pos { struct pos {
int x, y; int x, y;
pos() : x(-1), y(-1) {} pos() : x(-1), y(-1) {}
pos(int px, int py) : x(px), y(py) {} pos(int px, int py) : x(px), y(py) {}
pos(Vector2 v) : x(v.x), y(v.y) {} pos(Vector2 v) : x(v.x), y(v.y) {}
pos normalize() {
if(x >= 3) x = 2; pos operator/(int a) {return {x/a, y/a};};
else if(x < 0) x = 0; pos operator%(int a) {return {x%a, y%a};};
if(y >= 3) y = 2;
else if(y < 0) y = 0; pos normalize() {
return *this; if(x >= 3) x = 2;
} else if(x < 0) x = 0;
pos operator/(int a) {return {x/a, y/a};}; if(y >= 3) y = 2;
pos operator%(int a) {return {x%a, y%a};}; else if(y < 0) y = 0;
int to_int() { return 3*y + x; } return *this;
deque<int> to_deque(int depth, int screenSize) { }
deque<int> r = {}; int to_int() { return 3*y + x; }
pos pp = pos(x,y); deque<int> to_deque(int depth, int screenSize) {
int pwr = 1; deque<int> r = {};
for(int i = 1; i <= depth; i++) { pos pp = pos(x,y);
pwr *= 3; int pwr = 1;
pos ppos = (pp/(screenSize/pwr)); for(int i = 1; i <= depth; i++) {
if(ppos.x > 2 || ppos.y > 2) return {}; pwr *= 3;
r.push_back(ppos.to_int()); pos ppos = (pp/(screenSize/pwr));
pp = pp%(screenSize/pwr); if(ppos.x > 2 || ppos.y > 2) return {};
} r.push_back(ppos.to_int());
return r; pp = pp%(screenSize/pwr);
} }
return r;
}
}; };
#define OKAY -1 #define OKAY -1
#define CHANGE -2 #define CHANGE -2
struct Block { struct Block {
tile t = fr; tile t = fr;
bool leaf = false; bool leaf = false;
Rectangle target; Rectangle target;
array<Block*, 9> sons; array<Block*, 9> sons;
Block() {} Block() {}
Block(int depth, Rectangle trg) { Block(int depth, Rectangle trg) {
target = trg; target = trg;
int x = trg.x, y = trg.y, w = trg.width, h = trg.height; int x = trg.x, y = trg.y, w = trg.width, h = trg.height;
if(depth == 0) leaf = true; if(depth == 0) leaf = true;
else else
for(int i = 0; i < 9; i++) for(int i = 0; i < 9; i++)
sons[i] = new Block(depth-1, sons[i] = new Block(depth-1,
{float(int(x + w/3 * (i%3))), float(int(y + h/3 * (i/3))), float(int(w/3)), float(int(h/3))}); {float(int(x + w/3 * (i%3))), float(int(y + h/3 * (i/3))), float(int(w/3)), float(int(h/3))});
} }
int change(tile pl) { int change(tile pl) {
t = pl; t = pl;
if(pl == fr) if(pl == fr)
return OKAY; return OKAY;
return CHANGE; return CHANGE;
} }
bool playable(deque<int> v) { bool playable(deque<int> v) {
if(leaf && t == fr) return true; if(leaf && t == fr) return true;
if(t != fr || v.size() == 0) return false; if(t != fr || v.size() == 0) return false;
int son = v.front(); int son = v.front();
v.pop_front(); v.pop_front();
return sons[son]->playable(v); return sons[son]->playable(v);
} }
int play(deque<int> v, tile pl) { int play(deque<int> v, tile pl) {
if(t != fr) return v.size(); if(t != fr) return v.size();
if(leaf) return change(pl); if(leaf) return change(pl);
if(v.size() == 0) return OKAY; if(v.size() == 0) return OKAY;
int son = v.front(); int son = v.front();
v.erase(v.begin()); v.erase(v.begin());
int rv = sons[son]->play(v, pl); int rv = sons[son]->play(v, pl);
if(rv == CHANGE) return change(check_win()); if(rv == CHANGE) return change(check_win());
return rv; return rv;
} }
tile check_win() { tile check_win() {
tile d1 = sons[0]->t, d2 = sons[2]->t; tile d1 = sons[0]->t, d2 = sons[2]->t;
for(int k = 0; k < 3; k++) { for(int k = 0; k < 3; k++) {
tile row = sons[k*3]->t, col = sons[k%3]->t; tile row = sons[k*3]->t, col = sons[k%3]->t;
for(int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
if(sons[k*3 + i]->t != row) row = fr; if(sons[k*3 + i]->t != row) row = fr;
if(sons[k%3 + i*3]->t != col) col = fr; if(sons[k%3 + i*3]->t != col) col = fr;
} }
if(row != fr) return row; if(row != fr) return row;
if(col != fr) return col; if(col != fr) return col;
if(sons[k*4]->t != sons[0]->t) d1 = fr; if(sons[k*4]->t != sons[0]->t) d1 = fr;
if(sons[(k+1)*2]->t != sons[2]->t) d2 = fr; if(sons[(k+1)*2]->t != sons[2]->t) d2 = fr;
} }
if(d1 != fr) return d1; if(d1 != fr) return d1;
if(d2 != fr) return d2; if(d2 != fr) return d2;
bool is_tie = true; bool is_tie = true;
for(Block* s : sons) for(Block* s : sons)
if(s->t == fr) is_tie = false; if(s->t == fr) is_tie = false;
if(is_tie) return tie; if(is_tie) return tie;
return fr; return fr;
} }
void render(int depth) { void render(int depth) {
if(!leaf) DrawRectangleLinesEx(target, depth, BLACK); if(!leaf) DrawRectangleLinesEx(target, depth, BLACK);
renderImage(t, target); renderImage(t, target);
if(leaf || (t != fr && t != tie)) return; if(leaf || (t != fr && t != tie)) return;
for(int i = 0; i < 9; i++) for(int i = 0; i < 9; i++)
sons[i]->render(depth-1); sons[i]->render(depth-1);
} }
Rectangle getRect(deque<int> v) { Rectangle getRect(deque<int> v) {
if(v.size() == 0) return target; if(v.size() == 0) return target;
else { else {
int index = v.front(); int index = v.front();
v.pop_front(); v.pop_front();
return sons[index]->getRect(v); return sons[index]->getRect(v);
} }
} }
void updateRect(Rectangle trg) { void updateRect(Rectangle trg) {
target = trg; target = trg;
int x = trg.x, y = trg.y, w = trg.width, h = trg.height; int x = trg.x, y = trg.y, w = trg.width, h = trg.height;
if(leaf) return; if(leaf) return;
for(int i = 0; i < 9; i++) for(int i = 0; i < 9; i++)
sons[i]->updateRect({ sons[i]->updateRect({
float(int(x + w/3 * (i%3))), float(int(x + w/3 * (i%3))),
float(int(y + h/3 * (i/3))), float(int(y + h/3 * (i/3))),
float(int(w/3)), float(int(w/3)),
float(int(h/3)) float(int(h/3))
}); });
} }
void save(vector<tile> *r) { void save(vector<tile> *r) {
if(leaf) r->push_back(t); if(leaf) r->push_back(t);
else else
for(Block* son : sons) for(Block* son : sons)
son->save(r); son->save(r);
} }
void load_state(vector<tile> state, int pos) { void load_state(vector<tile> state, int pos) {
if(leaf) t = state[pos]; if(leaf) t = state[pos];
else { else {
for(int i = 0; i < 9; i++) for(int i = 0; i < 9; i++)
sons[i]->load_state(state, pos*9+i); sons[i]->load_state(state, pos*9+i);
t = check_win(); t = check_win();
} }
} }
void undo(deque<int> &prev) { void undo(deque<int> &prev) {
// TODO // TODO
} }
}; };
void save_state(Block* root, int depth, int time, deque<int> &turn) { void save_state(Block* root, int depth, int time, deque<int> &turn) {
vector<tile> state = {}; vector<tile> state = {};
root->save(&state); root->save(&state);
string filename; std::cin >> filename; string filename; std::cin >> filename;
std::ofstream outfile("saves/" + filename); std::ofstream outfile("saves/" + filename);
outfile << depth << "\n" << time << "\n" << turn.size() << "\n"; outfile << depth << "\n" << time << "\n" << turn.size() << "\n";
for(int play : turn) for(int play : turn)
outfile << play << std::endl; outfile << play << std::endl;
for(tile t : state) for(tile t : state)
outfile << int(t) << std::endl; outfile << int(t) << std::endl;
} }
void load_state(Block** root, deque<int> &turn, int &depth, int &time, char* argv) { void load_state(Block** root, deque<int> &turn, int &depth, int &time, char* argv) {
depth = atoi(argv); depth = atoi(argv);
if(depth) if(depth)
*root = new Block(depth, {0, 0, SCREEN, SCREEN}); *root = new Block(depth, {0, 0, SCREEN, SCREEN});
else { else {
string path = "saves/" + string(argv); string path = "saves/" + string(argv);
std::ifstream infile(path); std::ifstream infile(path);
infile >> depth >> time; infile >> depth >> time;
int K; infile >> K; int K; infile >> K;
for(int k = 0; k < K; k++) { for(int k = 0; k < K; k++) {
int play; infile >> play; int play; infile >> play;
turn.push_back(play); turn.push_back(play);
cout << play; cout << play;
} }
vector<tile> state = {}; vector<tile> state = {};
long long pw = 1; long long pw = 1;
for(int i = 0; i < depth; i++) pw *= 9; for(int i = 0; i < depth; i++) pw *= 9;
for(int i = 0; i < pw; i++) { for(int i = 0; i < pw; i++) {
int next; infile >> next; int next; infile >> next;
state.push_back((tile)next); state.push_back((tile)next);
} }
*root = new Block(depth, {0, 0, SCREEN, SCREEN}); *root = new Block(depth, {0, 0, SCREEN, SCREEN});
(*root)->load_state(state, 0); (*root)->load_state(state, 0);
} }
} }
void update(int &time, deque<int> &turn, Block* root, Rectangle &dst) { void update(int &time, deque<int> &turn, Block* root, Rectangle &dst) {
time++; time++;
turn.erase(turn.begin()); turn.erase(turn.begin());
int rval_2 = root->play(turn, pas(time)); int rval_2 = root->play(turn, pas(time));
for(int i = 0; i <= rval_2; i++) for(int i = 0; i <= rval_2; i++)
turn.pop_back(); turn.pop_back();
dst = root->getRect(turn); dst = root->getRect(turn);
} }
void undo(Block *root, deque<int> &prev, Rectangle &dst, int &time) { void undo(Block *root, deque<int> &prev, Rectangle &dst, int &time) {
if(prev.size() == 0) return; if(prev.size() == 0) return;
time--; time--;
root->undo(prev); root->undo(prev);
// TODO // TODO
} }
bool valid(Block* root, Rectangle &dst, deque<int> &turn) { bool valid(Block* root, Rectangle &dst, deque<int> &turn) {
return CheckCollisionRecs(root->getRect(turn), dst) && root->playable(turn); return CheckCollisionRecs(root->getRect(turn), dst) && root->playable(turn);
} }
void render_all(Block* root, int time, Rectangle dst, int depth, deque<int> highlight = {}) { void render_all(Block* root, int time, Rectangle dst, int depth, deque<int> highlight = {}) {
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
root->render(depth); root->render(depth);
if(valid(root, dst, highlight)) if(valid(root, dst, highlight))
renderImage(act(time), root->getRect(highlight), BLACK); renderImage(act(time), root->getRect(highlight), BLACK);
DrawRectangleLinesEx(dst, 3*LINE_W, act(time+1) == p2 ? BLUE : RED); DrawRectangleLinesEx(dst, 3*LINE_W, act(time+1) == p2 ? BLUE : RED);
EndDrawing(); EndDrawing();
} }
void prepareScreen(Block* root, int time, Rectangle dst, int depth) { void prepareScreen(Block* root, int time, Rectangle dst, int depth) {
SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(SCREEN, SCREEN, "Rekurze"); InitWindow(SCREEN, SCREEN, "Rekurze");
SetTargetFPS(FPS); SetTargetFPS(FPS);
prepareTextures(); prepareTextures();
render_all(root, time, dst, depth); render_all(root, time, dst, depth);
} }
int main(int argc, char** argv) { int main(int argc, char** argv) {
deque<int> turn = {}; deque<int> turn = {};
int time = 0, depth; int time = 0, depth;
Block* root = nullptr; Block* root = nullptr;
int screenSize = SCREEN; int screenSize = SCREEN;
if(argc <= 1) { if(argc <= 1) {
cin >> depth; cin >> depth;
root = new Block(depth, {0, 0, SCREEN, SCREEN}); root = new Block(depth, {0, 0, SCREEN, SCREEN});
} }
else load_state(&root, turn, depth, time, argv[1]); else load_state(&root, turn, depth, time, argv[1]);
Rectangle dst = root->getRect(turn); Rectangle dst = root->getRect(turn);
prepareScreen(root, time, dst, depth); prepareScreen(root, time, dst, depth);
bool end = false; bool end = false;
deque<int> pturn = {}; deque<int> pturn = {};
while(!WindowShouldClose()) { while(!WindowShouldClose()) {
// Update screen size // Update screen size
screenSize = min(GetScreenWidth(), GetScreenHeight()); screenSize = min(GetScreenWidth(), GetScreenHeight());
root->updateRect({0, 0, (float)screenSize, (float)screenSize}); root->updateRect({0, 0, (float)screenSize, (float)screenSize});
dst = root->getRect(pturn); dst = root->getRect(pturn);
// Move // Move
Vector2 touch = GetMousePosition(); Vector2 touch = GetMousePosition();
turn = pos(touch).to_deque(depth, screenSize); turn = pos(touch).to_deque(depth, screenSize);
if(IsMouseButtonPressed(0) && CheckCollisionPointRec(touch, dst) && valid(root, dst, turn)) { if(IsMouseButtonPressed(0) && CheckCollisionPointRec(touch, dst) && valid(root, dst, turn)) {
int rval = root->play(turn, act(time)); int rval = root->play(turn, act(time));
if(rval == CHANGE) end = true; if(rval == CHANGE) end = true;
else if(rval == OKAY) { else if(rval == OKAY) {
update(time, turn, root, dst); update(time, turn, root, dst);
pturn = turn; pturn = turn;
} }
} }
// Key presses // Key presses
if(IsKeyPressed(KEY_X)) save_state(root, depth, time, turn), end = true; if(IsKeyPressed(KEY_X)) save_state(root, depth, time, turn), end = true;
else if(IsKeyPressed(KEY_Z)); //TODO undo else if(IsKeyPressed(KEY_Z)); //TODO undo
else if(IsKeyPressed(KEY_P)) TakeScreenshot("screenshot.png"); else if(IsKeyPressed(KEY_P)) TakeScreenshot("screenshot.png");
// Rendering // Rendering
render_all(root, time, dst, depth, turn); render_all(root, time, dst, depth, turn);
if(end) break; if(end) break;
} }
WaitTime(10); WaitTime(10);
CloseWindow(); CloseWindow();
return 0; return 0;
} }