fixed plenty of bugs, added agressive behavior
This commit is contained in:
parent
cad7cc19a2
commit
b6379dcc1f
393
behaviors/war_charge_east.cpp
Normal file
393
behaviors/war_charge_east.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
#include <cstdlib>
|
||||
#include "behavior.h"
|
||||
|
||||
// g++ -shared war_charge_east.cpp -o war_charge_east.dll -std=c++11 -I../src
|
||||
|
||||
#define KING_POS Coord(2, 2)
|
||||
#define ARMY_POS Coord(12, 4)
|
||||
#define CHARGE_DIR EAST
|
||||
|
||||
enum Purpose { NEWBORN, KING, PEASANT, SOLDIER };
|
||||
|
||||
struct KingMemory{ // 16 bytes
|
||||
int nbPeasants;
|
||||
int nbSoldiers;
|
||||
int date;
|
||||
Dir last_audience_dir;
|
||||
};
|
||||
|
||||
struct PeasantMemory{ // 8 bytes
|
||||
bool tried_picking_up_food;
|
||||
bool brings_food;
|
||||
};
|
||||
|
||||
struct SoldierMemory{ // 16 bytes
|
||||
Coord target;
|
||||
int charge_countdown;
|
||||
bool commander;
|
||||
};
|
||||
|
||||
union JobMemory { // 16 bytes
|
||||
KingMemory king;
|
||||
PeasantMemory peasant;
|
||||
SoldierMemory soldier;
|
||||
};
|
||||
|
||||
struct memory_data{ // 104 bytes
|
||||
// 40 bytes
|
||||
JobMemory job;
|
||||
Coord pos;
|
||||
bool new_born;
|
||||
int purpose;
|
||||
Dir last_dir;
|
||||
Action::Type last_action;
|
||||
// 64 bytes
|
||||
char debugStr[64];
|
||||
};
|
||||
|
||||
const char* PURPOSES_STRINGS[] {
|
||||
"Newborn",
|
||||
"King",
|
||||
"Peasant",
|
||||
"Soldier"
|
||||
};
|
||||
|
||||
extern "C" void debugOutput(char *outputString, const char *memory)
|
||||
{
|
||||
memory_data* data = (memory_data*)memory;
|
||||
sprintf(outputString, "%s\n%s", PURPOSES_STRINGS[data->purpose], data->debugStr);
|
||||
if(data->purpose == KING)
|
||||
{
|
||||
sprintf(outputString, "%s\nRuled the kingdom for %d ticks\npopulation :\n%d peasants\n%d soldiers",
|
||||
outputString, data->job.king.date, data->job.king.nbPeasants, data->job.king.nbSoldiers);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void think(Action *action, char *memory, const Info *info)
|
||||
{
|
||||
int i;
|
||||
PixelType type;
|
||||
|
||||
bool success = info->getSuccess();
|
||||
memory_data* data = (memory_data*)memory;
|
||||
data->debugStr[0] = '\0';
|
||||
|
||||
// if freshly spawned, init the position variable by looking in which direction is the spawn
|
||||
if(!data->new_born){
|
||||
success = false;
|
||||
data->new_born = true;
|
||||
for(i=0; i<4; i++)
|
||||
{
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == SPAWN)
|
||||
{
|
||||
data->pos = Coord(0) - Dir(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update position if last successful action was moving
|
||||
if(data->last_action == Action::MOVE){
|
||||
if(success)
|
||||
data->pos += data->last_dir;
|
||||
else
|
||||
{
|
||||
int blockedCount = 0;
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir((data->last_dir + rand()%3)%4);
|
||||
type = info->getNear(action->dir);
|
||||
++blockedCount;
|
||||
if(blockedCount > 3)
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
break;
|
||||
}
|
||||
}while(!PixelProperty::isWalkable(type));
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "moving around obstacle");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// work any workable resource when encountered
|
||||
if(data->purpose == SOLDIER && data->job.soldier.charge_countdown == 0)
|
||||
{
|
||||
action->dir = CHARGE_DIR;
|
||||
PixelType front = info->getNear(CHARGE_DIR);
|
||||
if(!PixelProperty::isWalkable(front))
|
||||
{
|
||||
if(PixelProperty::isDestructible(front))
|
||||
action->type = Action::ATTACK;
|
||||
else if(PixelProperty::isResource(front))
|
||||
{
|
||||
if(info->getInventory() != EMPTY)
|
||||
{
|
||||
action->type = Action::PUT;
|
||||
action->dir = Dir((CHARGE_DIR+2)%4);
|
||||
}
|
||||
else
|
||||
action->type = Action::PICK;
|
||||
}
|
||||
else
|
||||
action->type = Action::WORK;
|
||||
}
|
||||
else
|
||||
action->type = Action::MOVE;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "CHAAAAAAAAAARGE !");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == BERRIES || type == TREE || type == IRON_ORE || type == ROCK){
|
||||
action->type = Action::WORK;
|
||||
action->dir = Dir(i);
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "working on resource");
|
||||
return;
|
||||
}else if(type == FOOD && data->purpose == PEASANT
|
||||
&& !(data->job.peasant.brings_food) && !(data->job.peasant.tried_picking_up_food)){
|
||||
action->type = Action::PICK;
|
||||
action->dir = Dir(i);
|
||||
data->job.peasant.tried_picking_up_food = true;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "picking up food");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do your job
|
||||
switch(data->purpose)
|
||||
{
|
||||
case NEWBORN :
|
||||
{
|
||||
const Com* com = info->getCom();
|
||||
if(com != nullptr) // no activity
|
||||
{
|
||||
switch(com->data[0])
|
||||
{
|
||||
case 'p': data->purpose = PEASANT; break;
|
||||
case 's':
|
||||
data->purpose = SOLDIER;
|
||||
data->job.soldier.target.x = *((int*)(com->data+2));
|
||||
data->job.soldier.target.y = *((int*)(com->data+6));
|
||||
data->job.soldier.commander = bool(com->data[10]);
|
||||
data->job.soldier.charge_countdown = *((int*)(com->data+11));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "receiving job : %s", com->data);
|
||||
return;
|
||||
}
|
||||
Coord target = data->pos - KING_POS;
|
||||
int distance = target.dist();
|
||||
if(distance == 0) // i am the new king
|
||||
{
|
||||
data->job.king.last_audience_dir = NO_DIR;
|
||||
data->purpose = KING;
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "I AM THE KING, LONG LIVE THE KING");
|
||||
return;
|
||||
}
|
||||
// if adjacent to the king's position, speak to the king if there is one
|
||||
if(distance == 1){
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(Coord(Dir((i+2)%4)) == target && type == DUDE){ // it is the king
|
||||
action->dir = Dir(i);
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->com_data.data[0] = 'n'; // "give me a purpose"
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "asking the king to give me a task");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// move to the king's position
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(target + action->dir) > distance && distance != 0);
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "walking to the king's throne");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case KING :
|
||||
{
|
||||
data->job.king.date += 1;
|
||||
const Com* com = info->getCom();
|
||||
if(com == nullptr || data->job.king.last_audience_dir == Dir(com->flag)) // no activity
|
||||
{
|
||||
data->job.king.last_audience_dir = NO_DIR;
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "waiting for a subject to ask for an audience");
|
||||
return;
|
||||
}
|
||||
// someone requests an audience to the king
|
||||
char request = com->data[0];
|
||||
if(request == 'n')
|
||||
{
|
||||
int population = data->job.king.nbPeasants + data->job.king.nbSoldiers;
|
||||
if(population < 15 || data->job.king.nbPeasants < (2*population)/3)
|
||||
{
|
||||
action->com_data.data[0] = 'p'; // "thou shall be peasant"
|
||||
data->job.king.nbPeasants += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
action->com_data.data[0] = 's'; // "thou shall serve me as a soldier"
|
||||
Coord target = ARMY_POS;
|
||||
target.y -= data->job.king.nbSoldiers % 10;
|
||||
target.x -= data->job.king.nbSoldiers / 10;
|
||||
Coord* ptr = (Coord*)(action->com_data.data + 2);
|
||||
*ptr = target;
|
||||
*((int*)(action->com_data.data+11)) = -1;
|
||||
data->job.king.nbSoldiers += 1;
|
||||
|
||||
if(data->job.king.nbSoldiers % 10 == 9)
|
||||
{
|
||||
action->com_data.data[10] = 1; // "thou shall command the army to march on the corpses of our foes"
|
||||
*((int*)(action->com_data.data+11)) = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
action->com_data.data[0] = 'f'; // "you dare disturb me from my royal occupations ? Go "f" yourself !"
|
||||
|
||||
data->job.king.last_audience_dir = Dir(com->flag);
|
||||
action->dir = Dir(com->flag);
|
||||
action->type = Action::COMMUNICATE;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "receiving request : %s\ngiving job : %s", com->data, action->com_data.data);
|
||||
return;
|
||||
}
|
||||
case PEASANT :
|
||||
{
|
||||
if(data->job.peasant.tried_picking_up_food && success)
|
||||
data->job.peasant.brings_food = true;
|
||||
data->job.peasant.tried_picking_up_food = false;
|
||||
|
||||
if(data->job.peasant.brings_food){
|
||||
int distance = data->pos.dist();
|
||||
if(distance == 1){
|
||||
action->type = Action::MOVE;
|
||||
action->dir = NORTH;
|
||||
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == SPAWN){
|
||||
action->dir = Dir(i);
|
||||
action->type = Action::PUT;
|
||||
data->job.peasant.brings_food = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(data->pos + action->dir) > distance && distance != 0);
|
||||
|
||||
}
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "bringing food back to the spawn");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOLDIER :
|
||||
{
|
||||
Coord target = data->pos - data->job.soldier.target;
|
||||
int distance = target.dist();
|
||||
const Com* com = info->getCom();
|
||||
if(com != nullptr)
|
||||
{
|
||||
int charge_countdown = *((int*)(com->data));
|
||||
data->job.soldier.charge_countdown = charge_countdown;
|
||||
*((int*)(action->com_data.data))= charge_countdown - 1;
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->dir = Dir((com->flag+2)%4);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "receiving orders");
|
||||
}
|
||||
else if(distance == 0)
|
||||
{
|
||||
if(data->job.soldier.charge_countdown > 0)
|
||||
{
|
||||
if(data->job.soldier.commander)
|
||||
{
|
||||
data->job.soldier.commander = false;
|
||||
*((int*)(action->com_data.data))= data->job.soldier.charge_countdown;
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->dir = Dir(SOUTH);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "Notifying the troops that we are going into battle");
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
data->job.soldier.charge_countdown -= 1;
|
||||
sprintf(data->debugStr, "Charge in %d...", data->job.soldier.charge_countdown);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
sprintf(data->debugStr, "waiting orders");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(target + action->dir) > distance && distance != 0);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "going into formation");
|
||||
}
|
||||
data->last_action = action->type;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// wander around
|
||||
int blockedCount = 0;
|
||||
action->type = Action::MOVE;
|
||||
bool ok = false;
|
||||
do{
|
||||
action->dir = Dir((data->last_dir + rand()%3)%4);
|
||||
type = info->getNear(action->dir);
|
||||
ok = PixelProperty::isWalkable(type) && !((data->pos + Coord(action->dir)).x > 12); // do not interfere with military formations
|
||||
++blockedCount;
|
||||
if(blockedCount > 3)
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
ok = true;
|
||||
}
|
||||
}while(!ok);
|
||||
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "wandering around");
|
||||
}
|
393
behaviors/war_charge_west.cpp
Normal file
393
behaviors/war_charge_west.cpp
Normal file
@ -0,0 +1,393 @@
|
||||
#include <cstdlib>
|
||||
#include "behavior.h"
|
||||
|
||||
// g++ -shared war_charge_west.cpp -o war_charge_west.dll -std=c++11 -I../src
|
||||
|
||||
#define KING_POS Coord(2, 2)
|
||||
#define ARMY_POS Coord(-12, 4)
|
||||
#define CHARGE_DIR WEST
|
||||
|
||||
enum Purpose { NEWBORN, KING, PEASANT, SOLDIER };
|
||||
|
||||
struct KingMemory{ // 16 bytes
|
||||
int nbPeasants;
|
||||
int nbSoldiers;
|
||||
int date;
|
||||
Dir last_audience_dir;
|
||||
};
|
||||
|
||||
struct PeasantMemory{ // 8 bytes
|
||||
bool tried_picking_up_food;
|
||||
bool brings_food;
|
||||
};
|
||||
|
||||
struct SoldierMemory{ // 16 bytes
|
||||
Coord target;
|
||||
int charge_countdown;
|
||||
bool commander;
|
||||
};
|
||||
|
||||
union JobMemory { // 16 bytes
|
||||
KingMemory king;
|
||||
PeasantMemory peasant;
|
||||
SoldierMemory soldier;
|
||||
};
|
||||
|
||||
struct memory_data{ // 104 bytes
|
||||
// 40 bytes
|
||||
JobMemory job;
|
||||
Coord pos;
|
||||
bool new_born;
|
||||
int purpose;
|
||||
Dir last_dir;
|
||||
Action::Type last_action;
|
||||
// 64 bytes
|
||||
char debugStr[64];
|
||||
};
|
||||
|
||||
const char* PURPOSES_STRINGS[] {
|
||||
"Newborn",
|
||||
"King",
|
||||
"Peasant",
|
||||
"Soldier"
|
||||
};
|
||||
|
||||
extern "C" void debugOutput(char *outputString, const char *memory)
|
||||
{
|
||||
memory_data* data = (memory_data*)memory;
|
||||
sprintf(outputString, "%s\n%s", PURPOSES_STRINGS[data->purpose], data->debugStr);
|
||||
if(data->purpose == KING)
|
||||
{
|
||||
sprintf(outputString, "%s\nRuled the kingdom for %d ticks\npopulation :\n%d peasants\n%d soldiers",
|
||||
outputString, data->job.king.date, data->job.king.nbPeasants, data->job.king.nbSoldiers);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void think(Action *action, char *memory, const Info *info)
|
||||
{
|
||||
int i;
|
||||
PixelType type;
|
||||
|
||||
bool success = info->getSuccess();
|
||||
memory_data* data = (memory_data*)memory;
|
||||
data->debugStr[0] = '\0';
|
||||
|
||||
// if freshly spawned, init the position variable by looking in which direction is the spawn
|
||||
if(!data->new_born){
|
||||
success = false;
|
||||
data->new_born = true;
|
||||
for(i=0; i<4; i++)
|
||||
{
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == SPAWN)
|
||||
{
|
||||
data->pos = Coord(0) - Dir(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update position if last successful action was moving
|
||||
if(data->last_action == Action::MOVE){
|
||||
if(success)
|
||||
data->pos += data->last_dir;
|
||||
else
|
||||
{
|
||||
int blockedCount = 0;
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir((data->last_dir + rand()%3)%4);
|
||||
type = info->getNear(action->dir);
|
||||
++blockedCount;
|
||||
if(blockedCount > 3)
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
break;
|
||||
}
|
||||
}while(!PixelProperty::isWalkable(type));
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "moving around obstacle");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// work any workable resource when encountered
|
||||
if(data->purpose == SOLDIER && data->job.soldier.charge_countdown == 0)
|
||||
{
|
||||
action->dir = CHARGE_DIR;
|
||||
PixelType front = info->getNear(CHARGE_DIR);
|
||||
if(!PixelProperty::isWalkable(front))
|
||||
{
|
||||
if(PixelProperty::isDestructible(front))
|
||||
action->type = Action::ATTACK;
|
||||
else if(PixelProperty::isResource(front))
|
||||
{
|
||||
if(info->getInventory() != EMPTY)
|
||||
{
|
||||
action->type = Action::PUT;
|
||||
action->dir = Dir((CHARGE_DIR+2)%4);
|
||||
}
|
||||
else
|
||||
action->type = Action::PICK;
|
||||
}
|
||||
else
|
||||
action->type = Action::WORK;
|
||||
}
|
||||
else
|
||||
action->type = Action::MOVE;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "CHAAAAAAAAAARGE !");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == BERRIES || type == TREE || type == IRON_ORE || type == ROCK){
|
||||
action->type = Action::WORK;
|
||||
action->dir = Dir(i);
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "working on resource");
|
||||
return;
|
||||
}else if(type == FOOD && data->purpose == PEASANT
|
||||
&& !(data->job.peasant.brings_food) && !(data->job.peasant.tried_picking_up_food)){
|
||||
action->type = Action::PICK;
|
||||
action->dir = Dir(i);
|
||||
data->job.peasant.tried_picking_up_food = true;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "picking up food");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// do your job
|
||||
switch(data->purpose)
|
||||
{
|
||||
case NEWBORN :
|
||||
{
|
||||
const Com* com = info->getCom();
|
||||
if(com != nullptr) // no activity
|
||||
{
|
||||
switch(com->data[0])
|
||||
{
|
||||
case 'p': data->purpose = PEASANT; break;
|
||||
case 's':
|
||||
data->purpose = SOLDIER;
|
||||
data->job.soldier.target.x = *((int*)(com->data+2));
|
||||
data->job.soldier.target.y = *((int*)(com->data+6));
|
||||
data->job.soldier.commander = bool(com->data[10]);
|
||||
data->job.soldier.charge_countdown = *((int*)(com->data+11));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "receiving job : %s", com->data);
|
||||
return;
|
||||
}
|
||||
Coord target = data->pos - KING_POS;
|
||||
int distance = target.dist();
|
||||
if(distance == 0) // i am the new king
|
||||
{
|
||||
data->job.king.last_audience_dir = NO_DIR;
|
||||
data->purpose = KING;
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "I AM THE KING, LONG LIVE THE KING");
|
||||
return;
|
||||
}
|
||||
// if adjacent to the king's position, speak to the king if there is one
|
||||
if(distance == 1){
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(Coord(Dir((i+2)%4)) == target && type == DUDE){ // it is the king
|
||||
action->dir = Dir(i);
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->com_data.data[0] = 'n'; // "give me a purpose"
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "asking the king to give me a task");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// move to the king's position
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(target + action->dir) > distance && distance != 0);
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "walking to the king's throne");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case KING :
|
||||
{
|
||||
data->job.king.date += 1;
|
||||
const Com* com = info->getCom();
|
||||
if(com == nullptr || data->job.king.last_audience_dir == Dir(com->flag)) // no activity
|
||||
{
|
||||
data->job.king.last_audience_dir = NO_DIR;
|
||||
action->type = Action::WAIT;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "waiting for a subject to ask for an audience");
|
||||
return;
|
||||
}
|
||||
// someone requests an audience to the king
|
||||
char request = com->data[0];
|
||||
if(request == 'n')
|
||||
{
|
||||
int population = data->job.king.nbPeasants + data->job.king.nbSoldiers;
|
||||
if(population < 15 || data->job.king.nbPeasants < (2*population)/3)
|
||||
{
|
||||
action->com_data.data[0] = 'p'; // "thou shall be peasant"
|
||||
data->job.king.nbPeasants += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
action->com_data.data[0] = 's'; // "thou shall serve me as a soldier"
|
||||
Coord target = ARMY_POS;
|
||||
target.y -= data->job.king.nbSoldiers % 10;
|
||||
target.x -= data->job.king.nbSoldiers / 10;
|
||||
Coord* ptr = (Coord*)(action->com_data.data + 2);
|
||||
*ptr = target;
|
||||
*((int*)(action->com_data.data+11)) = -1;
|
||||
data->job.king.nbSoldiers += 1;
|
||||
|
||||
if(data->job.king.nbSoldiers % 10 == 9)
|
||||
{
|
||||
action->com_data.data[10] = 1; // "thou shall command the army to march on the corpses of our foes"
|
||||
*((int*)(action->com_data.data+11)) = 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
action->com_data.data[0] = 'f'; // "you dare disturb me from my royal occupations ? Go "f" yourself !"
|
||||
|
||||
data->job.king.last_audience_dir = Dir(com->flag);
|
||||
action->dir = Dir(com->flag);
|
||||
action->type = Action::COMMUNICATE;
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "receiving request : %s\ngiving job : %s", com->data, action->com_data.data);
|
||||
return;
|
||||
}
|
||||
case PEASANT :
|
||||
{
|
||||
if(data->job.peasant.tried_picking_up_food && success)
|
||||
data->job.peasant.brings_food = true;
|
||||
data->job.peasant.tried_picking_up_food = false;
|
||||
|
||||
if(data->job.peasant.brings_food){
|
||||
int distance = data->pos.dist();
|
||||
if(distance == 1){
|
||||
action->type = Action::MOVE;
|
||||
action->dir = NORTH;
|
||||
|
||||
for(i=0; i<4; i++){
|
||||
type = info->getNear(Dir(i));
|
||||
if(type == SPAWN){
|
||||
action->dir = Dir(i);
|
||||
action->type = Action::PUT;
|
||||
data->job.peasant.brings_food = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(data->pos + action->dir) > distance && distance != 0);
|
||||
|
||||
}
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "bringing food back to the spawn");
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SOLDIER :
|
||||
{
|
||||
Coord target = data->pos - data->job.soldier.target;
|
||||
int distance = target.dist();
|
||||
const Com* com = info->getCom();
|
||||
if(com != nullptr)
|
||||
{
|
||||
int charge_countdown = *((int*)(com->data));
|
||||
data->job.soldier.charge_countdown = charge_countdown;
|
||||
*((int*)(action->com_data.data))= charge_countdown - 1;
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->dir = Dir((com->flag+2)%4);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "receiving orders");
|
||||
}
|
||||
else if(distance == 0)
|
||||
{
|
||||
if(data->job.soldier.charge_countdown > 0)
|
||||
{
|
||||
if(data->job.soldier.commander)
|
||||
{
|
||||
data->job.soldier.commander = false;
|
||||
*((int*)(action->com_data.data))= data->job.soldier.charge_countdown;
|
||||
action->type = Action::COMMUNICATE;
|
||||
action->dir = Dir(SOUTH);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "Notifying the troops that we are going into battle");
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
data->job.soldier.charge_countdown -= 1;
|
||||
sprintf(data->debugStr, "Charge in %d...", data->job.soldier.charge_countdown);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
sprintf(data->debugStr, "waiting orders");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
action->type = Action::MOVE;
|
||||
do{
|
||||
action->dir = Dir( rand() % 4 );
|
||||
}while(~(target + action->dir) > distance && distance != 0);
|
||||
data->last_dir = action->dir;
|
||||
sprintf(data->debugStr, "going into formation");
|
||||
}
|
||||
data->last_action = action->type;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// wander around
|
||||
int blockedCount = 0;
|
||||
action->type = Action::MOVE;
|
||||
bool ok = false;
|
||||
do{
|
||||
action->dir = Dir((data->last_dir + rand()%3)%4);
|
||||
type = info->getNear(action->dir);
|
||||
ok = PixelProperty::isWalkable(type) && !((data->pos + Coord(action->dir)).x < -12); // do not interfere with military formations
|
||||
++blockedCount;
|
||||
if(blockedCount > 3)
|
||||
{
|
||||
action->type = Action::WAIT;
|
||||
ok = true;
|
||||
}
|
||||
}while(!ok);
|
||||
|
||||
data->last_dir = action->dir;
|
||||
data->last_action = action->type;
|
||||
sprintf(data->debugStr, "wandering around");
|
||||
}
|
16
src/dude.cpp
16
src/dude.cpp
@ -23,21 +23,27 @@ Dude::Dude(const Coord &_pos, Map *_map, const int &_team) :
|
||||
p_map->getPixel(m_pos).data.dudePtr = this;
|
||||
}
|
||||
|
||||
void Dude::perish()
|
||||
{
|
||||
m_dead = true;
|
||||
Pixel& p = p_map->getPixel(m_pos);
|
||||
p.type = DEAD_DUDE;
|
||||
}
|
||||
|
||||
void Dude::move(Dir d)
|
||||
{
|
||||
p_map->getPixel(m_pos).type = m_under;
|
||||
//if(PixelProperty::isResource(m_under))
|
||||
// p_map->getPixel(m_pos).data.nbRes = m_underResCount;
|
||||
p_map->getPixel(m_pos).data.dudePtr = NULL;
|
||||
|
||||
m_pos += Coord(d);
|
||||
|
||||
m_pos = p_map->toreillerLoop(m_pos + Coord(d));
|
||||
|
||||
m_under = p_map->getPixel(m_pos).type;
|
||||
//if(PixelProperty::isResource(m_under))
|
||||
// m_underResCount = p_map->getPixel(m_pos).data.nbRes;
|
||||
p_map->getPixel(m_pos).type = DUDE;
|
||||
p_map->getPixel(m_pos).data.dudePtr = this;
|
||||
p_map->toreillerLoop(m_pos);
|
||||
}
|
||||
|
||||
void Dude::receiveComData(Dir dir, const char *data)
|
||||
@ -61,10 +67,10 @@ void Dude::debugOutput(char *outputString, DebugBehaviorFunction func)
|
||||
|
||||
PixelType Dude::getNear(Dir d) const
|
||||
{
|
||||
return p_map->getPixel(Coord(d) + m_pos).type;
|
||||
return p_map->getPixel(p_map->toreillerLoop(Coord(d) + m_pos)).type;
|
||||
}
|
||||
|
||||
int Dude::getInfo(Dir d) const
|
||||
{
|
||||
return p_map->getPixel(Coord(d) + m_pos).data.nbRes;
|
||||
return p_map->getPixel(p_map->toreillerLoop(Coord(d) + m_pos)).data.nbRes;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
|
||||
//life-related function
|
||||
bool isAlive() { return !m_dead; }
|
||||
void perish() { m_dead = true; }
|
||||
void perish();
|
||||
|
||||
//movement-related function
|
||||
const Coord& getPos() { return m_pos; }
|
||||
|
@ -65,6 +65,7 @@ void Simulation::update()
|
||||
}
|
||||
|
||||
resolveBattles();
|
||||
removeDead();
|
||||
|
||||
// for each team, spawn dude if condition met
|
||||
for(unsigned int i=0; i<m_teams.size(); ++i){
|
||||
@ -203,6 +204,21 @@ void Simulation::handleAction(Dude *dude)
|
||||
else
|
||||
dude->setSuccess(false);
|
||||
break;
|
||||
case DEAD_DUDE:
|
||||
{
|
||||
PixelType inventory = target.data.dudePtr->getInventory();
|
||||
m_dead_dudes.emplace(target.data.dudePtr);
|
||||
target.data.dudePtr = nullptr;
|
||||
if(inventory != EMPTY)
|
||||
{
|
||||
target.type = inventory;
|
||||
target.data.nbRes = 1;
|
||||
}
|
||||
else
|
||||
target.type = GRASS;
|
||||
dude->setSuccess(false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dude->setSuccess(false);
|
||||
break;
|
||||
@ -247,32 +263,51 @@ void Simulation::handleAction(Dude *dude)
|
||||
}
|
||||
}
|
||||
|
||||
void Simulation::removeDead()
|
||||
{
|
||||
for(unsigned int i=0; i<m_dudes.size(); ++i)
|
||||
{
|
||||
Dude* d = m_dudes[i];
|
||||
if(m_dead_dudes.count(d))
|
||||
{
|
||||
m_dead_dudes.erase(d);
|
||||
delete d;
|
||||
m_dudes[i] = m_dudes[m_dudes.size()-1];
|
||||
m_dudes.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: verify if battle resolution work
|
||||
void Simulation::resolveBattles(){
|
||||
for (Battle battle : m_battles){
|
||||
bool attackerWins = true;
|
||||
Dude *attacker = battle.first, *defender = battle.second;
|
||||
if (defender->isAlive() && defender->getAction().type == Action::ATTACK){
|
||||
if (attacker->getPos() == defender->getPos() + Coord(defender->getAction().dir)){
|
||||
bool armedAttacker = attacker->getInventory() == PixelType::SWORD, armedDefender = defender->getInventory() == PixelType::SWORD;
|
||||
if (armedAttacker == armedDefender){
|
||||
if ((rand()%100 + 1) > 50)
|
||||
attacker->perish();
|
||||
else
|
||||
defender->perish();
|
||||
attackerWins = false;
|
||||
}else if(armedAttacker){
|
||||
if ((rand()%100 + 1) > 80)
|
||||
attacker->perish();
|
||||
else
|
||||
defender->perish();
|
||||
attackerWins = false;
|
||||
}else if(armedDefender){
|
||||
if ((rand()%100 + 1) > 20)
|
||||
attacker->perish();
|
||||
else
|
||||
defender->perish();
|
||||
attackerWins = false;
|
||||
}
|
||||
}else
|
||||
defender->perish();
|
||||
}else
|
||||
}
|
||||
}
|
||||
if(attackerWins)
|
||||
{
|
||||
defender->perish();
|
||||
p_map->updatePixel(defender->getPos());
|
||||
}
|
||||
else
|
||||
{
|
||||
attacker->perish();
|
||||
p_map->updatePixel(attacker->getPos());
|
||||
}
|
||||
}
|
||||
m_battles.clear();
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ private:
|
||||
std::vector<Dude*> m_dudes;
|
||||
std::vector<Team> m_teams;
|
||||
std::set<Battle,battleComparator> m_battles;
|
||||
std::set<Dude*> m_dead_dudes;
|
||||
|
||||
void handleAction(Dude* dude);
|
||||
void removeDead();
|
||||
void resolveBattles();
|
||||
|
||||
public:
|
||||
|
Loading…
x
Reference in New Issue
Block a user