diff --git a/Makefile b/Makefile index 29cc26f..11146ee 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/answer.txt b/answer.txt new file mode 100644 index 0000000..ddb2ade --- /dev/null +++ b/answer.txt @@ -0,0 +1 @@ +265 80 \ No newline at end of file diff --git a/bin/back b/bin/back index c31e692..9a71ad9 100755 Binary files a/bin/back and b/bin/back differ diff --git a/bots/answer.txt b/bots/answer.txt deleted file mode 100644 index 930b9f7..0000000 --- a/bots/answer.txt +++ /dev/null @@ -1 +0,0 @@ -137 83 \ No newline at end of file diff --git a/bots/dumb b/bots/dumb index fe5f510..0bbf42a 100755 Binary files a/bots/dumb and b/bots/dumb differ diff --git a/bots/dumb.ml b/bots/dumb.ml index 994b657..9557367 100644 --- a/bots/dumb.ml +++ b/bots/dumb.ml @@ -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 \ No newline at end of file diff --git a/bots/dumb.o b/bots/dumb.o index 271c27a..8a79625 100644 Binary files a/bots/dumb.o and b/bots/dumb.o differ diff --git a/levels/straight.txt b/levels/straight.txt new file mode 100644 index 0000000..87ece88 --- /dev/null +++ b/levels/straight.txt @@ -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 \ No newline at end of file diff --git a/levels/turning.txt b/levels/turning.txt new file mode 100644 index 0000000..5f4747f --- /dev/null +++ b/levels/turning.txt @@ -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 \ No newline at end of file diff --git a/obj/base.o b/obj/base.o index 72f341b..8bae35a 100644 Binary files a/obj/base.o and b/obj/base.o differ diff --git a/obj/cars.o b/obj/cars.o index 96596a5..56f51e3 100644 Binary files a/obj/cars.o and b/obj/cars.o differ diff --git a/obj/collisions.o b/obj/collisions.o index f2a2666..1335957 100644 Binary files a/obj/collisions.o and b/obj/collisions.o differ diff --git a/obj/display.o b/obj/display.o index 27a9ced..64ee9bb 100644 Binary files a/obj/display.o and b/obj/display.o differ diff --git a/obj/main.o b/obj/main.o index 3e9032b..aa74258 100644 Binary files a/obj/main.o and b/obj/main.o differ diff --git a/obj/rooms.o b/obj/rooms.o index 3c37f71..56f7553 100644 Binary files a/obj/rooms.o and b/obj/rooms.o differ diff --git a/obj/structure.o b/obj/structure.o index 1f20770..4f5069c 100644 Binary files a/obj/structure.o and b/obj/structure.o differ diff --git a/output.txt b/output.txt index 1dce8f1..8bbca05 100644 --- a/output.txt +++ b/output.txt @@ -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 diff --git a/src/base.c b/src/base.c index dd621e0..e11d73f 100644 --- a/src/base.c +++ b/src/base.c @@ -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(nmaxD-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); } // ------------------------------------------------------------------------------------------------------------------------- // diff --git a/src/display.h b/src/display.h index 727d91a..28956b0 100644 --- a/src/display.h +++ b/src/display.h @@ -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); diff --git a/src/main.c b/src/main.c index 37c958d..c7cddd5 100644 --- a/src/main.c +++ b/src/main.c @@ -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) */ \ No newline at end of file diff --git a/src/structure.c b/src/structure.c index 89eb959..a763d62 100644 --- a/src/structure.c +++ b/src/structure.c @@ -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 // ------------------------------------------------------------------------------------------ // diff --git a/src/structure.h b/src/structure.h index 15fb308..6ad0bf3 100644 --- a/src/structure.h +++ b/src/structure.h @@ -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;