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
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
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 () ;;
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);
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
0 (2 0) (44.74 79.84)
1 (2 0) (22.92 63.60)
2 (2 0) (22.92 36.40)
3 (2 0) (44.74 20.16)
[3]
0 (4 0) (44.83 67.29)
1 (2 0) (11.26 93.67)
2 (1 3) (95.26 50.45)
3 (1 3) (72.77 32.85)
[1]
5 5
..S14

View File

@ -22,15 +22,43 @@ int currentTurn;
int nPlayers;
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) {
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;
remainingTurns = -1;
winners = malloc(sizeof(int)*nPlayers);
players = malloc(sizeof(carData)*nPlayers);
for(int p = 0; p < nPlayers; p++) {
winners[p] = 0;
players[p].rgb = (color){.red = 255, .green = 255, .blue = 255};
players[p].rgb = assignColor();
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(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;
//printf("found\n");
} else {
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};
if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2, .deep = -1};
if(carc%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = -1, .dy = 0};
visit(lvl, pth, cx-1, cy, brk);
pth->nxts[cx][cy] = (next){.dx = -1, .dy = 0, .deep = depth};
visit(lvl, pth, cx-1, cy, depth+1, brk);
}
if((carc/2)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = 1};
visit(lvl, pth, cx, cy+1, brk);
pth->nxts[cx][cy] = (next){.dx = 0, .dy = 1, .deep = depth};
visit(lvl, pth, cx, cy+1, depth+1, brk);
}
if((carc/4)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 1, .dy = 0};
visit(lvl, pth, cx+1, cy, brk);
pth->nxts[cx][cy] = (next){.dx = 1, .dy = 0, .deep = depth};
visit(lvl, pth, cx+1, cy, depth+1, brk);
}
if((carc/8)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = -1};
visit(lvl, pth, cx, cy-1, brk);
pth->nxts[cx][cy] = (next){.dx = 0, .dy = -1, .deep = depth};
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++) {
res->nxts[l] = malloc(sizeof(next)*lvl->cols);
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;
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;
}
@ -157,7 +186,97 @@ void freePath(path* 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) {
if(n<b) {
@ -214,5 +333,3 @@ double dot(ptf p1, ptf p2) {
ptf add(ptf p1, ptf p2) {
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);
ptf add(ptf p1, ptf p2);
double getTotalRemainingDistance(level* lvl, path* pth, int nPl);
path* getPath(level* lvl);
void printPath(path* pth);
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) {
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) {
@ -525,7 +548,7 @@ void renderPlayers(SDL_Renderer* renderer, int cx, int cy, int range, int rsize)
//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);
renderStraights(renderer, lvl, cx, cy, range, rsize);
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);
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);
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_letters(SDL_Renderer* renderer);

View File

@ -18,6 +18,8 @@
#include "rooms.h"
#include "cars.h"
bool WAIT = true;
void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* sizeR) {
SDL_Event 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;
break;
case SDLK_TAB:
WAIT = !WAIT;
break;
default:
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) {
system(exec);
FILE* ptr = fopen("bots/answer.txt", "r");
FILE* ptr = fopen("answer.txt", "r");
int angle, mult;
fscanf(ptr, "%d %d", &angle, &mult);
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) {
@ -77,7 +86,7 @@ void parse_all_players(level* lvl, char** execs) {
for(int p = 0; p < nPlayers; p++) {
if(0==winners[p]) {
write_output("output.txt", lvl, p);
usleep(1000000/10);
if(WAIT)usleep(1000000/10);
player_turn(p, execs[p]);
}
}
@ -153,7 +162,7 @@ int main(int argc, char** argv) {
int sizeR = 200;
while(!halt) {
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++) {
pt proj = project(p, cx, cy, dezoom, sizeR);
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
);
}
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)) {
// movement
placeRectToRenderer(rend, 0, 0, 50, 50, 32, 255, 32, 192);
placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 32, 255, 32, 192);
} else {
// no movement
placeRectToRenderer(rend, 0, 0, 50, 50, 255, 32, 32, 192);
placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 255, 32, 32, 192);
updateWins();
parse_all_players(stage, execs);
if(remainingTurns >= 0) {
if(remainingTurns != 0)parse_all_players(stage, execs);
if(remainingTurns > 0) {
remainingTurns -= 1;
if(remainingTurns == 0) {
halt = true;
//halt = true;
}
}
elapsed = 0.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 {
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);
elapsed += DT;
usleep((int)(1000000*DT));
if(WAIT)usleep((int)(1000000*(DT/4)));
cameraActions(stage, &halt, &cx, &cy, &dezoom, &sizeR);
}
@ -215,9 +224,13 @@ int main(int argc, char** argv) {
return 0;
}
/* TODO :
/*
TODO :
- add level generation
- check seg faults
+ add items
+ 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 EPSILON = 1.0/4096.0;
const double DELTA_V = MAX_SPEED/30; // m/s
const double DELTA_THETA = 5; // degrees
const double DELTA_V = 7.0; // %
const double DELTA_THETA = 7.0; // degrees
// ------------------------------------------------------------------------------------------ //

View File

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