/*
    Living Realms is a primate evolution simulator.
    Copyright (C) 2011  Sterling Pickens

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __GLOBALS_H__
#define __GLOBALS_H__
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include "config.h"

#ifndef LRSTATS_COMPILE
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#elif HAVE_PTHREADS_H
#include <pthreads.h>
#endif
#endif

#define LR_VERSION "v0.2.5"
#define LR_NAME "Living Realms"
#define LR_DATE "06/11/2019"

// initial tribe # and location
#define INITIAL_TRIBES 25
#define INITIAL_TRIBE_X 2200
#define INITIAL_TRIBE_Y (uint32_t)floor(HEIGHT/2)
#define TRIBE_SQ (uint32_t)floor( sqrt(INITIAL_TRIBES) )
////  internal DEM dimensions (Don't edit !)
#define HEIGHT 1800
#define WIDTH 3600
#define DEM_SCALE 12     //don't change
#define REGION_SIZE 8  // don't change, Directly affects max number of threads  HEIGHT/REGION_SIZE == max thread count
//initial Opengl Window size
#define GLHEIGHT 600
#define GLWIDTH 800
// 1 in x chance new life will be new species, max 1.4 billion
#define CHANCE_OF_EVOLUTION 10000
//don't edit
#define CLIMATE_YEARS 1000  //values depend on 1000 to maintain approximate changes known from history
//C temperature lapse rates: degrees C of temp change per 1K meters from sea level
#define TEMP_PER_1000M 6.49

//// Species values for Initial tribes 1-255 ////
	//count as % of 256 ie: 127 = 50%
#define INTELLIGENCE 16
#define STRENGTH 16
#define SPEED 16
// values with degrees C (multiples of 4)
#define TEMP_L 16
#define TEMP_H 32
//in years
#define MAX_AGE 36
#define CUR_AGE 0
#define IMUNITY 240

//there needs to be a risk/reward for each of these
//only solution I can see is to make these fixed for now ...
//no food factor yet
//Sub-Species values for Initial tribes 1-255
#define MIGRATION_FACTOR 64  //moves to 0  risk = climate  reward = food
#define FIGHT_FLIGHT_BALANCE 72  //moves to 0  risk = death  reward = species adapt stronger
#define INTERSPECIES_VIOLENCE 18 //moves to 0  risk = death  reward = species adapt stronger
#define SOCIAL_FACTOR 200  //floats   risk = species slower adapt, less food  reward = reproduce more

//global values
#define WATER_MIGRATION_RANGE 16 // higher = more chance of water migrating 1-256
#define WATER_MIGRATION_T_MAX 36   //12 = 144KM max range, max "turns" to allow water migration

//use simple rand
#define SIMPLE_LRAND 1

#define LRAND(s) \
(((s) = (s) * 41943011 - 2147483647) >> 32)

#if ( defined(WITHOUT_HOST_PT_BARRIER) && !defined(LRSTATS_COMPILE) )
typedef int lrpthread_barrierattr_t;
typedef struct {
    pthread_mutex_t mutex;
    pthread_cond_t cond;
    int count;
    int tripCount;
} lrpthread_barrier_t;
int lrpthread_barrier_init(lrpthread_barrier_t *barrier, const lrpthread_barrierattr_t *attr, unsigned int count);
int lrpthread_barrier_destroy(lrpthread_barrier_t *barrier);
int lrpthread_barrier_wait(lrpthread_barrier_t *barrier);
#endif

struct Moves{
	uint32_t x;
	uint32_t y;
	uint32_t valid;
	int rating;
};

struct Species{
	unsigned char max_age;
	unsigned char cur_age;
	unsigned char imunity; //each time contact with another tribe doesn't kill them this goes up
	unsigned char water_turns;
	unsigned char migration_factor;
	unsigned char interspecies_violence;
	unsigned char social_factor;
	unsigned char fight_flight_balance;
	unsigned char intelligence;
    unsigned char strength;
    unsigned char speed;
	unsigned char temp_l;
	unsigned char temp_h;
	unsigned char water_direction;
};

struct image_attr{
    int16_t **dem; //elevation
    unsigned char *image; //rgb
};

struct Stats{
	uint32_t disease;
	uint32_t drown;
	uint32_t exposure; //died exposure to elements
	uint32_t old_age;
	uint32_t died_attacking;
	uint32_t died_defending;
	uint32_t new_life;
	uint32_t new_species;
};

#pragma pack(push, 1)
struct Stats_T{
	uint64_t disease;
	uint64_t drown;
	uint64_t exposure;
	uint64_t old_age;
	uint64_t died_attacking;
	uint64_t died_defending;
	uint64_t new_life;
	uint64_t new_species;
	uint64_t total_living;
	double total_runtime; //64-bit double == 292471208678 yrs total
	uint32_t year;
	float cur_temp;
	int16_t cur_sealevel;
	char sea_rising;
	char temp_rising;
};
#pragma pack(pop)

struct Thread_I{
	uint32_t start_h;
	uint32_t end_h;
};

void SET_ONE(unsigned char **array, size_t src_y, size_t src_x);
char IS_SET(unsigned char **array, size_t src_y, size_t src_x);

#endif
