编译  Bot        来源  GitHub

这是一个允许你在几乎任何街机游戏中训练你的强化学习算法的Python库,它目前在Linux系统上可用。通过这个工具包,你可以定制算法逐步完成游戏过程,同时接收每一帧的数据和内部存储器地址值以跟踪游戏状态,以及发送与游戏交互的动作。

安装

GitHub地址:github.com/M-J-Murray/MAMEToolkit/blob/master/README.md

你可以用pip安装这个库,只需运行以下命令:


 
  1. pip install MAMEToolkit

演示示例:街霸

在街机爱好者心中,街霸是史上最经典的游戏之一。现在工具包内包含的街霸版本是街头霸王3:三度冲击(Japan 990608, NO CD),我们以此为例,用以下代码写一个随机智能体:


 
  1. import random

  2. from MAMEToolkit.sf_environment import Environment

  3.  

  4. roms_path = "roms/"

  5. env = Environment("env1", roms_path)

  6. env.start()

  7. while True:

  8.    move_action = random.randint(0, 8)

  9.    attack_action = random.randint(0, 9)

  10.    frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)

  11.    if game_done:

  12.        env.new_game()

  13.    elif stage_done:

  14.        env.next_stage()

  15.    elif round_done:

  16.        env.next_round()

这个工具包还支持hogwild!训练:


 
  1. from threading import Thread

  2. import random

  3. from MAMEToolkit.sf_environment import Environment

  4.  

  5.  

  6. def run_env(env):

  7.    env.start()

  8.    while True:

  9.        move_action = random.randint(0, 8)

  10.        attack_action = random.randint(0, 9)

  11.        frames, reward, round_done, stage_done, game_done = env.step(move_action, attack_action)

  12.        if game_done:

  13.            env.new_game()

  14.        elif stage_done:

  15.            env.next_stage()

  16.        elif round_done:

  17.            env.next_round()

  18.  

  19.  

  20. def main():

  21.    workers = 8

  22.    # Environments must be created outside of the threads

  23.    roms_path = "roms/"

  24.    envs = [Environment(f"env{i}", roms_path) for i in range(workers)]

  25.    threads = [Thread(target=run_env, args=(envs[i], )) for i in range(workers)]

  26.    [thread.start() for thread in threads]

 

 

建立自己的游戏环境

这个工具包之所以易于上手,是因为它和模拟器本身不需要太多交互,只需注意两点——一是查找你关注的内部状态相关联的内存地址值,二是用选取的环境跟踪状态。你可以用MAME Cheat Debugger,它会反馈游戏的内存地址值如何随时间变化。如果要创建游戏模拟,你得先获得正在模拟的游戏的ROM,并知道MAME使用的游戏ID,比如街霸的ID是'sfiii3n'。

游戏ID

你可以通过运行以下代码找到游戏的ID:


 
  1. from MAMEToolkit.emulator import Emulator

  2. emulator = Emulator("env1", "", "", memory_addresses)

这个命令会打开MAME仿真器。你可以搜索游戏列表以找到想要的游戏,游戏的ID位于游戏标题末尾的括号中。

内存地址

如果获得了ID,也有了想要跟踪的内存地址,你可以开始模拟:


 
  1. from MAMEToolkit.emulator import Emulator

  2. from MAMEToolkit.emulator import Address

  3.  

  4. roms_path = "roms/"

  5. game_id = "sfiii3n"

  6. memory_addresses = {

  7.        "fighting": Address('0x0200EE44', 'u8'),

  8.        "winsP1": Address('0x02011383', 'u8'),

  9.        "winsP2": Address('0x02011385', 'u8'),

  10.        "healthP1": Address('0x02068D0B', 's8'),

  11.        "healthP2": Address('0x020691A3', 's8')

  12.    }

  13.  

  14. emulator = Emulator("env1", roms_path, "sfiii3n", memory_addresses)

这会启动仿真器,并在工具包连接到模拟器进程时暂停。

分步运行仿真器

连接工具箱后,你可以分步运行仿真器:


 
  1. data = emulator.step([])

  2.  

  3. frame = data["frame"]

  4. is_fighting = data["fighting"]

  5. player1_wins = data["winsP1"]

  6. player2_wins = data["winsP2"]

  7. player1_health = data["healthP1"]

  8. player2_health = data["healthP2"]

step函数会把帧数据作为NumPy矩阵返回,同时,它也会返回该时间步长的所有内存地址整数值。

如果要向仿真器输入动作,你还需要确定游戏支持的输入端口和字段。比如玩街霸需要先投币,这个代码是:


 
  1. from MAMEToolkit.emulator import Action

  2.  

  3. insert_coin = Action(':INPUTS', 'Coin 1')

  4. data = emulator.step([insert_coin])

要确定哪些端口可用,请使用list actions命令:


 
  1. from MAMEToolkit.emulator import list_actions

  2.  

  3. roms_path = "roms/"

  4. game_id = "sfiii3n"

  5. print(list_actions(roms_path, game_id))

