added progress bars + added random offset to speed and angle

This commit is contained in:
Alexandre 2025-05-17 15:41:25 +02:00
parent 412a74ffe7
commit 3c213a10c9
24 changed files with 244 additions and 46 deletions

View File

@ -10,6 +10,12 @@ test: bin/back
ez: bin/back ez: bin/back
bin/back levels/simple.txt bots/dumb bots/dumb bots/dumb bots/dumb bin/back levels/simple.txt bots/dumb bots/dumb bots/dumb bots/dumb
spin: bin/back
bin/back levels/turning.txt bots/dumb bots/dumb bots/dumb bots/dumb
road: bin/back
bin/back levels/straight.txt bots/dumb bots/dumb bots/dumb bots/dumb
mem: bin/back mem: bin/back
valgrind --leak-check=full ./bin/back levels/test.txt bots/dumb bots/dumb bots/dumb bots/dumb valgrind --leak-check=full ./bin/back levels/test.txt bots/dumb bots/dumb bots/dumb bots/dumb

1
answer.txt Normal file
View File

@ -0,0 +1 @@
265 80

BIN
bin/back

Binary file not shown.

View File

@ -1 +0,0 @@
137 83

BIN
bots/dumb

Binary file not shown.

View File

@ -1,6 +1,6 @@
Random.self_init () ;; Random.self_init () ;;
let ptr = open_out "bots/answer.txt" in let ptr = open_out "answer.txt" in
Printf.fprintf ptr "%d %d" (Random.int 360) (60 + Random.int 40); Printf.fprintf ptr "%d %d" (Random.int 360) (60 + Random.int 40);
close_out ptr close_out ptr

Binary file not shown.

14
levels/straight.txt Normal file
View File

@ -0,0 +1,14 @@
3 10
.S11111114
E........0
2111111115
$
. = NULL
0 = Vertical
1 = Horizontal
2 = TopRight (NE)
3 = BottomRight (SE)
4 = BottomLeft (SW)
5 = TopLeft (NW)
S = Start
E = End

19
levels/turning.txt Normal file
View File

@ -0,0 +1,19 @@
7 8
........
..31S...
..24....
...24...
...353E.
...215..
..........
$
. = NULL
0 = Vertical
1 = Horizontal
2 = TopRight (NE)
3 = BottomRight (SE)
4 = BottomLeft (SW)
5 = TopLeft (NW)
S = Start
E = End

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,9 @@
4 4
0 (2 0) (44.74 79.84) 0 (4 0) (44.83 67.29)
1 (2 0) (22.92 63.60) 1 (2 0) (11.26 93.67)
2 (2 0) (22.92 36.40) 2 (1 3) (95.26 50.45)
3 (2 0) (44.74 20.16) 3 (1 3) (72.77 32.85)
[3] [1]
5 5 5 5
..S14 ..S14

View File

