357 lines
9.1 KiB
C
357 lines
9.1 KiB
C
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
|
|
#include <raylib.h>
|
|
#include <raymath.h>
|
|
|
|
#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;
|
|
}
|