working on distnce calculation + added win detection

This commit is contained in:
Alexandre 2025-05-16 18:38:08 +02:00
parent 172bf4d213
commit 412a74ffe7
20 changed files with 237 additions and 39 deletions

View File

@ -7,8 +7,11 @@ all: bin/back
test: bin/back
bin/back levels/test.txt bots/dumb bots/dumb bots/dumb bots/dumb
ez: bin/back
bin/back levels/simple.txt bots/dumb bots/dumb bots/dumb bots/dumb
mem: bin/back
valgrind --leak-check=full ./bin/back
valgrind --leak-check=full ./bin/back levels/test.txt bots/dumb bots/dumb bots/dumb bots/dumb
bin/back: obj/main.o obj/display.o obj/base.o obj/collisions.o obj/cars.o obj/rooms.o obj/structure.o
mkdir -p bin

BIN
bin/back

Binary file not shown.

View File

@ -1 +1 @@
165 74
137 83

13
levels/simple.txt Normal file
View File

@ -0,0 +1,13 @@
1 3
S1E
$
. = 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,8 +1,8 @@
4
0 (3 0) (45.17 65.83)
1 (4 2) (65.68 34.72)
2 (3 3) (37.74 58.35)
3 (2 0) (19.47 35.72)
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]
5 5
@ -14,7 +14,7 @@
100
200
10
5
0.90
0.80
0.20

View File

