fixed plenty of bugs, added agressive behavior

This commit is contained in:
Anselme 2017-02-27 11:36:02 +01:00
parent cad7cc19a2
commit b6379dcc1f
6 changed files with 847 additions and 18 deletions

View 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");
}

View 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");
}

View File

@ -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;
}

View File

@ -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; }

View File

@ -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();
}

View File

@ -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: