#include #include #include #include #include #include #include #include #include #include #include #include #include "structure.h" #include "base.h" #include "music.h" #include "display.h" #include "collisions.h" #include "rooms.h" #include "cars.h" bool WAIT = true; bool SHOW = true; bool matchDone = false; bool noise = true; FILE* save; void cameraActions(level* lvl, bool* halt, int* cx, int* cy, int* dezoom, int* sizeR) { SDL_Event event; while(SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: break; case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_SPACE: *halt = true; break; case SDLK_q: *cy = max(0, *cy-1); break; case SDLK_z: *cx = max(0, *cx-1); break; case SDLK_d: *cy = min(lvl->cols-1, *cy+1); break; case SDLK_s: *cx = min(lvl->lines-1, *cx+1); break; case SDLK_p: *dezoom = max(1, *dezoom-1); *sizeR = min(WIDTH, HEIGHT)/(2*(*dezoom)+1)+1; break; case SDLK_m: *dezoom = min(3, *dezoom+1); *sizeR = min(WIDTH, HEIGHT)/(2*(*dezoom)+1)+1; break; case SDLK_TAB: WAIT = !WAIT; break; case SDLK_LSHIFT: SHOW = !SHOW; break; default: break; } } } } double playerSpeedModifier(int nPl) { // gives players a speed boost/penalty depending on their position // -12% if in the lead, and +12% if last if(maxRemD-minRemD >= 0.0001) { double theta = (remainingD[nPl]-minRemD)/(maxRemD-minRemD); //printf("%lf\n", theta); return (1.0 + (24.0*theta-12.0)/100.0); } else { return 1.0; } } void player_turn(int id, char* exec) { if(noise) { system(exec); FILE* ptr = fopen("answer.txt", "r"); int angle, mult; fscanf(ptr, "%d %d", &angle, &mult); fclose(ptr); 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 psm = playerSpeedModifier(id); double dtheta = (rand()%200-100)*DELTA_THETA/100.0; set_speed_car(players[id].c, psm*dvx*MAX_SPEED*(mult)/100.0*cos((angle+dtheta)*3.14159/180.0), psm*dvy*MAX_SPEED*(mult)/100.0*sin((angle+dtheta)*3.14159/180.0) ); fprintf(save, "%lf %lf\n", psm*dvx*MAX_SPEED*(mult)/100.0*cos((angle+dtheta)*3.14159/180.0), psm*dvy*MAX_SPEED*(mult)/100.0*sin((angle+dtheta)*3.14159/180.0) ); } else { double vx, vy; fscanf(save, "%lf %lf", &vx, &vy); set_speed_car(players[id].c, vx, vy); } } 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); if(WAIT)usleep(1000000/10); player_turn(p, execs[p]); } } } int main(int argc, char** argv) { if(argc < 2) { fprintf(stderr, "usage : ./back ...\n"); exit(1); } int offsetP = 0; if(argv[2][0] == 'R' && argv[2][1] == 'E' && argv[2][2] == 'P' && argv[2][3] == '\0') { // replay mode noise = false; printf("---------------------------\n"); printf("--| Replay mode enabled |--\n"); printf("---------------------------\n"); offsetP = 1; save = fopen("lastActions.txt", "r"); } else { save = fopen("lastActions.txt", "w"); } int N_PLAYERS = argc-2-offsetP; char** execs = malloc(sizeof(char*)*N_PLAYERS); int* ranks = malloc(sizeof(int)*N_PLAYERS); for(int k = 0; k < N_PLAYERS; k++) { ranks[k] = N_PLAYERS; execs[k] = malloc(sizeof(char)*64); execs[k][0] = '.'; execs[k][1] = '/'; int i = 2; while(i-2 < 64 && argv[k+2+offsetP][i-2] != '\0') { execs[k][i] = argv[k+2+offsetP][i-2]; i += 1; } execs[k][i] = '\0'; } for(int k = 0; k < N_PLAYERS; k++) { printf("[%d] %s\n", k, execs[k]); } double elapsed = 0.0; bool halt = false; srand(time(NULL)); if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { printf("error initializing SDL: %s\n", SDL_GetError()); } SDL_Window* win = SDL_CreateWindow("Game", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0); Uint32 render_flags = SDL_RENDERER_ACCELERATED; SDL_Renderer* rend = SDL_CreateRenderer(win, -1, render_flags); SDL_SetRenderDrawBlendMode(rend, SDL_BLENDMODE_BLEND); import_letters(rend); import_digits(rend); init_music(); // ---------------------------- // //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) { printf("North\n"); } else if(START_DIR == 1) { printf("East\n"); } else if(START_DIR == 2) { printf("South\n"); } else if(START_DIR == 3) { printf("West\n"); } else { printf("???\n"); } printf("From (%d %d) to (%d %d)\n", START_CHX, START_CHY, FINISH_CHX, FINISH_CHY); int cx = START_CHX; int cy = START_CHY; int dezoom = 2; int sizeR = 200; int count = 0; while(!halt) { resetRenderer(rend); minRemD = 999999.0; maxRemD = 0.0; renderMap(rend, stage, pth, cx, cy, dezoom, sizeR, SHOW); 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)); } if(elapsed <= 0.7) { // 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*(nm+PLAYER_R)/nm), proj.iy, 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 ); } placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 255, 255, 32, 192); } else if(updateCars(stage)) { // movement placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 32, 255, 32, 192); } else { // no movement placeRectToRenderer(rend, 0, HEIGHT-50, 50, 50, 255, 32, 32, 192); updateWins(ranks); if(remainingTurns != 0)parse_all_players(stage, execs); if(remainingTurns > 0) { remainingTurns -= 1; if(remainingTurns == 0) { matchDone = true; //halt = true; } } elapsed = 0.0; } if(!noise) { drawStringToRenderer(rend, "replay", 10, HEIGHT-75, 75/3, 105/3); } if(remainingTurns >= 0) { draw7SegNumberToRenderer(rend, remainingTurns, WIDTH/2, HEIGHT-75, 25, 25, 3, 255, 32, 32, 255, 0, 0); } else { draw7SegNumberToRenderer(rend, currentTurn, WIDTH/2, HEIGHT-75, 25, 25, 3, 255, 255, 255, 255, 0, 0); } updateRenderer(rend); elapsed += DT; if(WAIT && count%3==0)usleep((int)(1000000*DT)); cameraActions(stage, &halt, &cx, &cy, &dezoom, &sizeR); count += 1; } if(matchDone && noise)updateLeaderBoard(execs, ranks); // ---------------------------- // free_digits(digits); free_digits(letters); free_level(stage); freePath(pth); fclose(save); end_music(); for(int k = 0; k < N_PLAYERS; k++) { free(execs[k]); } free(execs); free(remainingD); free(ranks); SDL_DestroyRenderer(rend); SDL_DestroyWindow(win); SDL_Quit(); return 0; } /* TODO : - add level generation - check seg faults + add items + add hazards KNOWN ISSUES : - car can sometimes clip into walls (rare, seems turn-related) */