Greetings,
First I want to say that this is not a bug or problem, the game is running fine and the AI is working as expected in termos of final result. The problem is that I wanted it to "look a bit different".
The game is turn-based and uses regular quads for tiles in the map. When player ends its turn, a function from the enemy class is called a number of times equal to the total number of instantiated enemies, on the game loop.
Inside this function a given behavior is iterated a number of times equal the total amount of movement for that enemy unit. Here is the parts of the code I´ve mentioned:
The part in which the artificial inteligence procedure is called (it is inside the game loop):
//EXECUTA IA NO TURNO DO COMPUTADOR
if (jogador->turno == false) // mapa global e turno do computador
{
for (i=0;i<50;i++)
{
saxoes[i].executarInteligenciaArtificial(vikings, gerenciador, conversorString);
}
//Depois de atribuir ações para todos os inimigos reinicia o turno do jogador
jogador->iniciarTurno(vikings);
gerenciador->txtMensagem.SetColor(sf::Color(220,220,0));
//Verifica as condições de vitória
if (motor->condicaoDeVitoria(saxoes,cidades))
{
gerenciador->txtMensagem.SetColor(sf::Color(220,220,0));
gerenciador->txtMensagem.SetText("VITÓRIA! Inglaterra agora é Daneland! (ESC) SAIR");
motor->setEstadoGlobal(3);
}
//Verifica as condições de derrota
if (motor->condicaoDeDerrota(vikings))
{
gerenciador->txtMensagem.SetColor(sf::Color(220,220,0));
gerenciador->txtMensagem.SetText("DERROTA! Festeje no Castelo dos Mortos em Asgard! (ESC) SAIR");
motor->setEstadoGlobal(4);
}
}
This one is the function of the Saxao class that represents the saxon enemies:
void executarInteligenciaArtificial(Guerreiro *vikings, ResourceManager *gerenciador, StringConverter *conversorString)
{
gerenciador->txtMensagem.SetColor(sf::Color(220,0,0));
int cont;
int cont2;
int direcao;
int alvo;
//sf::Clock timer;
//timer.Reset();
if (inteligenciaArtificial == 1 && vivo)
{
for (cont=0;cont<50;cont++)
{
if (vikings[cont].vivo && tileX - vikings[cont].tileX <= alcanceVisao && tileX - vikings[cont].tileX >= -alcanceVisao && tileY - vikings[cont].tileY <= alcanceVisao && tileY - vikings[cont].tileY >= -alcanceVisao)
{
for (cont2 = 0; cont2 < movTotal; cont2++)
{
if (vikings[cont].tileX < tileX && vikings[cont].tileY < tileY)
{
direcao = sf::Randomizer::Random(1,2);
if (direcao == 1) tileX -= 1;
else tileY -= 1;
}
else if (vikings[cont].tileX > tileX && vikings[cont].tileY < tileY)
{
direcao = sf::Randomizer::Random(1,2);
if (direcao == 1) tileX += 1;
else tileY -= 1;
}
else if (vikings[cont].tileX > tileX && vikings[cont].tileY > tileY)
{
direcao = sf::Randomizer::Random(1,2);
if (direcao == 1) tileX += 1;
else tileY += 1;
}
else if (vikings[cont].tileX < tileX && vikings[cont].tileY > tileY)
{
direcao = sf::Randomizer::Random(1,2);
if (direcao == 1) tileX -= 1;
else tileY += 1;
}
else if (vikings[cont].tileX < tileX && vikings[cont].tileY == tileY)
{
tileX -= 1;
}
else if (vikings[cont].tileX == tileX && vikings[cont].tileY < tileY)
{
tileY -= 1;
}
else if (vikings[cont].tileX > tileX && vikings[cont].tileY == tileY)
{
tileX += 1;
}
else if (vikings[cont].tileX == tileX && vikings[cont].tileY > tileY)
{
tileY += 1;
}
//Ataca se possivel
if(vikings[cont].tileX == tileX && vikings[cont].tileY == tileY)
{
if (atacar(vikings[cont].defesa))
{
//atacou acertou e matou
if (vikings[cont].receberDano(aplicarDano())) gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(7,nome.GetText(),vikings[cont].nome.GetText()));
//atacou e acertou mas não matou
else gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(6,nome.GetText(),vikings[cont].nome.GetText()));
}
//Atacou mas não acertou
else gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(8,nome.GetText(),vikings[cont].nome.GetText()));
}
}
//Corrige a posição do inimigo ao final do seu turno
if(vikings[cont].tileX == tileX && vikings[cont].tileY == tileY) tileX += 1;
}
}
}
//Instancia defensiva
if (inteligenciaArtificial == 2 && vivo)
{
for (cont=0;cont<50;cont++)
{
if (vikings[cont].vivo && tileX - vikings[cont].tileX <= 1 && tileX - vikings[cont].tileX >= -1 && tileY - vikings[cont].tileY <= 1 && tileY - vikings[cont].tileY >= -1)
{
for (cont2 = 0; cont2 < movTotal; cont2++)
{
//Ataca se possivel
if (atacar(vikings[cont].defesa))
{
//atacou acertou e matou
if (vikings[cont].receberDano(aplicarDano())) gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(7,nome.GetText(),vikings[cont].nome.GetText()));
//atacou e acertou mas não matou
else gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(6,nome.GetText(),vikings[cont].nome.GetText()));
}
//Atacou mas não acertou
else gerenciador->txtMensagem.SetText(conversorString->concatenarMensagem(8,nome.GetText(),vikings[cont].nome.GetText()));
}
}
}
}
}
The issue is that I wanted the enemy movement to happen slowly enough so that the player could notice enemy moves. The actual code makes the enemy turn almost instantly finished.
I tried something with timers but something went wrong and it crashes... maybe someone faced a similar situation and could share with me his/her opinion.
Thanks
obs: Sorry for any bad english, I speak portuguese natively.