From e37bf141c2fdfe0364b575c3f4d58f6fb40bc891 Mon Sep 17 00:00:00 2001 From: attilavs2 Date: Mon, 12 Aug 2024 16:28:35 +0200 Subject: [PATCH] =?UTF-8?q?npc=20:=20D=C3=A9but=20d'ajout=20d'IA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/converters.py | 12 ++++---- src/game.c | 13 +++++++-- src/game.h | 9 ++++-- src/main.c | 7 ++--- src/npc.c | 68 +++++++++++++++++++++++++++++++++++++++++--- src/npc.h | 37 ++++++++++++++++++++---- 6 files changed, 123 insertions(+), 23 deletions(-) diff --git a/assets/converters.py b/assets/converters.py index ab91eb0..1d1bc72 100644 --- a/assets/converters.py +++ b/assets/converters.py @@ -309,15 +309,15 @@ def convert_map(input: str, output: str, params: dict, target): npc_struct += fxconv.u32(i["position"][0]) npc_struct += fxconv.u32(i["position"][1]) npc_struct += fxconv.u16(i["face"]) - npc_struct += fxconv.u8(0) + npc_struct += fxconv.u8(0) #paused npc_struct += fxconv.u8(i["hasDialog"]) npc_struct += fxconv.u32(i["dialogID"]) npc_struct += fxconv.u32(i["needAction"]) npc_struct += fxconv.string(i["name"]) npc_struct += fxconv.u8(len(i["path"]) > 2) - npc_struct += fxconv.u8(0) + npc_struct += fxconv.u8(0) #owns_path npc_struct += fxconv.u8(len(i["path"])//2) - npc_struct += fxconv.u8(0) + npc_struct += fxconv.u8(0) #current_point xpath = bytes() ypath = bytes() @@ -330,9 +330,11 @@ def convert_map(input: str, output: str, params: dict, target): npc_struct += fxconv.ptr(xpath) npc_struct += fxconv.ptr(ypath) - npc_struct += fxconv.u32(0) # TODO: Type + npc_struct += fxconv.u16(0) # Type - leave as npc_struct += fxconv.u8(0) # TODO: Group - npc_struct += fxconv.u8(0) # TODO: Hostile to + npc_struct += fxconv.u8(0) # Hostile to - leave as + npc_struct += fxconv.u8(0) # state - leave as + npc_struct += fxconv.u8(0) # Padding npc_struct += fxconv.u16(0) # Padding map_struct += fxconv.ptr(npc_struct) # Load signs diff --git a/src/game.c b/src/game.c index 8eb7c92..d1c1baa 100644 --- a/src/game.c +++ b/src/game.c @@ -11,18 +11,21 @@ #include #include #include +#include extern bopti_image_t SignAction_img; extern bopti_image_t player_male_img; extern bopti_image_t tiny_npc_male; extern Dialog *dialogRPG; -// extern NPC *npcRPG; -// extern uint32_t nbNPC; #define MAX_INTERACTION_DISTANCE 12 void game_init(Game *game) { + /*Seed the stdlib rand() function*/ + uint32_t randseed = time(NULL); + srand(randseed); + game->map_level = worldRPG[0]; /* NPC animation */ animation_new(&game->npc_animation, &tiny_npc_male, 3, 250); @@ -279,9 +282,15 @@ void game_get_inputs(Game *game) { mynpc->xpath = NULL; mynpc->ypath = NULL; } + while(keydown(KEY_F1)){ + clearevents(); + } } if(keydown(KEY_F2)) { npc_remove_pos(0); + while(keydown(KEY_F2)){ + clearevents(); + } } /* Display Debug Information on screen */ diff --git a/src/game.h b/src/game.h index b72abff..81b3f06 100644 --- a/src/game.h +++ b/src/game.h @@ -143,16 +143,21 @@ typedef struct { /* data for NPC's trajectories */ uint8_t hasPath; - uint8_t owns_path; + uint8_t owns_path; /*If the NPCs path is malloc()ed*/ uint8_t path_length; uint8_t currentPoint; int16_t *xpath; int16_t *ypath; - int type : 32; + /*Should be one of NPC_ - 0 for static NPCs*/ + uint16_t type; + /*The follwing should be one of NPC_T*/ uint8_t current_group; uint8_t hostile_to_group; + /*state should be one of NPC_S*/ + uint8_t state; + uint8_t __temp; /* uint16_t to keep the struct aligned */ uint16_t __padding; diff --git a/src/main.c b/src/main.c index e9762af..538df1b 100644 --- a/src/main.c +++ b/src/main.c @@ -124,6 +124,7 @@ int main(void) { _message_buffer = NULL; _message_buffer = malloc(MESSAGE_BUFFER_SZ); if(!_message_buffer) { + dclear(C_WHITE); dtext(64, 64, C_BLACK, "Failed to allocate the message buffer: not " "enough RAM available. Press any key to quit."); @@ -131,6 +132,7 @@ int main(void) { getkey(); return 0; } + game_init(&game); #if USB_FEATURE @@ -144,11 +146,6 @@ int main(void) { dgray(DGRAY_ON); #endif -#if DEBUGMODE - dupdate(); - getkey(); -#endif - do { /* render the map */ game_draw(&game); diff --git a/src/npc.c b/src/npc.c index c3952dc..689b988 100644 --- a/src/npc.c +++ b/src/npc.c @@ -18,6 +18,32 @@ extern bopti_image_t tiny_npc_female; extern bopti_image_t tiny_npc_milkman; extern bopti_image_t tiny_npc_police; +NPC_TypeData npc_typedat[NPC_Type_Count] = { + /*NPC_Static*/ + {0, 0, 0, 0}, + /*NPC_Guard*/ + { + .agressivity = 75, + .cowardice = 85, + .lazyness = 50, + .wanderlust = 150 + }, + /*NPC_Bandit*/ + { + .agressivity = 110, + .cowardice = 85, + .lazyness = 40, + .wanderlust = 60 + }, + /*NPC_Monster*/ + { + .agressivity = 170, + .cowardice = 50, + .lazyness = 40, + .wanderlust = 80 + } +}; + NPC npc_stack[NPC_STACK_SIZE]; uint32_t npc_count; @@ -340,16 +366,50 @@ void update_npcs(Game *game) { } for(i = 0; i < npc_count; i++) { update_npc(&npc_stack[i], game); - /*Temp debug*/ - game->mana = npc_pathfind(game->player.x, game->player.y, - game->map_level, &npc_stack[i]); + } +} + +void npc_ai(NPC *npc, Game *game){ + NPC_TypeData *tdat = &npc_typedat[npc->type]; + + uint32_t idle_chance = 0; + uint32_t wander_chance = 0; + uint32_t flee_chance = 0; + uint32_t attack_chance = 0; + + switch(npc->state){ + case NPC_S_IDLE : { + /*TODO : Expand conditions to switch states*/ + + break; + } + case NPC_S_WANDER : { + /*TODO : Choose a random close point to pathfind to */ + break; + } + case NPC_S_FLEE : { + /*TODO : Pathfind to a point away from the player*/ + break; + } + case NPC_S_ATTACK : { + /*TODO : Attack !*/ + break; + } + default : { + /*Get real*/ + npc->state = NPC_S_IDLE; + break; + } } } extern const short int walkable_speed[WALKABLE_TILE_MAX]; void update_npc(NPC *npc, Game *game) { - /* if the NPC has no path or is paused, skip it */ + if(npc->type != NPC_Static) + npc_ai(npc, game); + + /* if the NPC has no path or is paused, skip the moving part */ if(!npc->hasPath || npc->paused == true) return; diff --git a/src/npc.h b/src/npc.h index b1d14e4..d39da11 100644 --- a/src/npc.h +++ b/src/npc.h @@ -16,13 +16,40 @@ #define npc_to_curxy(a) (((a)*PXSIZE) << PRECISION) -enum { +typedef struct { - NPC_NONE = 0, - NPC_FRIENDLY = 1, // The player's team - NPC_HOSTILE = 2, // to the player - NPC_ALL = 3 + /*TODO : Stats*/ + + /*AI weights - Values on 255*/ + uint8_t agressivity; /*Attack*/ + uint8_t cowardice; /*Flee*/ + uint8_t lazyness; /*Idle*/ + uint8_t wanderlust; /*Wandering*/ + +} NPC_TypeData; + +enum { + NPC_Static = 0, /*~= none, disqualifies from all AI*/ + NPC_Guard = 1, + NPC_Bandit = 2, + NPC_Monster = 3, + NPC_Type_Count }; + +enum { + NPC_T_NONE = 0, + NPC_T_FRIENDLY = 1, /* The player's team */ + NPC_T_HOSTILE = 2, /* to the player */ + NPC_T_ALL = 3 +}; + +enum { + NPC_S_IDLE = 0, + NPC_S_ATTACK = 1, + NPC_S_FLEE = 2, + NPC_S_WANDER = 3 +}; + /* /!\ Warning /!\ * Do not keep hard references to non-static NPCs, as they will likely move * in the stack */