@ -22,15 +22,43 @@ int currentTurn;
int nPlayers; int nPlayers;
carData* players; carData* players;
int RED = 0;
int GREEN = 0;
int BLUE = 0;
color assignColor() {
color res = (color){.red = RED, .green = GREEN, .blue = BLUE};
// increment color like a binary number (exclude (0,0,0) though)
if(RED == 255) {
RED = 0;
if(GREEN == 255) {
GREEN = 0;
BLUE=255-BLUE;
} else {
GREEN = 255;
}
} else {
RED = 255;
}
if(RED == 0 && GREEN == 0 && BLUE == 0) {RED = 255;}
return res;
}
void init_all(int nPl) { void init_all(int nPl) {
nPlayers = nPl; nPlayers = nPl;
RED = 255*(rand()%2);
GREEN = 255*(rand()%2);
BLUE = 255*(rand()%2);
if(RED == 0 && GREEN == 0 && BLUE == 0) {RED = 255;}
currentTurn = 0; currentTurn = 0;
remainingTurns = -1; remainingTurns = -1;
winners = malloc(sizeof(int)*nPlayers); winners = malloc(sizeof(int)*nPlayers);
players = malloc(sizeof(carData)*nPlayers); players = malloc(sizeof(carData)*nPlayers);
for(int p = 0; p < nPlayers; p++) { for(int p = 0; p < nPlayers; p++) {
winners[p] = 0; winners[p] = 0;
players[p].rgb = (color){.red = 255, .green = 255, .blue = 255}; players[p].rgb = assignColor();
players[p].c = init_car(p, nPlayers); players[p].c = init_car(p, nPlayers);
} }
} }
@ -62,38 +90,37 @@ int return_directions(road r) {
} }
} }
void visit(level* lvl, path* pth, int cx, int cy, bool* brk) { void visit(level* lvl, path* pth, int cx, int cy, int depth, bool* brk) {
if(!(*brk) && (cx >= 0 && cy >= 0 && cx < lvl->lines && cy < lvl->cols) && pth->nxts[cx][cy].dx == -2) { if(!(*brk) && (cx >= 0 && cy >= 0 && cx < lvl->lines && cy < lvl->cols) && pth->nxts[cx][cy].dx == -2) {
if(cx == FINISH_CHX && cy == FINISH_CHY) { if(cx == FINISH_CHX && cy == FINISH_CHY) {
pth->nxts[cx][cy] = (next){.dx = -1, .dy = -1}; pth->nxts[cx][cy] = (next){.dx = -1, .dy = -1, .deep = depth};
pth->maxDepth = depth-1;
*brk = true; *brk = true;
//printf("found\n");
} else { } else {
int carc = return_directions(lvl->map[cx][cy]); int carc = return_directions(lvl->map[cx][cy]);
//printf("at (%d %d) [%d%d%d%d]\n", cx, cy, carc%2, (carc/2)%2, (carc/4)%2, (carc/8)%2); if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2, .deep = -1};
if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2};
if(carc%2==1 && !(*brk)) { if(carc%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = -1, .dy = 0}; pth->nxts[cx][cy] = (next){.dx = -1, .dy = 0, .deep = depth};
visit(lvl, pth, cx-1, cy, brk); visit(lvl, pth, cx-1, cy, depth+1, brk);
} }
if((carc/2)%2==1 && !(*brk)) { if((carc/2)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = 1}; pth->nxts[cx][cy] = (next){.dx = 0, .dy = 1, .deep = depth};
visit(lvl, pth, cx, cy+1, brk); visit(lvl, pth, cx, cy+1, depth+1, brk);
} }
if((carc/4)%2==1 && !(*brk)) { if((carc/4)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 1, .dy = 0}; pth->nxts[cx][cy] = (next){.dx = 1, .dy = 0, .deep = depth};
visit(lvl, pth, cx+1, cy, brk); visit(lvl, pth, cx+1, cy, depth+1, brk);
} }
if((carc/8)%2==1 && !(*brk)) { if((carc/8)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = -1}; pth->nxts[cx][cy] = (next){.dx = 0, .dy = -1, .deep = depth};
visit(lvl, pth, cx, cy-1, brk); visit(lvl, pth, cx, cy-1, depth+1, brk);
} }
if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2}; if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2, .deep = -1};
} }
} }
} }
@ -107,12 +134,14 @@ path* getPath(level* lvl) {
for(int l = 0; l < lvl->lines; l++) { for(int l = 0; l < lvl->lines; l++) {
res->nxts[l] = malloc(sizeof(next)*lvl->cols); res->nxts[l] = malloc(sizeof(next)*lvl->cols);
for(int c = 0; c < lvl->cols; c++) { for(int c = 0; c < lvl->cols; c++) {
res->nxts[l][c] = (next){.dx = -2, .dy = -2}; res->nxts[l][c] = (next){.dx = -2, .dy = -2, .deep = -1};
} }
} }
bool brk = false; bool brk = false;
visit(lvl, res, START_CHX, START_CHY, &brk); visit(lvl, res, START_CHX, START_CHY, 0, &brk);
res->maxD = (1+res->maxDepth)*ROOM_SIZE;
res->singleDist = (ROOM_SIZE/res->maxD);
return res; return res;
} }
@ -157,7 +186,97 @@ void freePath(path* p) {
free(p); free(p);
} }
// ------------------------- // // ------------------------------------------------------------------------------------ //
double getRemDistance(level* lvl, path* pth, int nPl) {
car* c = players[nPl].c;
switch (lvl->map[c->chy][c->chx]){
case NONE:
fprintf(stderr, "ERROR : player in NONE chunk (%d at [%d %d])\n", nPl, c->chx, c->chy);
return 0.0;
case START: {
if(START_DIR == 0) { // North (-Y)
return c->pos.fy;
} else if(START_DIR == 1) { // East (+X)
return (ROOM_SIZE-c->pos.fx);
} else if(START_DIR == 2) { // South (+Y)
return (ROOM_SIZE-c->pos.fy);
} else { // West (-X)
return c->pos.fx;
}
break;
}
case END: return 0.0;
case STR_V:{
if(pth->nxts[c->chy][c->chx].dx == -1) { // UP (North)
return c->pos.fy;
} else { // DOWN (South)
return (ROOM_SIZE-c->pos.fy);
}
break;
}
case STR_H:{
if(pth->nxts[c->chy][c->chx].dy == 1) { // RIGHT (East)
return (ROOM_SIZE-c->pos.fx);
} else { // LEFT (West)
return c->pos.fx;
}
break;
}
case TURN_NE:{
if(pth->nxts[c->chy][c->chx].dy == 1) { // RIGHT (East)
return (ROOM_SIZE-c->pos.fx);
} else { // UP (North)
return c->pos.fy;
}
break;
}
case TURN_SE:{
if(pth->nxts[c->chy][c->chx].dy == 1) { // RIGHT (East)
return (ROOM_SIZE-c->pos.fx);
} else { // DOWN (South)
return (ROOM_SIZE-c->pos.fy);
}
break;
}
case TURN_SW:{
if(pth->nxts[c->chy][c->chx].dy == -1) { // LEFT (West)
return c->pos.fx;
} else { // DOWN (South)
return (ROOM_SIZE-c->pos.fy);
}
break;
}
case TURN_NW:{
if(pth->nxts[c->chy][c->chx].dy == -1) { // LEFT (West)
return c->pos.fx;
} else { // UP (North)
return c->pos.fy;
}
break;
}
default: return 0.0;
}
fprintf(stderr, "what ?\n");
return (0.0);
}
double getTotalRemainingDistance(level* lvl, path* pth, int nPl) {
car* c = players[nPl].c;
double localRem = getRemDistance(lvl, pth, nPl);
return (localRem + 1.0*ROOM_SIZE*(max(0,pth->maxDepth-pth->nxts[c->chy][c->chx].deep)));
}
// ------------------------------------------------------------------------------------ //
int ln_baseN(int n, int b) { int ln_baseN(int n, int b) {
if(n<b) { if(n<b) {
@ -214,5 +333,3 @@ double dot(ptf p1, ptf p2) {
ptf add(ptf p1, ptf p2) { ptf add(ptf p1, ptf p2) {
return (ptf){.fx = p1.fx + p2.fx, .fy = p1.fy + p2.fy}; return (ptf){.fx = p1.fx + p2.fx, .fy = p1.fy + p2.fy};
} }
// ------------------------------------------------------------------------------------ //

View File

@ -19,6 +19,8 @@ ptf normalize(ptf p);
double dot(ptf p1, ptf p2); double dot(ptf p1, ptf p2);
ptf add(ptf p1, ptf p2); ptf add(ptf p1, ptf p2);
double getTotalRemainingDistance(level* lvl, path* pth, int nPl);
path* getPath(level* lvl); path* getPath(level* lvl);
void printPath(path* pth); void printPath(path* pth);
void printLvl(level* lvl); void printLvl(level* lvl);

View File

@ -511,6 +511,29 @@ pt project(int p, int cx, int cy, int range, int rsize) {
} }
} }
const int BAR_W = 25;
const int BAR_T = 3;
void renderProgress(SDL_Renderer* renderer, level* lvl, path* pth) {
for(int p = 0; p < nPlayers; p++) {
double remD = getTotalRemainingDistance(lvl, pth, p);
//printf("(%lf out of %lf rem)\n", remD, maxD);
placeRectToRenderer(renderer, 10, BAR_W/8+p*(BAR_W+BAR_W/8), WIDTH-20, BAR_W, players[p].rgb.red/2, players[p].rgb.green/2, players[p].rgb.blue/2, 255);
placeRectToRenderer(renderer, 10+BAR_T, BAR_W/8+p*(BAR_W+BAR_W/8)+BAR_T, WIDTH-20-2*BAR_T, BAR_W-2*BAR_T, 0, 0, 0, 255);
placeRectToRenderer(renderer,
10+BAR_T, BAR_W/8+p*(BAR_W+BAR_W/8)+BAR_T,
(int)(((pth->maxD-remD)/(pth->maxD))*(WIDTH-20-2*BAR_T)), BAR_W-2*BAR_T,
players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255
);
for(int k = 1; k <= pth->maxDepth; k++) {
if(k <= pth->nxts[players[p].c->chy][players[p].c->chx].deep) {
placeRectToRenderer(renderer, 10+BAR_T+(int)(pth->singleDist*k*(WIDTH-20-2*BAR_T))-2, BAR_W/8+p*(BAR_W+BAR_W/8)+BAR_T, 4, BAR_W-2*BAR_T, 0, 0, 0, 255);
} else {
k = pth->maxDepth+1;
}
}
}
}
void renderPlayers(SDL_Renderer* renderer, int cx, int cy, int range, int rsize) { void renderPlayers(SDL_Renderer* renderer, int cx, int cy, int range, int rsize) {
for(int p = 0; p < nPlayers; p++) { for(int p = 0; p < nPlayers; p++) {
if(players[p].c->chx >= cy-range && players[p].c->chx <= cy+range && players[p].c->chy >= cx-range && players[p].c->chy <= cx+range) { if(players[p].c->chx >= cy-range && players[p].c->chx <= cy+range && players[p].c->chy >= cx-range && players[p].c->chy <= cx+range) {
@ -525,7 +548,7 @@ void renderPlayers(SDL_Renderer* renderer, int cx, int cy, int range, int rsize)
//printf("\n"); //printf("\n");
} }
void renderMap(SDL_Renderer* renderer, level* lvl, int cx, int cy, int range, int rsize) { void renderMap(SDL_Renderer* renderer, level* lvl, path* pth, int cx, int cy, int range, int rsize) {
renderCircles(renderer, lvl, cx, cy, range, rsize); renderCircles(renderer, lvl, cx, cy, range, rsize);
renderStraights(renderer, lvl, cx, cy, range, rsize); renderStraights(renderer, lvl, cx, cy, range, rsize);
for(int x = -range; x <= range; x++) { for(int x = -range; x <= range; x++) {
@ -536,6 +559,7 @@ void renderMap(SDL_Renderer* renderer, level* lvl, int cx, int cy, int range, in
} }
} }
renderPlayers(renderer, cx, cy, range, rsize); renderPlayers(renderer, cx, cy, range, rsize);
renderProgress(renderer, lvl, pth);
} }
// ------------------------------------------------------------------------------------------------------------------------- // // ------------------------------------------------------------------------------------------------------------------------- //

View File

@ -18,7 +18,7 @@ void drawCircleToRenderer(SDL_Renderer * renderer, int32_t centreX, int32_t cent
void drawQuarterCircleToRenderer(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius, bool TL, bool TR, bool BL, bool BR, int r, int g, int b, int a); void drawQuarterCircleToRenderer(SDL_Renderer * renderer, int32_t centreX, int32_t centreY, int32_t radius, bool TL, bool TR, bool BL, bool BR, int r, int g, int b, int a);
pt project(int p, int cx, int cy, int range, int rsize); pt project(int p, int cx, int cy, int range, int rsize);
void renderMap(SDL_Renderer* renderer, level* lvl, int cx, int cy, int range, int rsize); void renderMap(SDL_Renderer* renderer, level* lvl, path* pth, int cx, int cy, int range, int rsize);
void import_digits(SDL_Renderer* renderer); void import_digits(SDL_Renderer* renderer);
void import_letters(SDL_Renderer* renderer); void import_letters(SDL_Renderer* renderer);

View File

@ -18,6 +18,8 @@
#include "rooms.h" #include "rooms.h"
#include "cars.h" #include "cars.h"
bool WAIT = true;
void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* sizeR) { void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* sizeR) {
SDL_Event event; SDL_Event event;
while(SDL_PollEvent(&event)) { while(SDL_PollEvent(&event)) {
@ -56,6 +58,10 @@ void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* s
*sizeR = min(WIDTH, HEIGHT)/(2*(*dezoom)+1)+1; *sizeR = min(WIDTH, HEIGHT)/(2*(*dezoom)+1)+1;
break; break;
case SDLK_TAB:
WAIT = !WAIT;
break;
default: default:
break; break;
} }
@ -65,11 +71,14 @@ void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* s
void player_turn(int id, char* exec) { void player_turn(int id, char* exec) {
system(exec); system(exec);
FILE* ptr = fopen("bots/answer.txt", "r"); FILE* ptr = fopen("answer.txt", "r");
int angle, mult; int angle, mult;
fscanf(ptr, "%d %d", &angle, &mult); fscanf(ptr, "%d %d", &angle, &mult);
fclose(ptr); fclose(ptr);
set_speed_car(players[id].c, MAX_SPEED*mult/100.0*cos(angle*3.14159/180.0), MAX_SPEED*mult/100.0*sin(angle*3.14159/180.0)); double dvx = 1.0+(rand()%200-100)/100.0*(DELTA_V/100.0);
double dvy = 1.0+(rand()%200-100)/100.0*(DELTA_V/100.0);
double dtheta = (rand()%200-100)*DELTA_THETA/100.0;
set_speed_car(players[id].c, dvx*MAX_SPEED*(mult)/100.0*cos((angle+dtheta)*3.14159/180.0), dvy*MAX_SPEED*(mult)/100.0*sin((angle+dtheta)*3.14159/180.0));
} }
void parse_all_players(level* lvl, char** execs) { void parse_all_players(level* lvl, char** execs) {
@ -77,7 +86,7 @@ void parse_all_players(level* lvl, char** execs) {
for(int p = 0; p < nPlayers; p++) { for(int p = 0; p < nPlayers; p++) {
if(0==winners[p]) { if(0==winners[p]) {
write_output("output.txt", lvl, p); write_output("output.txt", lvl, p);
usleep(1000000/10); if(WAIT)usleep(1000000/10);
player_turn(p, execs[p]); player_turn(p, execs[p]);
} }
} }
@ -153,7 +162,7 @@ int main(int argc, char** argv) {
int sizeR = 200; int sizeR = 200;
while(!halt) { while(!halt) {
resetRenderer(rend); resetRenderer(rend);
renderMap(rend, stage, cx, cy, dezoom, sizeR); renderMap(rend, stage, pth, cx, cy, dezoom, sizeR);
for(int p = 0; p < N_PLAYERS; p++) { for(int p = 0; p < N_PLAYERS; p++) {
pt proj = project(p, cx, cy, dezoom, sizeR); pt proj = project(p, cx, cy, dezoom, sizeR);
drawStringToRenderer(rend, &(execs[p][1]), proj.ix, proj.iy, 75/(4+dezoom), 105/(4+dezoom)); drawStringToRenderer(rend, &(execs[p][1]), proj.ix, proj.iy, 75/(4+dezoom), 105/(4+dezoom));
@ -171,31 +180,31 @@ int main(int argc, char** argv) {
players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255 players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255
); );
} }
placeRectToRenderer(rend, 0, 0, 50, 50, 255, 255, 32, 192); placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 255, 255, 32, 192);
} else if(updateCars(stage)) { } else if(updateCars(stage)) {
// movement // movement
placeRectToRenderer(rend, 0, 0, 50, 50, 32, 255, 32, 192); placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 32, 255, 32, 192);
} else { } else {
// no movement // no movement
placeRectToRenderer(rend, 0, 0, 50, 50, 255, 32, 32, 192); placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 255, 32, 32, 192);
updateWins(); updateWins();
parse_all_players(stage, execs); if(remainingTurns != 0)parse_all_players(stage, execs);
if(remainingTurns >= 0) { if(remainingTurns > 0) {
remainingTurns -= 1; remainingTurns -= 1;
if(remainingTurns == 0) { if(remainingTurns == 0) {
halt = true; //halt = true;
} }
} }
elapsed = 0.0; elapsed = 0.0;
} }
if(remainingTurns >= 0) { if(remainingTurns >= 0) {
draw7SegNumberToRenderer(rend, remainingTurns, WIDTH/2, 30, 25, 25, 3, 255, 32, 32, 255, 0, 0); draw7SegNumberToRenderer(rend, remainingTurns, WIDTH/2, HEIGHT-75, 25, 25, 3, 255, 32, 32, 255, 0, 0);
} else { } else {
draw7SegNumberToRenderer(rend, currentTurn, WIDTH/2, 30, 25, 25, 3, 255, 255, 255, 255, 0, 0); draw7SegNumberToRenderer(rend, currentTurn, WIDTH/2, HEIGHT-75, 25, 25, 3, 255, 255, 255, 255, 0, 0);
} }
updateRenderer(rend); updateRenderer(rend);
elapsed += DT; elapsed += DT;
usleep((int)(1000000*DT)); if(WAIT)usleep((int)(1000000*(DT/4)));
cameraActions(stage, &halt, &cx, &cy, &dezoom, &sizeR); cameraActions(stage, &halt, &cx, &cy, &dezoom, &sizeR);
} }
@ -215,9 +224,13 @@ int main(int argc, char** argv) {
return 0; return 0;
} }
/* TODO : /*
TODO :
- add level generation - add level generation
- check seg faults - check seg faults
+ add items + add items
+ add hazards + add hazards
KNOWN ISSUES :
- car can sometimes clip into walls (rare, seems turn-related)
*/ */

View File

@ -25,8 +25,8 @@ const double DV = 2.2; // m/s
const double DT = 1.0/100.0; const double DT = 1.0/100.0;
const double EPSILON = 1.0/4096.0; const double EPSILON = 1.0/4096.0;
const double DELTA_V = MAX_SPEED/30; // m/s const double DELTA_V = 7.0; // %
const double DELTA_THETA = 5; // degrees const double DELTA_THETA = 7.0; // degrees
// ------------------------------------------------------------------------------------------ // // ------------------------------------------------------------------------------------------ //

View File

@ -58,13 +58,16 @@ typedef struct carData_t {
} carData; } carData;
// meta // meta
typedef struct next_t {int dx; int dy;} next; typedef struct next_t {int dx; int dy; int deep;} next;
// path // path
typedef struct path_t { typedef struct path_t {
int lines; int lines;
int cols; int cols;
pt start; pt start;
int maxDepth;
double maxD;
double singleDist;
next** nxts; next** nxts;
} path; } path;