游戏编程中的人工智能技术-演化算法入门
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;
}
演化算法的思路就是让弱小的生命体“死亡”,再让强大的生命体代替“死亡”的生命体,从而保证种群的一直延续,并且,生命体基于求生的本能,避免被“死亡”,会衍生出各种叹为观止的新行为,称之为生物的多样性。因此,演化算法的思路可以概括为:如何筛选弱小的生命体进行“死亡”操作(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;
}
相关文章推荐
- 2016 Multi-University Training Contest 1
- HDU5723 2016 Multi-University Training Contest 1 (最小生成树+dfs)
- main函数的参数和返回值
- baidu地图sdk使用(3)自定义定位图标
- No grammar constraints (DTD or XML Schema) 解决
- Naive的Spark优化
- smail记录
- UVA 10780-Again Prime? No Time.
- 线程obj.wait()和obj.notify()详解.
- AIX常用文章集锦
- AIX常用命令汇总
- AIX常见问题整理(二)
- 游戏编程中的人工智能技术-神经网络入门(四)
- Failed to lookup provider 'shm' for 'slotmem': is mod_slotmem_shm loaded??
- 如何解决linux下apache启动时httpd: apr_sockaddr_info_get() failed for 报错
- HDU - 1021 Fibonacci Again
- 游戏编程中的人工智能技术-神经网络入门(三)
- 2016 Multi-University Training Contest 1
- Container With Most Water
- HDU 5733 tetrahedron (2016 Multi-University Training Contest 1 计算几何)