@ -15,6 +15,9 @@
#include "cars.h"
#include "base.h"
int* winners;
int remainingTurns;
int currentTurn;
int nPlayers;
carData* players;
@ -22,8 +25,11 @@ carData* players;
void init_all(int nPl) {
nPlayers = nPl;
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].c = init_car(p, nPlayers);
}
@ -36,6 +42,121 @@ void destroy_all() {
free(players);
}
// 1 = N
// 2 = E
// 4 = S
// 8 = W
int return_directions(road r) {
switch (r){
case NONE: return 0;
case START: return 15;
case END: return 15;
case STR_V: return 5;
case STR_H: return 10;
case TURN_NE: return 3;
case TURN_SE: return 6;
case TURN_SW: return 12;
case TURN_NW: return 9;
default: return 0;
}
}
void visit(level* lvl, path* pth, int cx, int cy, 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};
*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(carc%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = -1, .dy = 0};
visit(lvl, pth, cx-1, cy, brk);
}
if((carc/2)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = 1};
visit(lvl, pth, cx, cy+1, brk);
}
if((carc/4)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 1, .dy = 0};
visit(lvl, pth, cx+1, cy, brk);
}
if((carc/8)%2==1 && !(*brk)) {
pth->nxts[cx][cy] = (next){.dx = 0, .dy = -1};
visit(lvl, pth, cx, cy-1, brk);
}
if(!(*brk))pth->nxts[cx][cy] = (next){.dx = 2, .dy = 2};
}
}
}
path* getPath(level* lvl) {
path* res = malloc(sizeof(path));
res->cols = lvl->cols;
res->lines = lvl->lines;
res->start = (pt){.ix = START_CHX, .iy = START_CHY};
res->nxts = malloc(sizeof(next*)*lvl->lines);
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};
}
}
bool brk = false;
visit(lvl, res, START_CHX, START_CHY, &brk);
return res;
}
void printPath(path* pth) {
for(int l = 0; l < pth->lines; l++) {
for(int c = 0; c < pth->cols; c++) {
if(pth->nxts[l][c].dx == -1 && pth->nxts[l][c].dy == -1) {
printf("E");
} else if(pth->nxts[l][c].dx == 1) {
printf("v");
} else if(pth->nxts[l][c].dx == -1) {
printf("^");
} else if(pth->nxts[l][c].dy == 1) {
printf(">");
} else if(pth->nxts[l][c].dy == -1) {
printf("<");
} else {
printf(".");
}
}
printf("\n");
}
printf("\n");
}
void printLvl(level* lvl) {
for(int l = 0; l < lvl->lines; l++) {
for(int c = 0; c < lvl->cols; c++) {
printf("%d", (int)lvl->map[l][c]);
}
printf("\n");
}
printf("\n");
}
void freePath(path* p) {
for(int l = 0; l < p->lines; l++) {
free(p->nxts[l]);
}
free(p->nxts);
free(p);
}
// ------------------------- //
int ln_baseN(int n, int b) {
@ -93,3 +214,5 @@ 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,4 +19,9 @@ ptf normalize(ptf p);
double dot(ptf p1, ptf p2);
ptf add(ptf p1, ptf p2);
path* getPath(level* lvl);
void printPath(path* pth);
void printLvl(level* lvl);
void freePath(path* p);
#endif

View File

@ -53,32 +53,32 @@ void move_on_ENDS(int nPl) {
c->pos.fx += c->vel.fx*DT;
c->pos.fy += c->vel.fy*DT;
if(
(START_DIR != 3 && c->pos.fx-PLAYER_R/2 <= 0.0 && c->vel.fx < 0.0) ||
(START_DIR == 3 && c->pos.fx-PLAYER_R/2 <= 0.0 && c->vel.fx < 0.0 && (c->pos.fy-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE || c->pos.fy+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE)))
(START_DIR != 3 && c->pos.fx-PLAYER_R <= 0.0 && c->vel.fx < 0.0) ||
(START_DIR == 3 && c->pos.fx-PLAYER_R <= 0.0 && c->vel.fx < 0.0 && (c->pos.fy-PLAYER_R <= ROOM_SIZE*DIST_EDGE || c->pos.fy+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE)))
) { // left wall
c->vel.fx *= -1.0;
c->pos.fx += 2.0*c->vel.fx*DT;
c->vel.fx *= RESTITUTION_WALL;
}
if(
(START_DIR != 1 && c->pos.fx+PLAYER_R/2 >= 1.0*ROOM_SIZE && c->vel.fx > 0.0) ||
(START_DIR == 1 && c->pos.fx+PLAYER_R/2 >= 1.0*ROOM_SIZE && c->vel.fx > 0.0 && (c->pos.fy-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE || c->pos.fy+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE)))
(START_DIR != 1 && c->pos.fx+PLAYER_R >= 1.0*ROOM_SIZE && c->vel.fx > 0.0) ||
(START_DIR == 1 && c->pos.fx+PLAYER_R >= 1.0*ROOM_SIZE && c->vel.fx > 0.0 && (c->pos.fy-PLAYER_R <= ROOM_SIZE*DIST_EDGE || c->pos.fy+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE)))
) { // right wall
c->vel.fx *= -1.0;
c->pos.fx += 2.0*c->vel.fx*DT;
c->vel.fx *= RESTITUTION_WALL;
}
if(
(START_DIR != 0 && c->pos.fy-PLAYER_R/2 <= 0.0 && c->vel.fy < 0.0) ||
(START_DIR == 0 && c->pos.fy-PLAYER_R/2 <= 0.0 && c->vel.fy < 0.0 && (c->pos.fx-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE || c->pos.fx+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE)))
(START_DIR != 0 && c->pos.fy-PLAYER_R <= 0.0 && c->vel.fy < 0.0) ||
(START_DIR == 0 && c->pos.fy-PLAYER_R <= 0.0 && c->vel.fy < 0.0 && (c->pos.fx-PLAYER_R <= ROOM_SIZE*DIST_EDGE || c->pos.fx+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE)))
) { // top wall
c->vel.fy *= -1.0;
c->pos.fy += 2.0*c->vel.fy*DT;
c->vel.fy *= RESTITUTION_WALL;
}
if(
(START_DIR != 2 && c->pos.fy+PLAYER_R/2 >= 1.0*ROOM_SIZE && c->vel.fy > 0.0) ||
(START_DIR == 2 && c->pos.fy+PLAYER_R/2 >= 1.0*ROOM_SIZE && c->vel.fy > 0.0 && (c->pos.fx-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE || c->pos.fx+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE)))
(START_DIR != 2 && c->pos.fy+PLAYER_R >= 1.0*ROOM_SIZE && c->vel.fy > 0.0) ||
(START_DIR == 2 && c->pos.fy+PLAYER_R >= 1.0*ROOM_SIZE && c->vel.fy > 0.0 && (c->pos.fx-PLAYER_R <= ROOM_SIZE*DIST_EDGE || c->pos.fx+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE)))
) { // bottom wall
c->vel.fy *= -1.0;
c->pos.fy += 2.0*c->vel.fy*DT;
@ -90,12 +90,12 @@ void move_on_STR_V(int nPl) {
car* c = players[nPl].c;
c->pos.fx += c->vel.fx*DT;
c->pos.fy += c->vel.fy*DT;
if(c->pos.fx-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE && c->vel.fx < 0.0) { // left wall
if(c->pos.fx-PLAYER_R <= ROOM_SIZE*DIST_EDGE && c->vel.fx < 0.0) { // left wall
c->vel.fx *= -1.0;
c->pos.fx += 2.0*c->vel.fx*DT;
c->vel.fx *= RESTITUTION_WALL;
}
if(c->pos.fx+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE) && c->vel.fx > 0.0) { // right wall
if(c->pos.fx+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE) && c->vel.fx > 0.0) { // right wall
c->vel.fx *= -1.0;
c->pos.fx += 2.0*c->vel.fx*DT;
c->vel.fx *= RESTITUTION_WALL;
@ -106,12 +106,12 @@ void move_on_STR_H(int nPl) {
car* c = players[nPl].c;
c->pos.fx += c->vel.fx*DT;
c->pos.fy += c->vel.fy*DT;
if(c->pos.fy-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE && c->vel.fy < 0.0) { // top wall
if(c->pos.fy-PLAYER_R <= ROOM_SIZE*DIST_EDGE && c->vel.fy < 0.0) { // top wall
c->vel.fy *= -1.0;
c->pos.fy += 2.0*c->vel.fy*DT;
c->vel.fy *= RESTITUTION_WALL;
}
if(c->pos.fy+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE) && c->vel.fy > 0.0) { // bottom wall
if(c->pos.fy+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE) && c->vel.fy > 0.0) { // bottom wall
c->vel.fy *= -1.0;
c->pos.fy += 2.0*c->vel.fy*DT;
c->vel.fy *= RESTITUTION_WALL;
@ -129,7 +129,7 @@ void move_on_TURN(int nPl, int cenX, int cenY) {
double nextDist = distance(next, (ptf){.fx = 1.0*cenX, .fy = 1.0*cenY});
// inner circle
if(prevDist-PLAYER_R/2 > ROOM_SIZE*DIST_EDGE && nextDist-PLAYER_R/2 <= ROOM_SIZE*DIST_EDGE) {
if(prevDist-PLAYER_R > ROOM_SIZE*DIST_EDGE && nextDist-PLAYER_R <= ROOM_SIZE*DIST_EDGE) {
ptf to_in = normalize((ptf){
.fx = cenX-prev.fx,
.fy = cenY-prev.fy
@ -142,7 +142,7 @@ void move_on_TURN(int nPl, int cenX, int cenY) {
}
// outer circle
if(prevDist+PLAYER_R/2 < ROOM_SIZE*(1.0-DIST_EDGE) && nextDist+PLAYER_R/2 >= ROOM_SIZE*(1.0-DIST_EDGE)) {
if(prevDist+PLAYER_R < ROOM_SIZE*(1.0-DIST_EDGE) && nextDist+PLAYER_R >= ROOM_SIZE*(1.0-DIST_EDGE)) {
ptf to_out = normalize((ptf){
.fx = prev.fx-cenX,
.fy = prev.fy-cenY
@ -157,12 +157,12 @@ void move_on_TURN(int nPl, int cenX, int cenY) {
void bumpOtherCars(int nPl) {
for(int p = 0; p < nPlayers; p++) {
if(p != nPl) {
if(p != nPl && 0==winners[p]) {
double sep = distance(
get_absolute_coords(p),
get_absolute_coords(nPl)
);
if(sep <= PLAYER_R) {
if(sep <= 2*PLAYER_R) {
// p_total is multiplied by RESTITUTION_PLAYER
ptf director = normalize((ptf){
.fx = players[p].c->pos.fx - players[nPl].c->pos.fx,
@ -254,12 +254,31 @@ bool updateCar(level* lvl, int nPl) {
}
}
void hasWon(int nPl) {
if(0==winners[nPl]) {
car* c = players[nPl].c;
winners[nPl] = ((c->chx == FINISH_CHY && c->chy == FINISH_CHX)?(1):(0));
if(winners[nPl]==1 && remainingTurns == -1) {
remainingTurns = 4;
}
}
}
void updateWins() {
for(int p = 0; p < nPlayers; p++) {
hasWon(p);
}
}
// return true if at least one car moved
bool updateCars(level* lvl) {
bool res = false;
for(int p = 0; p < nPlayers; p++) {
if(0==winners[p]) {
bool rr = updateCar(lvl, p);
res = res || rr;
}
}
return res;
}

View File

@ -2,5 +2,6 @@
#define COLLISIONS_H
bool updateCars(level* lvl);
void updateWins();
#endif

View File

@ -517,7 +517,7 @@ void renderPlayers(SDL_Renderer* renderer, int cx, int cy, int range, int rsize)
//printf("[%d]", p);
int cox = (WIDTH-rsize)/2+rsize*(players[p].c->chx-cy) + (int)((players[p].c->pos.fx*1.0)/ROOM_SIZE*rsize);
int coy = (HEIGHT-rsize)/2+rsize*(players[p].c->chy-cx) + (int)((players[p].c->pos.fy*1.0)/ROOM_SIZE*rsize);
SDL_RenderFillCircle(renderer, cox, coy, PLAYER_R, players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255);
SDL_RenderFillCircle(renderer, cox, coy, PLAYER_R*rsize/ROOM_SIZE, players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255);
} else {
//
}
@ -531,7 +531,7 @@ void renderMap(SDL_Renderer* renderer, level* lvl, int cx, int cy, int range, in
for(int x = -range; x <= range; x++) {
for(int y = -range; y <= range; y++) {
if((cx+x == START_CHX && cy+y == START_CHY) || (cx+x == FINISH_CHX && cy+y == FINISH_CHY)) {
SDL_RenderDrawCircle(renderer, (WIDTH)/2+rsize*(y), (HEIGHT)/2+rsize*(x), (int)(ROOM_SIZE/2.0 + ROOM_SIZE/3.3), 192, 192, 192, 255);
SDL_RenderDrawCircle(renderer, (WIDTH)/2+rsize*(y), (HEIGHT)/2+rsize*(x), (int)(rsize/3.5), 192, 192, 192, 255);
}
}
}

View File

@ -39,11 +39,11 @@ void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* s
break;
case SDLK_d:
*cy = min(lvl->lines-1, *cy+1);
*cy = min(lvl->cols-1, *cy+1);
break;
case SDLK_s:
*cx = min(lvl->cols-1, *cx+1);
*cx = min(lvl->lines-1, *cx+1);
break;
case SDLK_p:
@ -75,10 +75,12 @@ void player_turn(int id, char* exec) {
void parse_all_players(level* lvl, char** execs) {
currentTurn += 1;
for(int p = 0; p < nPlayers; p++) {
if(0==winners[p]) {
write_output("output.txt", lvl, p);
usleep(1000000/10);
player_turn(p, execs[p]);
}
}
}
int main(int argc, char** argv) {
@ -126,6 +128,10 @@ int main(int argc, char** argv) {
//stage_file("levels/stage.txt");
level* stage = parse_level(argv[1]);
init_all(N_PLAYERS);
printf("\n");
path* pth = getPath(stage);
printLvl(stage);
printPath(pth);
printf("Starting direction : ");
if(START_DIR == 0) {
@ -139,9 +145,10 @@ int main(int argc, char** argv) {
} else {
printf("???\n");
}
printf("From (%d %d) to (%d %d)\n", START_CHX, START_CHY, FINISH_CHX, FINISH_CHY);
int cx = 1;
int cy = 2;
int cx = START_CHX;
int cy = START_CHY;
int dezoom = 2;
int sizeR = 200;
while(!halt) {
@ -155,11 +162,12 @@ int main(int argc, char** argv) {
// just selected speeds
for(int p = 0; p < N_PLAYERS; p++) {
pt proj = project(p, cx, cy, dezoom, sizeR);
double nm = sqrt(proj.ix*1.0*proj.ix + proj.iy*1.0*proj.iy);
drawLineWithThicc(rend, 2,
proj.ix,
proj.ix+(int)(players[p].c->vel.fx/5.0),
proj.ix+(int)(players[p].c->vel.fx/5.0*(nm+PLAYER_R)/nm),
proj.iy,
proj.iy+(int)(players[p].c->vel.fy/5.0),
proj.iy+(int)(players[p].c->vel.fy/5.0*(nm+PLAYER_R)/nm),
players[p].rgb.red, players[p].rgb.green, players[p].rgb.blue, 255
);
}
@ -170,10 +178,21 @@ int main(int argc, char** argv) {
} else {
// no movement
placeRectToRenderer(rend, 0, 0, 50, 50, 255, 32, 32, 192);
updateWins();
parse_all_players(stage, execs);
if(remainingTurns >= 0) {
remainingTurns -= 1;
if(remainingTurns == 0) {
halt = true;
}
}
elapsed = 0.0;
}
if(remainingTurns >= 0) {
draw7SegNumberToRenderer(rend, remainingTurns, WIDTH/2, 30, 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);
}
updateRenderer(rend);
elapsed += DT;
usleep((int)(1000000*DT));
@ -184,6 +203,7 @@ int main(int argc, char** argv) {
free_digits(digits);
free_digits(letters);
free_level(stage);
freePath(pth);
for(int k = 0; k < N_PLAYERS; k++) {
free(execs[k]);
}

View File

@ -14,7 +14,7 @@ const double START_EDGE = 0.05;
const double RESTITUTION_WALL = 0.8;
const double RESTITUTION_PLAYER = 0.8; // keep equal to prevouis constant
const int PLAYER_R = 10;
const int PLAYER_R = 5;
const int MAX_THETA_SPAWN = 80; // degrees
const int BARRIERS = 1;

View File

@ -57,6 +57,17 @@ typedef struct carData_t {
color rgb;
} carData;
// meta
typedef struct next_t {int dx; int dy;} next;
// path
typedef struct path_t {
int lines;
int cols;
pt start;
next** nxts;
} path;
// ------------------------------------------------------------------------ //
extern imgs* digits; // SDL data
extern imgs* letters; // SDL data
@ -97,6 +108,9 @@ extern const double EPSILON;
extern const double DELTA_V;
extern const double DELTA_THETA;
extern int* winners;
extern int remainingTurns;
// -------------------------------------------------------------------------------- //
void write_output(char* stream, level* lvl, int nPl);