makeWay/src/structure.c

205 lines
5.6 KiB
C

#include <stdio.h>
#include <stdbool.h>
#include <math.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "structure.h"
const int WIDTH = 1000;
const int HEIGHT = 1000;
const int ROOM_SIZE = 100;
const int MAX_SPEED = 200; // m/s
const double DIST_EDGE = 0.2;
const double START_EDGE = 0.05;
const double RESTITUTION_WALL = 0.8;
const double RESTITUTION_PLAYER = 0.8; // keep equal to previous constant
const int PLAYER_R = 5;
const int MAX_THETA_SPAWN = 80; // degrees
const int BARRIERS = 1;
const double BARRIER_WIDTH = 0.05;
const double FRICTION = 0.90;
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 = 7.0; // %
const double DELTA_THETA = 7.0; // degrees
const double WIND_X = 0.0;
const double WIND_Y = 0.0;
double B = 0.0; // 0.6 works fine
// ------------------------------------------------------------------------------------------ //
void write_output(char* stream, level* lvl, int nPl) {
FILE* ptr = fopen(stream, "w");
fprintf(ptr, "%d\n", nPlayers);
for(int p = 0; p < nPlayers; p++) {
fprintf(ptr, "%d (%d %d) (%.2lf %.2lf)\n", p, players[p].c->chx, players[p].c->chy, players[p].c->pos.fx, players[p].c->pos.fy);
}
fprintf(ptr, "%d\n\n", nPl);
fprintf(ptr, "%d %d\n", lvl->lines, lvl->cols);
for(int l = 0; l < lvl->lines; l++) {
for(int c = 0; c < lvl->cols; c++) {
switch (lvl->map[l][c]){
case NONE:
fprintf(ptr, ".");
break;
case START:
fprintf(ptr, "S");
break;
case END:
fprintf(ptr, "E");
break;
default:
fprintf(ptr, "%d", (int)lvl->map[l][c]-3);
break;
}
}
fprintf(ptr, "\n");
}
fprintf(ptr, "\n");
fprintf(ptr, "%d %d %d %.2lf %.2lf %.2lf %.2lf\n", ROOM_SIZE, MAX_SPEED, PLAYER_R, FRICTION, RESTITUTION_WALL, DIST_EDGE, B);
fprintf(ptr, "\nRoom Size, Maximum speed, Player Radius, Friction, Restitution factor, Track Distance to Edge, Magnetic Field");
fclose(ptr);
}
// ------------------------- //
bool str_equal(char* s1, char* s2) {
if(s1[0] == '\0' || s2[0] == '\0') {
return (s1[0] == '\0' && s2[0] == '\0');
} else if(s1[0] != s2[0]) {
return false;
}
return str_equal(&s1[1], &s2[1]);
}
int* get_elo_diffs(char** execs) {
FILE* ptr = fopen("leaderboard.txt", "r");
int* elos = malloc(sizeof(int)*nPlayers);
for(int p = 0; p < nPlayers; p++) {
elos[p] = 500;
}
// ignore first line
char c = fgetc(ptr);
while(c != EOF && c != '\n') {
c = fgetc(ptr);
}
char* name = malloc(sizeof(char)*64);
int elo;
int scanres = fscanf(ptr, "%s %d", name, &elo);
while(scanres > 0) {
for(int p = 0; p < nPlayers; p++) {
if(str_equal(name, execs[p])) {
elos[p] = elo;
}
}
scanres = fscanf(ptr, "%s %d", name, &elo);
}
fclose(ptr);
free(name);
int* diffs = malloc(sizeof(int)*nPlayers);
for(int p = 0; p < nPlayers; p++) {
diffs[p] = 0;
for(int q = 0; q < nPlayers; q++) {
if(p != q) {
diffs[p] += elos[q] - elos[p];
}
}
diffs[p] = diffs[p]/(nPlayers-1+((nPlayers==1)?(1):(0)));
}
free(elos);
return diffs;
}
int smax(int a, int b) {return (a>b)?(a):(b);}
int smin(int a, int b) {return (a<b)?(a):(b);}
double fsmax(double a, double b) {return (a>b)?(a):(b);}
double fsmin(double a, double b) {return (a<b)?(a):(b);}
// +20 for #1 no matter what
// up to -70 (past 2500) for last
// if diff < -250, no bonus
// if diff > 250, 2x bonus
int gains(int elo, int rank, int diff) {
return 5+(int)(
(fsmax(0.1, fsmin(2.0, (diff+250.0)/250.0)))*20-
(smax(40,smin(90, (90*elo)/1900)))*
(((rank-1)*1.0)/((nPlayers-1+((nPlayers==1)?(1):(0)))*1.0))
);
}
void updateLeaderBoard(char** execs, int* ranks) {
FILE* ptr = fopen("leaderboard.txt", "r");
FILE* ptrOut = fopen("tempLeader.txt", "w");
// ignore first line
char c = fgetc(ptr);
while(c != EOF && c != '\n') {
fprintf(ptrOut, "%c", c);
c = fgetc(ptr);
}
fprintf(ptrOut, "\n");
int* diffs = get_elo_diffs(execs);
bool* found = malloc(sizeof(bool)*nPlayers);
char* entry = malloc(sizeof(char)*64);
int elo;
int res = fscanf(ptr, "%s %d", entry, &elo);
while(res > 0) {
for(int p = 0; p < nPlayers; p++) {
if(!found[p] && str_equal(execs[p], entry)) {
found[p] = true;
printf("[%s - rank %d/%d] : %d -", execs[p], ranks[p], nPlayers, elo);
int de = gains(elo, ranks[p], diffs[p]);
printf("(%d)-> ", de);
elo += de;
printf("%d\n", elo);
}
}
fprintf(ptrOut, "%s %d\n", entry, elo);
res = fscanf(ptr, "%s %d\n", entry, &elo);
}
fclose(ptr);
fclose(ptrOut);
// copy data to main file
FILE* tempRead = fopen("tempLeader.txt", "r");
FILE* mainWrite = fopen("leaderboard.txt", "w");
c = fgetc(tempRead);
while(c != EOF) {
fprintf(mainWrite, "%c", c);
c = fgetc(tempRead);
}
for(int k = 0; k < nPlayers; k++) {
if(!found[k]) {
fprintf(mainWrite, "%s %d\n", execs[k], 500+gains(500, ranks[k], diffs[k]));
}
}
fclose(tempRead);
fclose(mainWrite);
free(entry);
free(found);
free(diffs);
}