<commit_before>#include "globals.h"
#include "npc.h"
#include "map.h"
#include "item.h"
#include <stdbool.h>
#include "player.h"
#include "msg.h"
#include <math.h>

size_t npcDataSize     = 0;
size_t npcDataCapacity = 0;
npcdata_t *npcData     = NULL;

npc_t npcInfo[NPC_COUNT];

#define CREATE_NPC(p_symbol,p_id,p_name,p_color) npcInfo[p_id].symbol = p_symbol; npcInfo[p_id].name = TO_STRING(p_name); npcInfo[p_id].color = p_color; 

void npcInit(void){
	//--    symbol , id                 , name             , color
	CREATE_NPC('x' , NPC_GRID_BUG       , "Grid bug"       , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('g' , NPC_GNOME          , "Gnome"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('k' , NPC_KOBOLD         , "Kobold"         , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('G' , NPC_GNOME_LORD     , "Gnome Lord"     , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('g' , NPC_GNOME_SHAMAN   , "Gnome Shaman"   , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('K' , NPC_KOBOLD_LORD    , "Kobold Lord"    , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('k' , NPC_KOBOLD_SHAMAN  , "Kobold Shaman"  , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('w' , NPC_WOLF           , "Wolf"           , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('d' , NPC_DWARF          , "Dwarf"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('o' , NPC_ORC            , "Orc"            , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('B' , NPC_BUGBEAR        , "Bugbear"        , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('S' , NPC_SPIDER         , "Giant Spider"   , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('I' , NPC_IMP            , "Imp"            , TERM_COLOR_RED     ) ;
	CREATE_NPC('O' , NPC_ORC_LORD       , "Orc Lord"       , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('O' , NPC_OGRE           , "Ogre"           , TERM_COLOR_RED     ) ;
	CREATE_NPC('O' , NPC_OGRE_LORD      , "Ogre Lord"      , TERM_COLOR_RED     ) ;
	CREATE_NPC('L' , NPC_THUNDER_LIZARD , "Thunder Lizard" , TERM_COLOR_BLUE    ) ;
	CREATE_NPC('G' , NPC_GARGOULE       , "Gargoule"       , TERM_COLOR_GREY    ) ;
	CREATE_NPC('S' , NPC_GIANT_SLIME    , "Giant Slime"    , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('E' , NPC_EFREETI        , "Efreet"         , TERM_COLOR_RED     ) ;
	CREATE_NPC('G' , NPC_GIANT          , "Giant"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('C' , NPC_SCORPION       , "Scorpion"       , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('S' , NPC_SNAKE          , "Snake"          , TERM_COLOR_RED     ) ;
	CREATE_NPC('B' , NPC_BEAR           , "Bear"           , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('B' , NPC_GIANT_BEAR     , "Giant Bear"     , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('H' , NPC_HOBO           , "Hobo"           , TERM_COLOR_RED     ) ;
	CREATE_NPC('H' , NPC_DRUNK_HUNTER   , "<NAME>"   , TERM_COLOR_RED     ) ;
	CREATE_NPC('M' , NPC_MERCENARY      , "Mercenary"      , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('S' , NPC_GIANT_SPIDER   , "Giant SPider"   , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('C' , NPC_CROCODILE      , "Crocodile"      , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('D' , NPC_DINOSAUR       , "Dinosaur"       , TERM_COLOR_GREEN   ) ;

	//CREATE_NPC(,,,,,,,TERM_COLOR_DEFAULT, NPC_RELATION_HOSTILE);

	//Init the npcdata array
	for(int i = 0;i < npcDataSize;i++){
		npcData[i].state   = NPCSTATE_DEAD;
		npcData[i].aiState = &npcState_sleep;
	}
}

void npcSpawnRandom(int z){
	pos_t pos;
	pos.x = 0;
	pos.y = 0;
	pos.z = z;

	//LOG_DEBUG_INT("depth: %i",z);

	int npcCount = randomRange(10,10 + abs(playerGetInfo()->level * 5));

	while(npcCount > 0){
		int done = false;
		while(done == false){
            //TODO: Check for existing enemies

			pos.x = randomRange(1,MAP_MAX_WIDTH-1);
			pos.y = randomRange(1,MAP_MAX_HEIGHT-1);

			if(mapGetTileByPos(pos)->block == 0){
				npcSpawn(pos,randomRange(0,NPC_COUNT-1));
				done = true;
			}
		}
		npcCount--;
	}
}

void npcSpawn(pos_t pos,npcname_t id){
	assert(id < NPC_COUNT);
	assert(id >= 0);

	int i;

	for(i = 0;i < npcDataSize;i++){
		if(npcData[i].state == NPCSTATE_DEAD)
			goto npcSpawnReturn;
	}

	if(npcDataSize >= npcDataCapacity){
		npcDataCapacity *= 2;
		if(npcDataCapacity == 0)
			npcDataCapacity = 2;

		npcData = realloc(npcData,(npcDataCapacity) * sizeof(npcData[0]));
		LOG_DEBUG_F("[mem] Reallocing npcData to %i",npcDataCapacity);
	}

	i = npcDataSize++;

npcSpawnReturn:
	npcData[i].maxHp = (playerGetInfo()->maxhp + randomRange(-10,10));
	npcData[i].maxHp = MAX(10,npcData[i].maxHp);
	npcData[i].meleeDmgMin = (playerGetInfo()->level * randomRange(2,5)); 
	npcData[i].meleeDmgMax = (playerGetInfo()->level * randomRange(5,9));

	npcData[i].meleeDmgMin = MAX(5,npcData[i].meleeDmgMin);
	npcData[i].meleeDmgMax = MAX(10,npcData[i].meleeDmgMax);

	if(randomRange(1,100) > 80){
		npcData[i].relation = NPC_RELATION_PEACEFUL;
	}else{
		npcData[i].relation = NPC_RELATION_HOSTILE;
	}

	npcData[i].state   = NPCSTATE_ALIVE;
	npcData[i].pos     = pos;
	npcData[i].aiState = &npcState_idle;
	npcData[i].name    = id;
	npcData[i].hp      = npcData[i].maxHp;

	LOG_INFO_F("hp: %i/%i min: %i max: %i",npcData[i].hp,npcData[i].maxHp,npcData[i].meleeDmgMin,npcData[i].meleeDmgMax);

	static const pos_t empty = {0,0,0};
	npcData[i].playerLastKnownPosition = empty;
}

void npcRender(){
	for(int i = 0;i < npcDataSize;i++){
		if(npcData[i].state != NPCSTATE_ALIVE)
			continue;

		if(npcData[i].pos.z != playerGetInfo()->pos.z)
			continue;

		if(mapLosCheckByPos(playerGetInfo()->pos,npcData[i].pos) == false)
			continue;

		printIntxy(npcData[i].pos.x,npcData[i].pos.y,npcInfo[npcData[i].name].symbol);
	}
}

void npcClearFromLevel(int z){

	for(int i = 0;i < npcDataSize;i++){
<commit_msg>Fixed npc's not having colors<commit_after>#include "globals.h"
#include "npc.h"
#include "map.h"
#include "item.h"
#include <stdbool.h>
#include "player.h"
#include "msg.h"
#include <math.h>

size_t npcDataSize     = 0;
size_t npcDataCapacity = 0;
npcdata_t *npcData     = NULL;

npc_t npcInfo[NPC_COUNT];

#define CREATE_NPC(p_symbol,p_id,p_name,p_color) npcInfo[p_id].symbol = p_symbol; npcInfo[p_id].name = TO_STRING(p_name); npcInfo[p_id].color = p_color; 

void npcInit(void){
	//--    symbol , id                 , name             , color
	CREATE_NPC('x' , NPC_GRID_BUG       , "Grid bug"       , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('g' , NPC_GNOME          , "Gnome"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('k' , NPC_KOBOLD         , "Kobold"         , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('G' , NPC_GNOME_LORD     , "Gnome Lord"     , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('g' , NPC_GNOME_SHAMAN   , "Gnome Shaman"   , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('K' , NPC_KOBOLD_LORD    , "Kobold Lord"    , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('k' , NPC_KOBOLD_SHAMAN  , "Kobold Shaman"  , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('w' , NPC_WOLF           , "Wolf"           , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('d' , NPC_DWARF          , "Dwarf"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('o' , NPC_ORC            , "Orc"            , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('B' , NPC_BUGBEAR        , "Bugbear"        , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('S' , NPC_SPIDER         , "Giant Spider"   , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('I' , NPC_IMP            , "Imp"            , TERM_COLOR_RED     ) ;
	CREATE_NPC('O' , NPC_ORC_LORD       , "Orc Lord"       , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('O' , NPC_OGRE           , "Ogre"           , TERM_COLOR_RED     ) ;
	CREATE_NPC('O' , NPC_OGRE_LORD      , "Ogre Lord"      , TERM_COLOR_RED     ) ;
	CREATE_NPC('L' , NPC_THUNDER_LIZARD , "Thunder Lizard" , TERM_COLOR_BLUE    ) ;
	CREATE_NPC('G' , NPC_GARGOULE       , "Gargoule"       , TERM_COLOR_GREY    ) ;
	CREATE_NPC('S' , NPC_GIANT_SLIME    , "Giant Slime"    , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('E' , NPC_EFREETI        , "Efreet"         , TERM_COLOR_RED     ) ;
	CREATE_NPC('G' , NPC_GIANT          , "Giant"          , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('C' , NPC_SCORPION       , "Scorpion"       , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('S' , NPC_SNAKE          , "Snake"          , TERM_COLOR_RED     ) ;
	CREATE_NPC('B' , NPC_BEAR           , "Bear"           , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('B' , NPC_GIANT_BEAR     , "Giant Bear"     , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('H' , NPC_HOBO           , "Hobo"           , TERM_COLOR_RED     ) ;
	CREATE_NPC('H' , NPC_DRUNK_HUNTER   , "Drunk Hunter"   , TERM_COLOR_RED     ) ;
	CREATE_NPC('M' , NPC_MERCENARY      , "Mercenary"      , TERM_COLOR_DEFAULT ) ;
	CREATE_NPC('S' , NPC_GIANT_SPIDER   , "Giant SPider"   , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('C' , NPC_CROCODILE      , "Crocodile"      , TERM_COLOR_GREEN   ) ;
	CREATE_NPC('D' , NPC_DINOSAUR       , "Dinosaur"       , TERM_COLOR_GREEN   ) ;

	//CREATE_NPC(,,,,,,,TERM_COLOR_DEFAULT, NPC_RELATION_HOSTILE);

	//Init the npcdata array
	for(int i = 0;i < npcDataSize;i++){
		npcData[i].state   = NPCSTATE_DEAD;
		npcData[i].aiState = &npcState_sleep;
	}
}

void npcSpawnRandom(int z){
	pos_t pos;
	pos.x = 0;
	pos.y = 0;
	pos.z = z;

	//LOG_DEBUG_INT("depth: %i",z);

	int npcCount = randomRange(10,10 + abs(playerGetInfo()->level * 5));

	while(npcCount > 0){
		int done = false;
		while(done == false){
            //TODO: Check for existing enemies

			pos.x = randomRange(1,MAP_MAX_WIDTH-1);
			pos.y = randomRange(1,MAP_MAX_HEIGHT-1);

			if(mapGetTileByPos(pos)->block == 0){
				npcSpawn(pos,randomRange(0,NPC_COUNT-1));
				done = true;
			}
		}
		npcCount--;
	}
}

void npcSpawn(pos_t pos,npcname_t id){
	assert(id < NPC_COUNT);
	assert(id >= 0);

	int i;

	for(i = 0;i < npcDataSize;i++){
		if(npcData[i].state == NPCSTATE_DEAD)
			goto npcSpawnReturn;
	}

	if(npcDataSize >= npcDataCapacity){
		npcDataCapacity *= 2;
		if(npcDataCapacity == 0)
			npcDataCapacity = 2;

		npcData = realloc(npcData,(npcDataCapacity) * sizeof(npcData[0]));
		LOG_DEBUG_F("[mem] Reallocing npcData to %i",npcDataCapacity);
	}

	i = npcDataSize++;

npcSpawnReturn:
	npcData[i].maxHp = (playerGetInfo()->maxhp + randomRange(-10,10));
	npcData[i].maxHp = MAX(10,npcData[i].maxHp);
	npcData[i].meleeDmgMin = (playerGetInfo()->level * randomRange(2,5)); 
	npcData[i].meleeDmgMax = (playerGetInfo()->level * randomRange(5,9));

	npcData[i].meleeDmgMin = MAX(5,npcData[i].meleeDmgMin);
	npcData[i].meleeDmgMax = MAX(10,npcData[i].meleeDmgMax);

	if(randomRange(1,100) > 80){
		npcData[i].relation = NPC_RELATION_PEACEFUL;
	}else{
		npcData[i].relation = NPC_RELATION_HOSTILE;
	}

	npcData[i].state   = NPCSTATE_ALIVE;
	npcData[i].pos     = pos;
	npcData[i].aiState = &npcState_idle;
	npcData[i].name    = id;
	npcData[i].hp      = npcData[i].maxHp;

	LOG_INFO_F("hp: %i/%i min: %i max: %i",npcData[i].hp,npcData[i].maxHp,npcData[i].meleeDmgMin,npcData[i].meleeDmgMax);

	static const pos_t empty = {0,0,0};
	npcData[i].playerLastKnownPosition = empty;
}

void npcRender(){
	for(int i = 0;i < npcDataSize;i++){
		if(npcData[i].state != NPCSTATE_ALIVE)
			continue;

		if(npcData[i].pos.z != playerGetInfo()->pos.z)
			continue;

		if(mapLosCheckByPos(playerGetInfo()->pos,npcData[i].pos) == false)
			continue;

		setColor(npcInfo[npcData[i].name].color);
		printIntxy(npcData[i].pos.x,npcData[i].pos.y,npcInfo[npcData[i].name].symbol);
		setColorOff(npcInfo[npcData[i].name].color);
	}
}

void npcClearFromLevel(int z){

	for(int i = 0;i < npcDataSize;i++){

{'fraction_non_alphanumeric': 0.15170997410483078, 'fraction_numerical': 0.008572193945888026, 'mean_word_length': 3.204204204204204, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7091818', 'n_tokens_mistral': 5149, 'n_tokens_neox': 4821, 'n_words': 677}