/* * BSD 2-Clause “Simplified” License * Copyright (c) 2019, Aldrik Ramaekers, aldrik.ramaekers@protonmail.com * All rights reserved. */ #ifndef INCLUDE_WORLD #define INCLUDE_WORLD #define MAX_WORLD_LOCATION_NAME_LENGTH 20 #define MAX_ENPOLYEE_FIRSTNAME_LENGTH 14 #define MAX_ENPOLYEE_LASTNAME_LENGTH 14 #define MAX_EMPLOYEE_NAME_LENGTH 30 #define MAX_COMPANY_NAME_LENGTH 50 #define MAX_DEALER_NAME_LENGTH 20 #define MAX_TRUCK_NAME_LENGTH 30 #define MAX_PRODUCT_NAME_LENGTH 50 #define MAX_EMPLOYEE_NR_LENGTH 12 #define MAX_INPUT_LENGTH_FOR_EMPLOYEE_SELECTOR 10 // Static = loaded from file // Save State = loaded from save state // Dynamic = set at runtime #define MINUTES(_n) (_n*60) #define HOURS(_n) (_n*MINUTES(60)) #define DAYS(_n) (_n*HOURS(24)) typedef struct t_world_location world_location; typedef struct t_employee employee; #define WORK_HOUR_START 0 #define WORK_HOUR_END 24 #define TIME_SLOTS_PER_HOUR 4 #define TIME_SLOTS_PER_DAY ((WORK_HOUR_END-WORK_HOUR_START)*TIME_SLOTS_PER_HOUR) #define TIME_SLOTS_PER_WEEK (TIME_SLOTS_PER_DAY*7) #define MAX_JOBOFFER_COUNT 25 #define MAX_EMPLOYEE_COUNT (TIME_SLOTS_PER_WEEK) #define MAX_TRUCK_COUNT (TIME_SLOTS_PER_WEEK) #define JOB_STARTING_TRUST 0.8f #define MISSED_DELIVERY_TRUST_PENALTY (0.1f) #define MAX_EFFECTIVE_EXPERIENCE 25.0f // anything past 25 years of experience has no extra positives. #define SHIPTIME_DURATION_MULTIPLIER_MAX 1.0f #define SHIPTIME_DURATION_MULTIPLIER_MIN 1.15f #define DIESEL_PRICE_PER_LITER 1.4f #define RETIREMENT_AGE 65 #define INVALID_ID 0 #define MAX_WORKED_HOURS_WEEKLY (50.0f) #define MINIMUM_EMPLOYEE_HAPPINESS (0.4f) #define EMPLOYEE_MAX_UNHAPPY_DAYS_BEFORE_QUITTING (30.0f) #define CDAYTORDAY(_day) (_day == 0 ? 7 : _day) // m = 1, s = 7 #define RDAYTOCDAY(_day) (_day == 7 ? 0 : _day) // m = 1, s = 0 #define INVESTMENT_INCREMENT 100.0f #define BASE_PAY 1800 #define RAISE_PER_YEAR 55 #define MAX_PAY 3250 typedef enum t_weekday { MONDAY = 1, TUESDAY = 2, WEDNESDAY = 3, THURSDAY = 4, FRIDAY = 5, SATURDAY = 6, SUNDAY = 0, DAY_INVALID = 99 } weekday; typedef struct t_product { char name[MAX_PRODUCT_NAME_LENGTH]; } product; typedef struct t_company { // Static char name[MAX_COMPANY_NAME_LENGTH]; array products; // Dynamic image* logo; } company; typedef struct t_truck { // Static char name[MAX_TRUCK_NAME_LENGTH]; u16 hp; u32 price; u16 fuelcapacity; u16 torque; float fuelusage; // Dynamic image* logo; // Save State s32 type; s32 id; employee* assigned_employee; } truck; typedef struct t_truck_dealer { // Static char name[MAX_DEALER_NAME_LENGTH]; array trucks; // Dynamic image* logo; } truck_dealer; #define JOB_OFFER_REWARD_PER_CONNECTION 160 #define MAX_SHIPDAYS 4 #define MIN_POSSIBLE_SHIPDAYS 2 typedef struct t_job_offer { u32 id; s64 expire_date; company* company; product* product; s32 shipday_count; weekday shipdays[MAX_SHIPDAYS]; u32 reward; array connections; // Should not be freed if offer has been accepted. double total_distance; // in KM time_t duration_sec_min; // experienced drivers time_t duration_sec_max; // inexperienced drivers } job_offer; typedef struct t_employee { u32 id; char name[MAX_EMPLOYEE_NAME_LENGTH]; u8 age; struct tm hire_date; float experience; float salary; float happiness; // 0-1 s16 days_below_happiness_treshold; u32 current_location_id; u32 original_location_id; truck* assigned_truck; u32 active_job_id; // Portrait u8 portrait_hair_type; color hair_color; color face_color; color body_color; } employee; #define RESUME_FADEOUT_MS 300 typedef struct t_resume { employee* employee; s64 expire_date; bool hired; animation animation; } resume; typedef struct t_scheduled_job_time { s16 day; // sunday = 0 s16 timeslot; bool stay_at_destination; employee* assignee; } scheduled_job_time; typedef struct t_scheduled_job { float trust; job_offer offer; world_location* location; scheduled_job_time timeslots[MAX_SHIPDAYS]; } scheduled_job; typedef struct t_active_job { // save state s16 day; s16 timeslot; bool stay_at_destination; job_offer offer; employee assignee; truck assigned_truck; time_t duration_sec; time_t left_at; time_t done_at; bool reversed; // dynamic vec2f px_pos; bool is_hovered; } active_job; typedef struct t_active_job_ref { s16 day; s16 timeslot; u32 offerid; } active_job_ref; typedef struct t_world_update_result { active_job* clicked_job; world_location* clicked_location; } world_update_result; #define NUM_DAYS 7 typedef struct t_schedule { array jobs; } schedule; typedef struct t_world_location { // Static u8 size; double latitude; double longitude; char name[MAX_WORLD_LOCATION_NAME_LENGTH]; s32 map_position_x; s32 map_position_y; // Save State bool is_owned; array employees; // Contains internal and external employees. Employee can be at 2 locations at any given time. array job_offers; array resumes; array trucks; schedule schedule; u16 purchase_year; array insights; float score; // 0-1 // Dynamic array connections; bool is_hovered; bool is_accessible; u32 id; } world_location; typedef struct t_job_endpoints { world_location* source; world_location* dest; } job_endpoints; typedef enum t_event_type { EVENT_TYPE_MISSED_SHIPMENT_NO_TRUCK, // go to employee detail EVENT_TYPE_MISSED_SHIPMENT_NOT_AT_LOCATION, // go to schedule EVENT_TYPE_MISSED_SHIPMENT_NO_ASSIGNEE, // go to schedule EVENT_TYPE_EMPLOYEE_QUIT, // go to schedule EVENT_TYPE_FINED, // go to employee detail EVENT_TYPE_INFO, // not clickable } event_type; #define MAX_EVENT_MESSAGE_LENGTH 200 typedef struct t_event { void* data; event_type type; scheduled_job_time job_time; char message[MAX_EVENT_MESSAGE_LENGTH]; } event; #define MIN_SIMULATION_SPEED 0 #define MAX_SIMULATION_SPEED 8 #define LOG_HISTORY_LENGTH 25 typedef struct t_event_log { array events; u16 write_cursor; bool has_unread_messages; } event_log; #define ADD_EXPENSE(_world,_loc,_var,_amount)\ {\ _world->money -= _amount;\ money_data_collection* collection = get_current_insights_data(_world);\ collection->months[_world->current_time.tm_mon].total_expenses -= _amount;\ collection->months[_world->current_time.tm_mon].total_profit -= _amount;\ collection->months[_world->current_time.tm_mon]._var -= _amount;\ if (_loc) {\ collection = get_current_insights_data_for_location(_world,_loc);\ collection->months[_world->current_time.tm_mon].total_expenses -= _amount;\ collection->months[_world->current_time.tm_mon].total_profit -= _amount;\ collection->months[_world->current_time.tm_mon]._var -= _amount;}\ } #define ADD_INCOME(_world,_loc,_var,_amount)\ {\ _world->money += _amount;\ money_data_collection* collection = get_current_insights_data(_world);\ collection->months[_world->current_time.tm_mon].total_income += _amount;\ collection->months[_world->current_time.tm_mon].total_profit += _amount;\ collection->months[_world->current_time.tm_mon]._var += _amount;\ if (_loc) {\ collection = get_current_insights_data_for_location(_world,_loc);\ collection->months[_world->current_time.tm_mon].total_income += _amount;\ collection->months[_world->current_time.tm_mon].total_profit += _amount;\ collection->months[_world->current_time.tm_mon]._var += _amount;}\ } #define EXPENSES get_current_insights_data(world)->months[world->current_time.tm_mon] typedef struct t_money_data { float total_income; float total_expenses; float total_profit; float income_from_trips; float expenses_from_trucks; float expenses_from_utility; float expenses_from_healthcare; float expenses_from_repairs; float expenses_from_fuel; float expenses_from_employees; } money_data; #define MONTHS_IN_YEAR 12 typedef struct t_money_data_collection { money_data months[MONTHS_IN_YEAR]; } money_data_collection; typedef struct t_company_investments { u32 marketing; u32 human_resources; u32 training; u32 legal; } company_investments; typedef struct t_world { // Save State s64 simulation_time; u16 start_year; float money; u32 next_id; u8 simulation_speed; array active_jobs; event_log log; array insights; company_investments investments; u16 days_since_last_random_event; // Dynamic array locations; array companies; array firstnames; array lastnames; array truck_dealers; array boat_routes; struct tm current_time; } world; world* world_create_new(); void world_report_event(world* world, char* msg, event_type type, void* data); world_location* get_world_location_by_id(world* world, s32 id); world_location* get_world_location_by_name(world* world, char* str); float world_location_get_price(world_location* location); void add_truck_to_world_location(world* world, world_location* location, truck* tr); void world_update(platform_window* window, world* world); world_update_result world_render(platform_window* window, world* world); #endif