RetroArch/deps/game_ai_lib/games/NHL94GameAI.cpp

225 lines
7.0 KiB
C++

#include "NHL94GameAI.h"
#include <cstdlib>
#include <iostream>
#include <assert.h>
#include <random>
//=======================================================
// NHL94GameAI::Init
//=======================================================
void NHL94GameAI::Init(void * ram_ptr, int ram_size)
{
LoadConfig();
InitRAM(ram_ptr, ram_size);
static_assert(NHL94NeuralNetInput::NN_INPUT_MAX == 16);
isShooting = false;
}
//=======================================================
// NHL94GameAI::SetModelInputs
//=======================================================
void NHL94GameAI::SetModelInputs(std::vector<float> & input, const NHL94Data & data)
{
// players
input[NHL94NeuralNetInput::P1_X] = (float)data.p1_x / (float) NHL94NeuralNetInput::MAX_PLAYER_X;
input[NHL94NeuralNetInput::P1_Y] = (float)data.p1_y / (float) NHL94NeuralNetInput::MAX_PLAYER_Y;
input[NHL94NeuralNetInput::P2_X] = (float)data.p2_x / (float) NHL94NeuralNetInput::MAX_PLAYER_X;
input[NHL94NeuralNetInput::P2_Y] = (float) data.p2_y / (float) NHL94NeuralNetInput::MAX_PLAYER_Y;
input[NHL94NeuralNetInput::G2_X] = (float) data.g2_x / (float) NHL94NeuralNetInput::MAX_PLAYER_X;
input[NHL94NeuralNetInput::G2_Y] = (float) data.g2_y / (float) NHL94NeuralNetInput::MAX_PLAYER_Y;
input[NHL94NeuralNetInput::P1_VEL_X] = (float) data.p1_vel_x / (float) NHL94NeuralNetInput::MAX_VEL_XY;
input[NHL94NeuralNetInput::P1_VEL_Y] = (float) data.p1_vel_y / (float) NHL94NeuralNetInput::MAX_VEL_XY;
input[NHL94NeuralNetInput::P2_VEL_X] = (float) data.p2_vel_x / (float) NHL94NeuralNetInput::MAX_VEL_XY;
input[NHL94NeuralNetInput::P2_VEL_Y] = (float) data.p2_vel_y / (float) NHL94NeuralNetInput::MAX_VEL_XY;
// puck
input[NHL94NeuralNetInput::PUCK_X] = (float) data.puck_x / (float) NHL94NeuralNetInput::MAX_PLAYER_X;
input[NHL94NeuralNetInput::PUCK_Y] = (float) data.puck_y / (float) NHL94NeuralNetInput::MAX_PLAYER_Y;
input[NHL94NeuralNetInput::PUCK_VEL_X] = (float) data.puck_vel_x / (float) NHL94NeuralNetInput::MAX_VEL_XY;
input[NHL94NeuralNetInput::PUCK_VEL_Y] = (float) data.puck_vel_y / (float) NHL94NeuralNetInput::MAX_VEL_XY;
input[NHL94NeuralNetInput::P1_HASPUCK] = data.p1_haspuck ? 0.0 : 1.0;
input[NHL94NeuralNetInput::G1_HASPUCK] = data.g1_haspuck ? 0.0 : 1.0;
}
//=======================================================
// NHL94GameAI::GotoTarget
//=======================================================
void NHL94GameAI::GotoTarget(std::vector<float> & input, int vec_x, int vec_y)
{
if (vec_x > 0)
input[NHL94Buttons::INPUT_LEFT] = 1;
else
input[NHL94Buttons::INPUT_RIGHT] = 1;
if (vec_y > 0)
input[NHL94Buttons::INPUT_DOWN] = 1;
else
input[NHL94Buttons::INPUT_UP] = 1;
}
//=======================================================
// isInsideAttackZone
//=======================================================
static bool isInsideAttackZone(NHL94Data & data)
{
if (data.attack_zone_y > 0 && data.p1_y >= data.attack_zone_y)
{
return true;
}
else if (data.attack_zone_y < 0 && data.p1_y <= data.attack_zone_y)
{
return true;
}
return false;
}
//=======================================================
// isInsideScoreZone
//=======================================================
static bool isInsideScoreZone(NHL94Data & data)
{
if (data.p1_y < data.score_zone_top && data.p1_y > data.score_zone_bottom)
{
return true;
}
return false;
}
//=======================================================
// isInsideDefenseZone
//=======================================================
static bool isInsideDefenseZone(NHL94Data & data)
{
if (data.defense_zone_y > 0 && data.p1_y >= data.defense_zone_y)
{
return true;
}
else if (data.defense_zone_y < 0 && data.p1_y <= data.defense_zone_y)
{
return true;
}
return false;
}
//=======================================================
// NHL94GameAI::Think
//=======================================================
void NHL94GameAI::Think(bool buttons[GAMEAI_MAX_BUTTONS], int player, const void *frame_data, unsigned int frame_width, unsigned int frame_height, unsigned int frame_pitch, unsigned int pixel_format)
{
NHL94Data data;
data.Init(retro_data);
if(player == 1)
{
data.Flip();
if(data.period % 2 == 0)
{
data.FlipZones();
}
}
else if (player == 0)
{
if(data.period % 2 == 1)
{
data.FlipZones();
}
}
std::vector<float> input(16);
std::vector<float> output(12);
this->SetModelInputs(input, data);
if (data.p1_haspuck)
{
DebugPrint("have puck");
if (isInsideAttackZone(data))
{
DebugPrint(" in attackzone");
models["ScoreGoal"]->Forward(output, input);
output[NHL94Buttons::INPUT_C] = 0;
output[NHL94Buttons::INPUT_B] = 0;
if (isInsideScoreZone(data))
{
if (data.p1_vel_x >= 30 && data.puck_x > -23 && data.puck_x < 0)
{
DebugPrint("Shoot");
output[NHL94Buttons::INPUT_C] = 1;
isShooting = true;
}
else if(data.p1_vel_x <= -30 && data.puck_x < 23 && data.puck_x > 0)
{
DebugPrint("Shoot");
output[NHL94Buttons::INPUT_C] = 1;
isShooting = true;
}
}
}
else
{
this->GotoTarget(output, data.p1_x, -data.attack_zone_y);
}
}
else if (data.g1_haspuck)
{
if (rand() > (RAND_MAX / 2))
output[NHL94Buttons::INPUT_B] = 1;
}
else
{
DebugPrint("Don't have puck");
isShooting = false;
if (isInsideDefenseZone(data) && data.p2_haspuck)
{
DebugPrint(" DefenseModel->Forward");
models["DefenseZone"]->Forward(output, input);
}
else
{
DebugPrint(" GOTO TARGET");
GotoTarget(output, data.p1_x - data.puck_x, data.p1_y - data.puck_y);
}
if (isShooting)
{
//output[NHL94Buttons::INPUT_MODE] = 1;
DebugPrint("Shooting");
output[NHL94Buttons::INPUT_C] = 1;
}
}
assert(output.size() <= 16);
for (int i=0; i < output.size(); i++)
{
buttons[i] = output[i] >= 1.0 ? 1 : 0;
}
buttons[NHL94Buttons::INPUT_START] = 0;
buttons[NHL94Buttons::INPUT_MODE] = 0;
buttons[NHL94Buttons::INPUT_A] = 0;
//buttons[NHL94Buttons::INPUT_B] = 0;
//buttons[NHL94Buttons::INPUT_C] = 0;
buttons[NHL94Buttons::INPUT_X] = 0;
buttons[NHL94Buttons::INPUT_Y] = 0;
buttons[NHL94Buttons::INPUT_Z] = 0;
//Flip directions
if(data.period % 2 != player)
{
std::swap(buttons[NHL94Buttons::INPUT_UP], buttons[NHL94Buttons::INPUT_DOWN]);
std::swap(buttons[NHL94Buttons::INPUT_LEFT], buttons[NHL94Buttons::INPUT_RIGHT]);
}
}