如何在视频游戏中给 AI 控制权?
How to give an AI controls in a video game?
所以我使用 PyGame 制作了 Pong,我想使用遗传算法让 AI 学习玩游戏。我希望它只知道桨、球和控件的位置。我只是不知道如何让 AI 自己移动桨。我不想这样做:"If the ball is above you, go up." 我希望它只是尝试随机的东西,直到它学会做什么。
所以我的问题是,如何让 AI 尝试控制并查看效果如何?
一个可能有用的设计考虑是,如果您可以通过另一个界面提供一些最小的显示细节集;并反过来允许向玩家桨发出命令。例如,您可以通过 socket 发送一个简单的结构来描述球的位置以及球拍和球的每一帧更新。按照相同的模式,您可以创建一个结构,作为对描述如何移动玩家桨的消息的回复发送。例如:
# Pong Game program
import socket
import struct
# Set up server or client socket
# ... Into game loop
state = (p1_paddle_y, p2_paddle_y, ball_x, ball_y, victory_state)
# assuming pixel locations, and victory_state is -1:Loss, 0:InProgress, 1:Win
myGameStateMsg = struct.pack('>LLLLh', state[0], state[1], state[2], state[3])
sock.send(myGameStateMsg) # Sending game state to player
playerMsg = sock.recv(4) # Get player command
playerCmd = struct.unpack('i', playerMsg)
# playerCmd is an integer describing direction & speed of paddle motion
# ... Process game state update, repeat loop
您可以使用 线程 和事务处理结构实现相同的效果,但您需要考虑适当保护这些结构(边写边读问题等)
就我个人而言,出于稳定性原因,我更喜欢第一种方法(套接字和多处理)。假设有某种导致崩溃的错误;如果您已经进行了进程分离,那么识别崩溃的根源就会变得更加容易。在线程级别,它仍然是可能的,但更具挑战性。多处理方法的另一个好处是您可以轻松设置多个玩家并扩展游戏(1vInGameAI、1v1、3v3、4v4)。尤其是当你扩展的时候,你可以尝试不同的算法,比如Q-Learning、自适应动态规划等,让它们相互发挥!
附录:插槽 101
Sockets 是一种让多个进程(即 运行 程序)相互发送消息的机制。这些进程可以 运行 在同一台机器上,也可以跨网络。从某种意义上说,使用它们就像读写一个不断修改的文件(这是套接字提供的抽象),而且还提供阻塞调用以便让进程等待信息可用。
关于套接字(例如文件套接字与网络套接字(FD 与 IP);UDP 与 TCP 等)可以讨论的细节很多,可以轻松填满多个页面。相反,请参阅以下有关基本设置的教程:https://docs.python.org/3/howto/sockets.html。有了这些,您将基本了解它们可以提供什么以及从哪里获得更高级的技术。
您可能还想参考 struct 教程以及介绍性消息打包:https://docs.python.org/3/library/struct.html。有更好的方法可以做到这一点,但如果不了解结构,您将无法了解 它们如何工作和分解。
所以你希望 AI 输入球拍的位置和球的位置。 AI 输出是两个布尔输出,AI 是否应该在下一个模拟步骤中按下向上或向下按钮。
我还建议添加另一个输入值,即球的速度。否则,您可能需要添加另一个输入,即前面模拟步骤中球的位置,以及一个更复杂的中间层,让 AI 学习速度的概念。
Learning Atari-Pong has become a standard task in reinforcement learning. For example there is the OpenAI baselines github repo 实现了可以插入各种任务的 RL 算法。
你绝对不需要那些高级算法只是为了按照你描述的方式学习 Pong,但你可以从 API 他们用来区分任务的方法中学习("environments" 在强化学习术语)和 AI 部分("controller" 或 "agent")。为此,我建议阅读 OpenAI Gymn Documentation 以了解如何添加新环境。
简而言之,您可以使用一些浮点数(球的位置和速度,或者两个位置而不是速度,以及球拍的位置)。或者您可以使用离散输入(整数或像素,更难学习)。这些输入可以连接到一个小型神经网络。
对于命令输出,最简单的事情就是预测向上或向下移动的概率。这是个好主意,因为当您评估您的控制器时,它将有 一些 非零得分机会,因此您的遗传算法可以将不同的控制器(具有不同的权重)相互比较.只需在神经网络输出上使用 sigmoid 函数,并将其解释为概率。
如果您将所有神经网络权重初始化为一个良好的随机范围,您可能可以通过尝试随机权重足够长的时间(即使没有 GA)来获得一个不会完全糟糕的乒乓球播放器。
PS:如果您不打算使用神经网络:如果您只需要实现前向传播,那么从头开始实现它们真的很简单。例如。如果您不实施反向传播训练,而是使用 GA 来学习权重(或 evolution strategy,或只是随机权重)。最难的部分是为初始随机权重找到一个好的范围。
所以我使用 PyGame 制作了 Pong,我想使用遗传算法让 AI 学习玩游戏。我希望它只知道桨、球和控件的位置。我只是不知道如何让 AI 自己移动桨。我不想这样做:"If the ball is above you, go up." 我希望它只是尝试随机的东西,直到它学会做什么。
所以我的问题是,如何让 AI 尝试控制并查看效果如何?
一个可能有用的设计考虑是,如果您可以通过另一个界面提供一些最小的显示细节集;并反过来允许向玩家桨发出命令。例如,您可以通过 socket 发送一个简单的结构来描述球的位置以及球拍和球的每一帧更新。按照相同的模式,您可以创建一个结构,作为对描述如何移动玩家桨的消息的回复发送。例如:
# Pong Game program
import socket
import struct
# Set up server or client socket
# ... Into game loop
state = (p1_paddle_y, p2_paddle_y, ball_x, ball_y, victory_state)
# assuming pixel locations, and victory_state is -1:Loss, 0:InProgress, 1:Win
myGameStateMsg = struct.pack('>LLLLh', state[0], state[1], state[2], state[3])
sock.send(myGameStateMsg) # Sending game state to player
playerMsg = sock.recv(4) # Get player command
playerCmd = struct.unpack('i', playerMsg)
# playerCmd is an integer describing direction & speed of paddle motion
# ... Process game state update, repeat loop
您可以使用 线程 和事务处理结构实现相同的效果,但您需要考虑适当保护这些结构(边写边读问题等)
就我个人而言,出于稳定性原因,我更喜欢第一种方法(套接字和多处理)。假设有某种导致崩溃的错误;如果您已经进行了进程分离,那么识别崩溃的根源就会变得更加容易。在线程级别,它仍然是可能的,但更具挑战性。多处理方法的另一个好处是您可以轻松设置多个玩家并扩展游戏(1vInGameAI、1v1、3v3、4v4)。尤其是当你扩展的时候,你可以尝试不同的算法,比如Q-Learning、自适应动态规划等,让它们相互发挥!
附录:插槽 101
Sockets 是一种让多个进程(即 运行 程序)相互发送消息的机制。这些进程可以 运行 在同一台机器上,也可以跨网络。从某种意义上说,使用它们就像读写一个不断修改的文件(这是套接字提供的抽象),而且还提供阻塞调用以便让进程等待信息可用。
关于套接字(例如文件套接字与网络套接字(FD 与 IP);UDP 与 TCP 等)可以讨论的细节很多,可以轻松填满多个页面。相反,请参阅以下有关基本设置的教程:https://docs.python.org/3/howto/sockets.html。有了这些,您将基本了解它们可以提供什么以及从哪里获得更高级的技术。
您可能还想参考 struct 教程以及介绍性消息打包:https://docs.python.org/3/library/struct.html。有更好的方法可以做到这一点,但如果不了解结构,您将无法了解 它们如何工作和分解。
所以你希望 AI 输入球拍的位置和球的位置。 AI 输出是两个布尔输出,AI 是否应该在下一个模拟步骤中按下向上或向下按钮。
我还建议添加另一个输入值,即球的速度。否则,您可能需要添加另一个输入,即前面模拟步骤中球的位置,以及一个更复杂的中间层,让 AI 学习速度的概念。
Learning Atari-Pong has become a standard task in reinforcement learning. For example there is the OpenAI baselines github repo 实现了可以插入各种任务的 RL 算法。
你绝对不需要那些高级算法只是为了按照你描述的方式学习 Pong,但你可以从 API 他们用来区分任务的方法中学习("environments" 在强化学习术语)和 AI 部分("controller" 或 "agent")。为此,我建议阅读 OpenAI Gymn Documentation 以了解如何添加新环境。
简而言之,您可以使用一些浮点数(球的位置和速度,或者两个位置而不是速度,以及球拍的位置)。或者您可以使用离散输入(整数或像素,更难学习)。这些输入可以连接到一个小型神经网络。
对于命令输出,最简单的事情就是预测向上或向下移动的概率。这是个好主意,因为当您评估您的控制器时,它将有 一些 非零得分机会,因此您的遗传算法可以将不同的控制器(具有不同的权重)相互比较.只需在神经网络输出上使用 sigmoid 函数,并将其解释为概率。
如果您将所有神经网络权重初始化为一个良好的随机范围,您可能可以通过尝试随机权重足够长的时间(即使没有 GA)来获得一个不会完全糟糕的乒乓球播放器。
PS:如果您不打算使用神经网络:如果您只需要实现前向传播,那么从头开始实现它们真的很简单。例如。如果您不实施反向传播训练,而是使用 GA 来学习权重(或 evolution strategy,或只是随机权重)。最难的部分是为初始随机权重找到一个好的范围。