544 lines
13 KiB
C
544 lines
13 KiB
C
#include "main.h"
|
|
#include "team.h"
|
|
#include "tools.h"
|
|
#include "generator.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
// temp code
|
|
t_action purple_update();
|
|
t_action orange_update();
|
|
|
|
t_dude* current_dude;
|
|
|
|
void initWorld(int width, int height){
|
|
int i;
|
|
|
|
// allocations
|
|
printf("Allocating memory...\n");
|
|
teams = malloc(sizeof(t_team)*NB_TEAMS);
|
|
for(i=0; i<NB_TEAMS; i++){
|
|
teams[i].team = i;
|
|
switch(i){
|
|
case ORANGE :
|
|
teams[i].update = orange_update;
|
|
break;
|
|
case PURPLE :
|
|
teams[i].update = purple_update;
|
|
break;
|
|
}
|
|
teams[i].nb_dudes = 0;
|
|
teams[i].dudes = malloc(sizeof(t_dude)*MAX_DUDES);
|
|
teams[i].spawn.x = 0;
|
|
teams[i].spawn.y = 0;
|
|
teams[i].spawn_food = NB_STARTING_FOOD;
|
|
teams[i].spawn_count = 0;
|
|
}
|
|
map = (t_pixel**)malloc(sizeof(t_pixel*)*width);
|
|
for(i=0; i<width; i++)
|
|
map[i] = (t_pixel*)malloc(sizeof(t_pixel)*height);
|
|
|
|
// generate map
|
|
printf("Generating map...\n");
|
|
create_map(width, height);
|
|
|
|
// create image from map
|
|
printf("Creating image from map...\n");
|
|
generateImg(width, height);
|
|
}
|
|
|
|
void updateTeam(t_team team){
|
|
int i;
|
|
|
|
for(i=0; i<team.nb_dudes; i++){
|
|
current_dude = team.dudes + i;
|
|
team.dudes[i].action = team.update();
|
|
if(team.dudes[i].com_data != NULL){
|
|
free(team.dudes[i].com_data);
|
|
team.dudes[i].com_data = NULL;
|
|
}
|
|
}
|
|
|
|
for(i=0; i<team.nb_dudes; i++){
|
|
current_dude = team.dudes + i;
|
|
handleAction(current_dude);
|
|
}
|
|
}
|
|
|
|
t_coord getPos(t_coord coord, int dir){
|
|
switch(dir){
|
|
case NORTH :
|
|
coord.y--;
|
|
break;
|
|
case SOUTH :
|
|
coord.y++;
|
|
break;
|
|
case WEST :
|
|
coord.x++;
|
|
break;
|
|
case EAST :
|
|
coord.x--;
|
|
break;
|
|
}
|
|
return coord;
|
|
}
|
|
|
|
int getNear(int dir){
|
|
t_coord coord = getPos(current_dude->pos, dir);
|
|
return map[coord.x][coord.y].type;
|
|
}
|
|
|
|
int getInfo(int dir){
|
|
t_coord coord = getPos(current_dude->pos, dir);
|
|
t_pixel pixel = map[coord.x][coord.y];
|
|
t_dude* dude;
|
|
int* n;
|
|
switch(pixel.type){
|
|
case DUDE :
|
|
dude = pixel.data;
|
|
return dude->team;
|
|
case FOOD :
|
|
case WOOD :
|
|
case STONE :
|
|
case IRON :
|
|
case SWORD :
|
|
case SPAWN :
|
|
n = pixel.data;
|
|
return *n;
|
|
default :
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int getInventory(){
|
|
return current_dude->inventory;
|
|
}
|
|
|
|
t_com* getComData(){
|
|
return current_dude->com_data;
|
|
}
|
|
|
|
void* getMemory(){
|
|
return current_dude->custom_data;
|
|
}
|
|
|
|
int getSuccess(){
|
|
return current_dude->success;
|
|
}
|
|
|
|
void spawnDudes(){
|
|
int i;
|
|
t_dude new_dude;
|
|
for(i=0; i<NB_TEAMS; i++){
|
|
if(teams[i].spawn_food > 0)
|
|
teams[i].spawn_count++;
|
|
if(teams[i].nb_dudes < MAX_DUDES && teams[i].spawn_count > SPAWN_COOLDOWN && map[teams[i].spawn.x][teams[i].spawn.y].type == SPAWN){
|
|
teams[i].spawn_food--;
|
|
teams[i].spawn_count = 0;
|
|
|
|
new_dude.pos = teams[i].spawn;
|
|
new_dude.team = teams[i].team;
|
|
new_dude.inventory = -1;
|
|
new_dude.success = 1;
|
|
new_dude.dead = 0;
|
|
new_dude.ground = map[teams[i].spawn.x][teams[i].spawn.y];
|
|
new_dude.custom_data = malloc(DUDE_MEMORY);
|
|
memset(new_dude.custom_data, 0, DUDE_MEMORY);
|
|
new_dude.com_data = NULL;
|
|
|
|
teams[i].dudes[teams[i].nb_dudes++] = new_dude;
|
|
}
|
|
}
|
|
}
|
|
|
|
void handleAction(t_dude* dude){
|
|
t_action action = dude->action;
|
|
t_coord target_pos = getPos(dude->pos, action.dir);
|
|
t_pixel target = map[target_pos.x][target_pos.y];
|
|
t_dude* target_dude;
|
|
int* nb_res;
|
|
switch(action.type){
|
|
case MOVE :
|
|
dude->success = 0;
|
|
if( target.type != WALL
|
|
&& target.type != ROCK
|
|
&& target.type != BEDROCK
|
|
&& target.type != IRON_ORE
|
|
&& target.type != TREE
|
|
&& target.type != LIBRARY
|
|
)
|
|
add_move(dude, target_pos);
|
|
break;
|
|
case ATTACK :
|
|
dude->success = 0;
|
|
if( target.type == DUDE
|
|
|| target.type == SPAWN
|
|
|| target.type == WALL
|
|
|| target.type == LIBRARY
|
|
|| target.type == ROAD
|
|
){
|
|
dude->success = 1;
|
|
if(target.type == DUDE)
|
|
add_fight(dude, target_pos);
|
|
else{
|
|
if(target.type == SPAWN){
|
|
nb_res = target.data;
|
|
teams[*nb_res].spawn_food = 0;
|
|
teams[*nb_res].spawn_count = 0;
|
|
}
|
|
if(target.data != NULL)
|
|
free(target.data);
|
|
map[target_pos.x][target_pos.y].type = GRASS;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
}
|
|
}
|
|
break;
|
|
case PICK :
|
|
nb_res = target.data;
|
|
if(target.type >= FOOD && target.type <= SWORD && dude->inventory == -1){
|
|
dude->inventory = target.type;
|
|
(*nb_res)--;
|
|
if(*nb_res < 1){
|
|
free(nb_res);
|
|
map[target_pos.x][target_pos.y].type = GRASS;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
putpixel(img, target_pos.x, target_pos.y, getColor(map[target_pos.x][target_pos.y]));
|
|
}
|
|
dude->success = 1;
|
|
}else
|
|
dude->success = 0;
|
|
break;
|
|
case PUT :
|
|
dude->success = 1;
|
|
if(dude->inventory != -1 && (target.type == GRASS || target.type == MARK || target.type == dude->inventory)){
|
|
if(target.type == GRASS || target.type == MARK){
|
|
map[target_pos.x][target_pos.y].type = dude->inventory;
|
|
nb_res = malloc(sizeof(int));
|
|
*nb_res = 1;
|
|
map[target_pos.x][target_pos.y].data = nb_res;
|
|
}else{
|
|
nb_res = target.data;
|
|
(*nb_res)++;
|
|
}
|
|
dude->inventory = -1;
|
|
putpixel(img, target_pos.x, target_pos.y, getColor(map[target_pos.x][target_pos.y]));
|
|
}else if(target.type == SPAWN && dude->inventory == FOOD){
|
|
dude->inventory = -1;
|
|
nb_res = (int*)target.data;
|
|
teams[*nb_res].spawn_food++;
|
|
}else{
|
|
printf("put failed : trying to put %d in %d\n", dude->inventory, target.type);
|
|
dude->success = 0;
|
|
}
|
|
break;
|
|
case WORK :
|
|
dude->success = 1;
|
|
switch(target.type){
|
|
case ROCK :
|
|
map[target_pos.x][target_pos.y].type = STONE;
|
|
nb_res = malloc(sizeof(int));
|
|
*nb_res = 1;
|
|
map[target_pos.x][target_pos.y].data = nb_res;
|
|
break;
|
|
case BERRIES :
|
|
map[target_pos.x][target_pos.y].type = FOOD;
|
|
nb_res = malloc(sizeof(int));
|
|
*nb_res = 1;
|
|
map[target_pos.x][target_pos.y].data = nb_res;
|
|
break;
|
|
case TREE :
|
|
map[target_pos.x][target_pos.y].type = WOOD;
|
|
nb_res = malloc(sizeof(int));
|
|
*nb_res = 1;
|
|
map[target_pos.x][target_pos.y].data = nb_res;
|
|
break;
|
|
case IRON_ORE :
|
|
map[target_pos.x][target_pos.y].type = IRON;
|
|
nb_res = malloc(sizeof(int));
|
|
*nb_res = 1;
|
|
map[target_pos.x][target_pos.y].data = nb_res;
|
|
break;
|
|
case GRASS :
|
|
map[target_pos.x][target_pos.y].type = MARK;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
break;
|
|
case MARK :
|
|
map[target_pos.x][target_pos.y].type = GRASS;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
break;
|
|
case WOOD :
|
|
nb_res = target.data;
|
|
switch(*nb_res){
|
|
case 1 :
|
|
free(target.data);
|
|
map[target_pos.x][target_pos.y].type = WALL;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
break;
|
|
case 2 :
|
|
free(target.data);
|
|
map[target_pos.x][target_pos.y].type = LIBRARY;
|
|
map[target_pos.x][target_pos.y].data = malloc(128);
|
|
memset(map[target_pos.x][target_pos.y].data, 0, 128);
|
|
default :
|
|
dude->success = 0;
|
|
break;
|
|
}
|
|
break;
|
|
case STONE :
|
|
nb_res = target.data;
|
|
if(*nb_res != 1)
|
|
dude->success = 0;
|
|
else{
|
|
free(target.data);
|
|
map[target_pos.x][target_pos.y].type = ROAD;
|
|
map[target_pos.x][target_pos.y].data = NULL;
|
|
}
|
|
break;
|
|
case IRON :
|
|
nb_res = target.data;
|
|
if(*nb_res != 1)
|
|
dude->success = 0;
|
|
else
|
|
map[target_pos.x][target_pos.y].type = SWORD;
|
|
break;
|
|
default :
|
|
dude->success = 0;
|
|
break;
|
|
}
|
|
if(dude->success)
|
|
putpixel(img, target_pos.x, target_pos.y, getColor(map[target_pos.x][target_pos.y]));
|
|
break;
|
|
case WAIT :
|
|
dude->success = 1;
|
|
break;
|
|
case COMMUNICATE :
|
|
switch(target.type){
|
|
// TODO : conflicts are not handled in a fair way
|
|
case DUDE :
|
|
printf("message to dude\n");
|
|
action.com_data.flag = (action.dir+2)%4;
|
|
target_dude = target.data;
|
|
if(target_dude->com_data == NULL){
|
|
target_dude->com_data = malloc(sizeof(t_com));
|
|
*(target_dude->com_data) = action.com_data;
|
|
dude->success = 1;
|
|
}else
|
|
dude->success = 0;
|
|
break;
|
|
case LIBRARY :
|
|
if(action.com_data.flag & READ){
|
|
if(dude->com_data == NULL){
|
|
action.com_data.flag = action.dir;
|
|
dude->com_data = malloc(sizeof(t_com));
|
|
*(dude->com_data) = action.com_data;
|
|
memcpy(dude->com_data + sizeof(int), target.data + (action.com_data.flag | 3), 32);
|
|
}else{
|
|
dude->success = 0;
|
|
break;
|
|
}
|
|
}else{
|
|
memcpy(target.data + action.com_data.flag, action.com_data.data, 32);
|
|
}
|
|
dude->success = 1;
|
|
break;
|
|
default :
|
|
dude->success = 0;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void generateImg(int width, int height){
|
|
img = SDL_CreateRGBSurface(0, width, height, 32, 0, 0, 0, 0);
|
|
int i, j;
|
|
for(i=0; i<width; i++){
|
|
for(j=0; j<height; j++){
|
|
putpixel(img, i, j, getColor(map[i][j]));
|
|
}
|
|
}
|
|
}
|
|
|
|
SDL_Surface* initSDL(int width, int height, int fullscreen)
|
|
{
|
|
SDL_Surface* screen;
|
|
srand(time(NULL));
|
|
if(fullscreen)
|
|
screen = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN);
|
|
else
|
|
screen = SDL_SetVideoMode(width, height, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
|
|
SDL_WM_SetCaption("Pixel Wars", NULL);
|
|
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
|
|
if (SDL_Init(SDL_INIT_VIDEO) == -1)
|
|
{
|
|
fprintf(stderr, "Erreur d'initialisation de la SDL");// and you don't want my french comment :p
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
return screen;
|
|
}
|
|
|
|
int screen_to_img(int pos_screen, int zoom ,int offset){
|
|
return pos_screen/zoom + offset;
|
|
}
|
|
|
|
void render(SDL_Surface* screen, int x_offset, int y_offset, int zoom_level){
|
|
int i, j, x, y;
|
|
int pos_x,pos_y;
|
|
|
|
pos_x = x_offset - img->w/(2*zoom_level);
|
|
pos_y = y_offset - img->h/(2*zoom_level);
|
|
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
|
|
for(i=0; i<screen->w; i++){
|
|
for(j=0; j<screen->h; j++){
|
|
//new version
|
|
x = screen_to_img(i,zoom_level,pos_x);
|
|
y = screen_to_img(j,zoom_level,pos_y);
|
|
|
|
//old version
|
|
//x = (i - img->w/2 )/zoom_level + x_offset;
|
|
//y = (j - img->h/2 )/zoom_level + y_offset;
|
|
if(x >= 0 && x < img->w && y >= 0 && y < img->h)
|
|
putpixel(screen, i, j, getpixel(img, x, y));
|
|
}
|
|
}
|
|
}
|
|
|
|
int MAIN
|
|
{
|
|
SDL_Surface* screen;
|
|
SDL_Event event;
|
|
int i;
|
|
int paused = 0;
|
|
int x_offset = 0;
|
|
int y_offset = 0;
|
|
int zoom_level = DEFAULT_STARTING_ZOOM;
|
|
int over = 0;
|
|
int time = 0;
|
|
int wait_time = 100;
|
|
int new_time = 0;
|
|
int remaining_time = -1;
|
|
int fullscreen = 0;
|
|
int width = DEFAULT_GAME_WIDTH;
|
|
int height = DEFAULT_GAME_HEIGHT;
|
|
int disp_width = DEFAULT_WINDOW_WIDTH;
|
|
int disp_height = DEFAULT_WINDOW_HEIGHT;
|
|
|
|
#ifndef _WIN32
|
|
argv++;
|
|
while(argc > 1){ // pas initialisé sur windows
|
|
printf("%s\n", argv[0]);
|
|
switch(argv[0][0]){
|
|
case 'f' :
|
|
fullscreen = 1;
|
|
break;
|
|
case 'w' :
|
|
width = atoi(argv[0]+2);
|
|
disp_width = 2*width;
|
|
break;
|
|
case 'h' :
|
|
height = atoi(argv[0]+2);
|
|
disp_height = 2*height;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
argv++;
|
|
argc--;
|
|
}
|
|
#endif
|
|
|
|
screen = initSDL(disp_width, disp_height, fullscreen);
|
|
initWorld(width, height);
|
|
SDL_Flip(img);
|
|
|
|
x_offset = width/2;
|
|
y_offset = height/2;
|
|
|
|
printf("Launching simulation...\n");
|
|
|
|
time = SDL_GetTicks();
|
|
while (!over){
|
|
while(SDL_PollEvent(&event)){
|
|
switch (event.type){
|
|
case SDL_KEYDOWN:
|
|
switch(event.key.keysym.sym) {
|
|
case SDLK_ESCAPE :
|
|
over = 1;
|
|
break;
|
|
case SDLK_z :
|
|
y_offset -= 5;
|
|
break;
|
|
case SDLK_s :
|
|
y_offset += 5;
|
|
break;
|
|
case SDLK_q :
|
|
x_offset -= 5;
|
|
break;
|
|
case SDLK_d :
|
|
x_offset += 5;
|
|
break;
|
|
case SDLK_UP :
|
|
wait_time *= 2;
|
|
break;
|
|
case SDLK_DOWN :
|
|
if(wait_time > 2)
|
|
wait_time /= 2;
|
|
break;
|
|
case SDLK_LEFT :
|
|
zoom_level++;
|
|
break;
|
|
case SDLK_RIGHT :
|
|
zoom_level--;
|
|
if(zoom_level < 1)
|
|
zoom_level = 1;
|
|
break;
|
|
case SDLK_SPACE :
|
|
paused = !paused;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
break;
|
|
case SDL_MOUSEMOTION:
|
|
x_offset += event.motion.xrel;
|
|
y_offset += event.motion.yrel;
|
|
break;
|
|
case SDL_QUIT:
|
|
over = 1;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
/* check x and y offset*/
|
|
if (x_offset < 0) x_offset=0;
|
|
if (x_offset > width) x_offset=width;
|
|
|
|
if (y_offset < 0) y_offset=0;
|
|
if(y_offset > height) y_offset=height;
|
|
|
|
new_time = SDL_GetTicks();
|
|
remaining_time -= new_time - time;
|
|
time = new_time;
|
|
if(remaining_time < 0 && !paused){
|
|
spawnDudes();
|
|
for(i=0; i<NB_TEAMS; i++)
|
|
updateTeam(teams[i]);
|
|
resolve_moves();
|
|
|
|
remaining_time = wait_time;
|
|
}
|
|
|
|
render(screen, x_offset, y_offset, zoom_level);
|
|
|
|
SDL_Delay(30);
|
|
SDL_Flip(screen);
|
|
}
|
|
SDL_FreeSurface(screen);
|
|
SDL_Quit();
|
|
return 0;
|
|
}
|