您的位置:首页 > 大数据 > 人工智能

游戏编程中的人工智能技术-演化算法入门

2016-07-20 09:09 591 查看
   buckland大神的每一章都很经典,少了任何一章都会感到不完整。今天先介绍第十章-演化算法。因为这是人工生命的基础。大名鼎鼎的tierra就是采用了演化算法。(什么是Tierra?看这里点击打开链接

    演化算法的思路就是让弱小的生命体“死亡”,再让强大的生命体代替“死亡”的生命体,从而保证种群的一直延续,并且,生命体基于求生的本能,避免被“死亡”,会衍生出各种叹为观止的新行为,称之为生物的多样性。因此,演化算法的思路可以概括为:如何筛选弱小的生命体进行“死亡”操作(Tierra里称之为“死神”、“收割机”),以及如何用强大的生命体进行替代。

    若想让生命体“死亡”,除了创建一个std::vector作为种群外,还必须创建另一个向量std::multiset,称之为“池”。“池”中的生命体不是显示在游戏屏幕上的,而是在后台运作的一个“母体”,因为游戏画面上所有的生命体都是从“池”中孵化得来的,弱小的即将被杀死的生命体也会丢弃到这个池中等待“死神”“收割”。替代死亡生命体也是从“池”中选出的最强壮的生命体。因此,“池”必须具备两个特征:

    (1)“池”中生命体的数量必定比游戏画面上“种群”中生命体的数量要大的多。

    (2)“池”必须是有序向量,这样才能简便的分辩谁是弱小生命体,谁是强壮生命体。

    ok,闲话不多说,直接进入代码。本节中只介绍关于演化的那一部分,其他部分,例如外星人部分,神经网络部分等不在介绍。

    先看相关参数设定。

class CController
{
private:

//the player's gun
CGun* m_pGunTurret;

//the pool of aliens
multiset<CAlien> m_setAliens; //设定“基因组池”,使用multiset容器,利用二叉树实现,详细内容参见教材P235页

//the currently active aliens
vector<CAlien> m_vecActiveAliens;//这个是显示在游戏画面上的种群

int m_iAliensCreatedSoFar;

int m_iNumSpawnedFromTheMultiset;

//vertex buffer for the stars
vector<SPoint> m_vecStarVB;

//keeps track of the window size
int m_cxClient,
m_cyClient;

//lets the program run as fast as possible
bool m_bFastRender;

//custom pens used for drawing the game objects
HPEN m_GreenPen;
HPEN m_RedPen;
HPEN m_GunPen;
HPEN m_BarPen;

void WorldTransform(vector<SPoint> &pad);

CAlien TournamentSelection();

public:

CController(int cxClient, int cyClient);

~CController();

//The workhorse of the program. Updates all the game objects and
//spawns new aliens into the population.
bool Update();//演化计算在这里

void Render(HDC &surface);

//resets all the controller variables and creates a new starting
//population of aliens, ready for another run
void Reset();

//-----------------------------accessor functions
bool FastRender(){return m_bFastRender;}
};接下来介绍演化计算相关的Update程序。
//------------------------------- Update ---------------------------------
//
// The workhorse of the program. Updates all the game objects and
// spawns new aliens into the population.
//------------------------------------------------------------------------
bool CController::Update()
{

//switch the autogun off if enough offspring have been
//spawned
if (m_iNumSpawnedFromTheMultiset > CParams::iPreSpawns)
{
m_pGunTurret->AutoGunOff();

m_bFastRender = false;
}

//get update from player for the turret movement
//and update any bullets that may have been fired
m_pGunTurret->Update();

//move the stars
for (int str=0; str<m_vecStarVB.size(); ++str)
{
m_vecStarVB[str].y -= 0.2f;

if (m_vecStarVB[str].y < 0)
{
//create a new star
m_vecStarVB[str].x = RandInt(0, CParams::WindowWidth);
m_vecStarVB[str].y = CParams::WindowHeight;
}
}

//update the aliens
for (int i=0; i<m_vecActiveAliens.size(); ++i)
{

//if alien has 'died' replace with a new one
if (!m_vecActiveAliens[i].Update(m_pGunTurret->m_vecBullets,
m_pGunTurret->m_vPos))//如果外星人“死”了
{

//first we need to re-insert into the breeding population so
//that its fitness score and genes are recorded.
m_setAliens.insert(m_vecActiveAliens[i]);//将死去的外星人插入“池”中

//if the required population size has been reached, delete the
//worst performer from the multiset
if (m_setAliens.size() >= CParams::iPopSize)//如果池中的数目满了,iPopSize是池中生命体最大数量
{
m_setAliens.erase(--m_setAliens.end()); //将池中最后的,也就是适应度最差的外星人删去,即“收割”操作
}

++m_iNumSpawnedFromTheMultiset;

//if early in the run then we are still trying out new aliens
if (m_iAliensCreatedSoFar <= CParams::iPopSize)//如果刚开始,池中的生命体还没满的话,就新建一个生命体,来替代死去的
{
m_vecActiveAliens[i] = CAlien();

++m_iAliensCreatedSoFar;
}

//otherwise select from the multiset and apply mutation,如果池中生命体满了的话,就从池中进行精英选择,来替代死去的
else
{
m_vecActiveAliens[i] = TournamentSelection();

m_vecActiveAliens[i].Reset();

if (RandFloat() < 0.8)
{
m_vecActiveAliens[i].Mutate();
}
}
}
}//next alien

return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: