makeWay/src/main.c

304 lines
9.0 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#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 <level_path> <P1 executable> <P2 executable> ...\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)
*/