下面这个返回的列表就包含街霸环境中可用于向步骤函数发送动作的所有端口和字段:


 
  1. [

  2.    {'port': ':scsi:1:cdrom:SCSI_ID', 'field': 'SCSI ID'},

  3.    {'port': ':INPUTS', 'field': 'P2 Jab Punch'},

  4.    {'port': ':INPUTS', 'field': 'P1 Left'},

  5.    {'port': ':INPUTS', 'field': 'P2 Fierce Punch'},

  6.    {'port': ':INPUTS', 'field': 'P1 Down'},

  7.    {'port': ':INPUTS', 'field': 'P2 Down'},

  8.    {'port': ':INPUTS', 'field': 'P2 Roundhouse Kick'},

  9.    {'port': ':INPUTS', 'field': 'P2 Strong Punch'},

  10.    {'port': ':INPUTS', 'field': 'P1 Strong Punch'},

  11.    {'port': ':INPUTS', 'field': '2 Players Start'},

  12.    {'port': ':INPUTS', 'field': 'Coin 1'},

  13.    {'port': ':INPUTS', 'field': '1 Player Start'},

  14.    {'port': ':INPUTS', 'field': 'P2 Right'},

  15.    {'port': ':INPUTS', 'field': 'Service 1'},

  16.    {'port': ':INPUTS', 'field': 'Coin 2'},

  17.    {'port': ':INPUTS', 'field': 'P1 Jab Punch'},

  18.    {'port': ':INPUTS', 'field': 'P2 Up'},

  19.    {'port': ':INPUTS', 'field': 'P1 Up'},

  20.    {'port': ':INPUTS', 'field': 'P1 Right'},

  21.    {'port': ':INPUTS', 'field': 'Service Mode'},

  22.    {'port': ':INPUTS', 'field': 'P1 Fierce Punch'},

  23.    {'port': ':INPUTS', 'field': 'P2 Left'},

  24.    {'port': ':EXTRA', 'field': 'P2 Short Kick'},

  25.    {'port': ':EXTRA', 'field': 'P2 Forward Kick'},

  26.    {'port': ':EXTRA', 'field': 'P1 Forward Kick'},

  27.    {'port': ':EXTRA', 'field': 'P1 Roundhouse Kick'},

  28.    {'port': ':EXTRA', 'field': 'P1 Short Kick'}

  29. ]

仿真器类还有一个frame_ratio参数,可用于调整算法所见的帧速率。默认情况下,MAME以每秒60帧的速度生成帧,如果你觉得这太多了,想把它改成每秒20帧,可以输入以下代码:


 
  1. from MAMEToolkit.emulator import Emulator

  2.  

  3. emulator = Emulator(roms_path, game_id, memory_addresses, frame_ratio=3)

MAME性能基准测试

目前这个工具包的开发和测试已在8核AMD FX-8300 3.3GHz CPU以及3GB GeForce GTX 1060 GPU上完成。在使用单个随机智能体的情况下,街头霸王环境可以以正常游戏速度的600%+运行。而如果是用8个随机智能体进行hogwild!训练,环境可以以正常游戏速度的300%+运行。

ConvNet智能体

为了确保工具包能够训练算法,作者还设置了一个简单的5层ConvNet,只需少量调整,你就可以用它进行测试。在街霸实验中,这个算法能够成功学习到游戏的一些简单技巧,比如连击(combo)和格挡(blocking)。街霸本身的游戏机制是分成10个关卡(难度递增),玩家在每个关卡都要迎战不同的对手。刚开始的时候,这个智能体平均只能打到第2关。但在经过2200次训练后,它平均能打到第5关。

至于智能体的学习率,它是用每一局智能体所造成的净伤害和所承受的伤害来计算的。

教你用Python玩任一款街机游戏!-LMLPHP

- The End -

「若你有原创文章想与大家分享,欢迎投稿。」

加编辑微信ID,备注#投稿#:

程序 丨 druidlost  

 

2018 中国大数据技术大会

BDTC 2018

 

BDTC 2018中国大数据技术大会携主题“大数据新应用”再度强势来袭。本次大会由华东师范大学副校长、教授周傲英,百度商业智能实验室主任熊辉,阿里巴巴副总裁李飞飞三位会议主席对大会内容把关,多位两院院士参与指导,由最了解行业痛点的一线从业者为同行打造。

 

扫描下方二维码或点击【阅读原文】快速购票。现在购票还有机会获得大数据图书一本(中国科学院院士梅宏主编的《大数据导论》或华中科技大学教授金海主编的《大数据处理》),数量有限!

 

教你用Python玩任一款街机游戏!-LMLPHP

 

推荐阅读:

教你用Python玩任一款街机游戏!-LMLPHP

print_r('点个赞吧');
var_dump('点个赞吧');
NSLog(@"点个赞吧!");
System.out.println("点个赞吧!");
console.log("点个赞吧!");
print("点个赞吧!");
printf("点个赞吧!\n");
cout << "点个赞吧!" << endl;
Console.WriteLine("点个赞吧!");
fmt.Println("点个赞吧!");
Response.Write("点个赞吧");
alert(’点个赞吧’)

 

12-04 00:48