#include #include #include #include #include #include #include #include #include "types.h" #include "map.h" #include "game.h" #include "lua_inter.h" MachineDef machine_dict[] = { {{{0,0},{32,0},{0,32},{32,32}}, {}, 0, R_Coal, 4}, // MT_CoalMine {{{0,0},{32,0},{0,32},{32,32}}, {}, 0, R_Iron, 4}, // MT_IronMine {{{0,0},{32,0},{0,32},{32,32}}, {R_Coal, R_Iron}, 2, R_Steel, 0}, // MT_Furnace }; int init_machines(Machines *machines){ machines->machine_n = 0; machines->machine_id = 0; machines->machine_stack = malloc(sizeof(Worker)*W_ALLOC_BLOCK); if(!machines->machine_stack) return 1; return 0; } int init_workers(Workers *workers){ workers->worker_n = 0; workers->worker_stack = malloc(sizeof(Worker)*W_ALLOC_BLOCK); if(!workers->worker_stack) return 1; return 0; } int init_game(Game *game){ int rand_seed = GetTime(); rand_seed &= 0xFFFFFFFF; srand(rand_seed); game->paused = true; game->exit = false; game->ttime = 0; game->camera = (Camera2D){.offset = {0, 0}, .zoom = 1}; int err = init_machines(&game->machines); err |= init_workers(&game->workers); if(err){ printf("Failed to init game. Error : %x\n", err); return 1; } int c_worker = 0; for(int k = 0; k < 16; k++){ for(int j = 0; j < 16; j++){ Machine *coal_mine = add_machine(&game->machines, (V2d){k*250+40,j*400+40}); coal_mine->type = MT_CoalMine; Machine *iron_mine = add_machine(&game->machines, (V2d){k*250+40,j*400+240}); iron_mine->type = MT_IronMine; Machine *furnace = add_machine(&game->machines, (V2d){k*250+140,j*400+140}); furnace->type = MT_Furnace; for(int i = 0; i < 10; i++) add_worker(&game->workers, (V2d){.x=k*250+100,.y=j*400}); for(int i = 0; i < 4; i++) assign_worker_machine(coal_mine, &game->workers.worker_stack[c_worker++]); for(int i = 4; i < 8; i++) assign_worker_machine(iron_mine, &game->workers.worker_stack[c_worker++]); assign_worker_fetch(iron_mine, furnace, &game->workers.worker_stack[c_worker++]); assign_worker_fetch(coal_mine, furnace, &game->workers.worker_stack[c_worker++]); if(!(furnace->id%1000)) printf("%d\n",furnace->id); } } return 0; } void clean_machines(Machines *machines){ free(machines->machine_stack); } void clean_workers(Workers *workers){ free(workers->worker_stack); } void clean_game(Game *game){ clean_machines(&game->machines); clean_workers(&game->workers); clean_map(game); } Worker *add_worker(Workers *workers, V2d pos){ if((workers->worker_n%W_ALLOC_BLOCK)+1 >= W_ALLOC_BLOCK){ void *tmp = realloc(workers->worker_stack, (workers->worker_n+W_ALLOC_BLOCK)*sizeof(Worker)); if(!tmp){ printf("Failed to extend worker stack !\n"); return NULL; } workers->worker_stack = tmp; } Worker *work = &workers->worker_stack[workers->worker_n++]; work->pos = pos; work->ai = (AiInternal){S_Idle, 0, 0, 0, MACH_NULL, MACH_NULL, {.x=0,.y=0}}; return work; } Machine *add_machine(Machines *machines, V2d pos){ if((machines->machine_n%M_ALLOC_BLOCK)+1 >= M_ALLOC_BLOCK){ void *tmp = realloc(machines->machine_stack, (machines->machine_n+W_ALLOC_BLOCK)*sizeof(Machine)); if(!tmp){ printf("Failed to extend machine stack !\n"); return NULL; } machines->machine_stack = tmp; } if(machines->machine_id == MACH_NULL){ printf("Max machines reached !\n"); return NULL; } Machine *mach = &machines->machine_stack[machines->machine_n++]; *mach = (Machine){.pos=pos}; mach->id = machines->machine_id++; return mach; } int id_cmpfunc(const void *a_, const void *b_){ const Machine *a = a_; const Machine *b = b_; return a->id - b->id; } Machine *get_machine_from_id(Machines *machines, uint16_t id){ Machine tmach = {.id = id}; Machine *match = bsearch(&tmach, machines->machine_stack, machines->machine_n, sizeof(Machine), &id_cmpfunc); return match; } int get_machine_localres(Machine *machine, int globalres){ MachineDef *def = &machine_dict[machine->type]; for(int i = 0; i < 4; i++){ if(def->inputs[i] == globalres) return i; } return -1; } Worker *get_worker_from_pos(Workers *workers, V2d pos){ Worker *match = NULL; for(int i = 0; i < workers->worker_n; i++){ Worker *curr = &workers->worker_stack[i]; if(CheckCollisionPointRec(pos, (Rectangle){.x=curr->pos.x,.y=curr->pos.y,.width=32,.height=32})){ match = curr; break; } } return match; } Machine *get_machine_from_pos(Machines *machines, V2d pos){ Machine *match = NULL; for(int i = 0; i < machines->machine_n; i++){ Machine *curr = &machines->machine_stack[i]; if(CheckCollisionPointRec(pos, (Rectangle){.x=curr->pos.x,.y=curr->pos.y,.width=64,.height=64})){ match = curr; break; } } return match; } void update_worker(Game *game, Worker *worker){ AiInternal *ai = &worker->ai; Machine *mach[2] = {0}; //MachineDef *defs[2]; if(ai->assigned_machine != MACH_NULL){ mach[0] = get_machine_from_id(&game->machines, ai->assigned_machine); if(!mach[0]) ai->assigned_machine = MACH_NULL; else{ //defs[0] = &machine_dict[mach[0]->type]; ai->mtype = mach[0]->type; } } if(ai->assigned_machine1 != MACH_NULL){ mach[1] = get_machine_from_id(&game->machines, ai->assigned_machine1); if(!mach[1]) ai->assigned_machine1 = MACH_NULL; /*else defs[1] = &machine_dict[mach[1]->type]; */ } if(ai->assigned_machine == MACH_NULL && ai->assigned_machine1 == MACH_NULL) ai->status = S_Idle; int localres; Vector2 mov; //TODO : Move ! switch(ai->status){ default: case S_Idle: break; case S_Loading: if(!Vector2Equals(worker->pos,mach[0]->pos)){ ai->status = S_Transporting; ai->dest = mach[0]->pos; break; } if(ai->carrying <= 50 && mach[0]->storage[4]){ ai->carrying++; mach[0]->storage[4]--; } else { ai->status = S_Transporting; ai->dest = mach[1]->pos; } break; case S_Unloading: localres = get_machine_localres(mach[1], ai->carry_type); if(localres != (int)ai->carry_type){ ai->status = S_Idle; break; } if(!Vector2Equals(worker->pos, mach[1]->pos)){ ai->status = S_Transporting; ai->dest = mach[1]->pos; break; } if(ai->carrying && mach[1]->storage[localres] <= 200){ ai->carrying--; mach[1]->storage[localres]++; } else{ ai->status = S_Transporting; ai->dest = mach[0]->pos; } break; case S_Operating: worker->pos = mach[0]->pos; break; case S_Transporting: case S_Walking: mov = Vector2Scale( Vector2Normalize(Vector2Subtract(ai->dest, worker->pos)), 2 ); worker->pos = Vector2Add(worker->pos, mov); if(Vector2LengthSqr(Vector2Subtract(mach[0]->pos, worker->pos)) < 0.5){ worker->pos = mach[0]->pos; ai->status = S_Loading; } else if(Vector2LengthSqr(Vector2Subtract(mach[1]->pos, worker->pos)) < 0.5){ worker->pos = mach[1]->pos; ai->status = S_Unloading; } break; } } void update_workers(Game *game){ for(int i = 0; i < game->workers.worker_n; i++){ update_worker(game, &game->workers.worker_stack[i]); } } void update_machine(Game *game, Machine *machine){ MachineDef *def = &machine_dict[machine->type]; bool can_output = machine->assign_workers == def->workers_required; can_output = can_output && (machine->storage[4] <= 200); for(int i = 0; i < def->input_n; i++){ if(!machine->storage[i]) can_output = false; } if(can_output){ for(int i = 0; i < def->input_n; i++){ machine->storage[i]--; } machine->storage[4]++; if(machine->active < 252) machine->active+=4; } else if(machine->active > 1) machine->active-=2; } void update_machines(Game *game){ for(int i = 0; i < game->machines.machine_n; i++){ update_machine(game, &game->machines.machine_stack[i]); } } void update(Game *game){ game->t_per_frame = 0; if(game->paused) return; lua_onframe(game); game->ttime += GetFrameTime(); while(game->ttime > TPS_TIME){ lua_ontick(game); update_machines(game); update_workers(game); game->ttime -= TPS_TIME; game->t_per_frame++; } } int assign_worker_machine(Machine *machine, Worker *worker){ worker->assign_n = machine->assign_workers++; AiInternal *ai = &worker->ai; ai->assigned_machine = machine->id; ai->assigned_machine1 = MACH_NULL; ai->status = S_Operating; worker->pos = machine->pos; return 0; } int assign_worker_fetch(Machine *a, Machine *b, Worker *worker){ AiInternal *ai = &worker->ai; ai->carry_type = machine_dict[a->type].output; ai->assigned_machine = a->id; ai->assigned_machine1 = b->id; ai->status = S_Loading; return 0; }