游戏AI的创造思路-技术基础-蒙特卡洛树搜索(2)

news2024/11/14 4:13:38

接上一篇,让我们来看更多的例子

目录

7. 更多例子

7.1. 国际象棋实例

7.2. RTS类游戏实例

7.3. FPS类游戏实例


7. 更多例子

蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)在游戏AI中有着广泛的应用,尤其是在那些具有巨大状态空间和复杂决策过程的游戏中。

除了围棋,MCTS还被应用于国际象棋、五子棋、扑克牌游戏(如德州扑克)、甚至在一些实时策略游戏(如《星际争霸II》)的AI中也使用了MCTS或其变种。

7.1. 国际象棋实例

以下是一个使用Python实现的MCTS在国际象棋中的应用实例。

这个示例是一个简化的版本,主要用于演示MCTS的基本框架和算法流程。

请注意,由于国际象棋的完整规则相当复杂,这里的实现仅涵盖了MCTS的核心部分,并未包括完整的游戏逻辑和胜负判断。

import random  
from math import sqrt, log  
import chess  # 使用python-chess库来处理国际象棋的游戏逻辑  
  
class Node:  
    def __init__(self, game_state, parent=None):  
        self.game_state = game_state  
        self.parent = parent  
        self.children = []  
        self.visits = 0  
        self.wins = 0  
        self.untried_moves = list(game_state.legal_moves)  
  
    def is_terminal(self):  
        return self.game_state.is_game_over()  
  
    def uct_value(self, parent_visits):  
        if self.visits == 0:  
            return float('inf')  
        win_rate = self.wins / self.visits  
        exploration_factor = sqrt(2)  
        return win_rate + exploration_factor * sqrt(log(parent_visits) / self.visits)  
  
    def expand(self):  
        move = self.untried_moves.pop()  
        next_state = self.game_state.copy()  
        next_state.push(move)  
        child_node = Node(next_state, self)  
        self.children.append(child_node)  
        return child_node  
  
    def select_child(self):  
        return max(self.children, key=lambda child: child.uct_value(self.visits))  
  
def simulate(node):  
    current_node = node  
    while not current_node.is_terminal():  
        if current_node.untried_moves:  
            current_node = current_node.expand()  
        else:  
            current_node = current_node.select_child()  
    return current_node.game_state.result()  
  
def backpropagate(node, result):  
    while node:  
        node.visits += 1  
        if result == '1-0':  # 白方胜  
            node.wins += 1  
        elif result == '0-1':  # 黑方胜  
            node.wins += 0  # 这里实际上不需要加0,只是为了保持格式一致  
        node = node.parent  
  
def mcts(root, num_iterations):  
    for _ in range(num_iterations):  
        node = root  
        while not node.is_terminal():  
            if node.untried_moves:  
                node = node.expand()  
            else:  
                node = node.select_child()  
        result = simulate(node)  
        backpropagate(node, result)  
  
# 示例用法  
board = chess.Board()  
root = Node(board)  
num_iterations = 1000  
mcts(root, num_iterations)  
best_child = max(root.children, key=lambda child: child.visits)  
print("推荐走子:", best_child.game_state.peek())  
print("访问次数:", best_child.visits)

在这个示例中,我们使用了python-chess库来处理国际象棋的游戏逻辑。

Node类表示MCTS中的一个节点,它包含了游戏状态、父节点、子节点列表、访问次数、胜利次数以及未尝试的走子列表。

mcts函数实现了MCTS算法的主要流程,包括选择、扩展、模拟和反向传播。

在示例用法中,我们创建了一个初始的游戏状态,并进行了1000次MCTS迭代来选择最佳的走子。最后,我们打印了推荐的走子和它的访问次数。

7.2. RTS类游戏实例

蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)在即时战略(RTS)游戏AI中的应用相对复杂,因为RTS游戏具有巨大的状态空间和复杂的实时决策需求。

以下是一个简化的MCTS在RTS游戏AI中的应用实例,涵盖了游戏单位的移动、走位、攻击、使用魔法和撤退等基本操作。

由于完整的RTS游戏环境(如《星际争霸II》或《魔兽争霸III》)的代码实现非常复杂,且通常需借助游戏特定的API(例如《星际争霸II》的PySC2)来交互,这里将使用一个简化的模拟环境来演示MCTS的应用。我们将创建一个简化的RTS游戏状态类,并在其上实现MCTS,你可以基于此框架,结合具体的RTS游戏API,进行进一步的开发。

以下是一个简化的MCTS算法Python代码:

import random  
from math import sqrt, log  

class RTSGameState:  
    def __init__(self):  
        # 简化状态表示,实际应包含所有游戏单位的状态  
        self.units = [  
            {"type": "warrior", "health": 100, "position": (0, 0)},  
            {"type": "mage", "health": 80, "position": (1, 1), "mana": 100},  
            # ... 其他单位  
        ]  
        self.enemy_units = [  
            {"type": "enemy_warrior", "health": 100, "position": (10, 10)},  
            # ... 其他敌方单位  
        ]  
        self.turn = 0  # 游戏回合数  
  
    def is_game_over(self):  
        # 简化判断,实际应包含复杂的游戏结束条件  
        return False  
  
    def legal_moves(self):  
        # 返回所有合法动作,这里仅作为示例  
        return ["move_up", "move_down", "move_left", "move_right", "attack", "use_magic", "retreat"]  
  
    def copy(self):  
        # 深拷贝游戏状态  
        return RTSGameState()  # 实际应用中需要实现深拷贝逻辑  
  
    def apply_move(self, move):  
        # 应用动作到游戏状态,这里仅作为示例  
        if move == "move_up":  
            self.units[0]["position"] = (self.units[0]["position"][0], self.units[0]["position"][1] + 1)  
        # ... 其他动作的逻辑  
  
    def result(self):  
        # 返回游戏结果,这里仅作为示例  
        return "ongoing"  # 或 "win", "lose"  
  
class Node:  
    def __init__(self, game_state, parent=None, move=None):  
        self.game_state = game_state  
        self.parent = parent  
        self.move = move  
        self.children = []  
        self.visits = 0  
        self.total_reward = 0  
        self.untried_moves = game_state.legal_moves()
  
    def select_child(self):  
        # 使用UCT选择子节点  
        scores = [(child.total_reward / child.visits) + sqrt(2 * log(self.visits) / child.visits)  
                  for child in self.children]  
        return self.children[scores.index(max(scores))]  
  
    def expand(self):  
        # 展开节点,随机选择一个未尝试的动作  
        move = random.choice(self.untried_moves)  
        new_game_state = self.game_state.copy()  
        new_game_state.apply_move(move)  
        child_node = Node(new_game_state, self, move)  
        self.children.append(child_node)  
        self.untried_moves.remove(move)  
        return child_node  
  
    def update(self, result):  
        # 更新节点的访问次数和总奖励  
        self.visits += 1  
        self.total_reward += result  
  
    def __repr__(self):  
        return f"[M:{self.move} V:{self.visits} R:{self.total_reward}]"  
  
def simulate(node):  
    # 简化模拟:随机选择动作直至游戏结束  
    while not node.game_state.is_game_over():  
        move = random.choice(node.game_state.legal_moves())  
        node.game_state.apply_move(move)  
    return node.game_state.result()  
  
def backpropagate(node, result):  
    # 反向传播模拟结果  
    while node:  
        node.update(result)  
        node = node.parent  
  
def mcts(root, num_iterations):  
    for _ in range(num_iterations):  
        node = root  
        # 选择  
        while node.untried_moves == [] and node.children != []:  
            node = node.select_child()  
        # 展开  
        if node.untried_moves != []:  
            node = node.expand()  
        # 模拟  
        result = simulate(node)  
        # 反向传播  
        backpropagate(node, result)  
  
  
# 示例用法  
game_state = RTSGameState()  
root = Node(game_state)  
num_iterations = 1000  
mcts(root, num_iterations)  
best_child = max(root.children, key=lambda child: child.visits)  
print("推荐动作:", best_child.move)  
print("访问次数:", best_child.visits)

RTSGameState类是一个抽象基类,你需结合具体的RTS游戏API来实现它。

apply_move方法应修改游戏状态,legal_moves方法应返回当前状态下的合法动作列表,is_game_over方法应判断游戏是否已结束,而result方法则应返回游戏的结果。

7.3. FPS类游戏实例

蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)在第一人称射击游戏(FPS)的AI队友中实现是一个复杂的任务,涉及对游戏环境的深入理解、与游戏引擎的交互以及AI算法的实现。由于FPS游戏的复杂性和多样性,这里只能提供一个简化的MCTS实现框架,并不能直接应用于具体的游戏,如《CS:GO》或《守望先锋》。你需要根据具体游戏的环境和API来调整和完善这个框架。

以下是一个简化的MCTS算法框架,用于FPS游戏中AI队友的决策:

import random  
from math import sqrt, log  
  
# 假设存在一个与游戏交互的API模块,这里我们使用一个模拟的游戏API  
class GameAPI:  
    # 假设游戏状态是一个字典,包含玩家的位置、敌人的位置和玩家的生命值  
    game_state = {  
        'player_position': (0, 0),  
        'enemy_positions': [(10, 10)],  
        'player_health': 100  
    }  
      
    @staticmethod  
    def get_game_state():  
        # 返回当前游戏状态的副本  
        return GameAPI.game_state.copy()  
      
    @staticmethod  
    def is_game_over():  
        # 判断游戏是否结束,例如玩家生命值小于等于0  
        return GameAPI.game_state['player_health'] <= 0  
      
    @staticmethod  
    def get_available_actions():  
        # 返回当前游戏状态下可用的动作列表  
        return ['move_forward', 'move_backward', 'move_left', 'move_right', 'shoot', 'throw_grenade', 'retreat']  
      
    @staticmethod  
    def apply_action(action):  
        # 应用动作到游戏状态  
        if action == 'move_forward':  
            GameAPI.game_state['player_position'] = (GameAPI.game_state['player_position'][0] + 1, GameAPI.game_state['player_position'][1])  
        elif action == 'move_backward':  
            GameAPI.game_state['player_position'] = (GameAPI.game_state['player_position'][0] - 1, GameAPI.game_state['player_position'][1])  
        elif action == 'move_left':  
            GameAPI.game_state['player_position'] = (GameAPI.game_state['player_position'][0], GameAPI.game_state['player_position'][1] - 1)  
        elif action == 'move_right':  
            GameAPI.game_state['player_position'] = (GameAPI.game_state['player_position'][0], GameAPI.game_state['player_position'][1] + 1)  
        elif action == 'shoot':  
            # 假设射击总是成功的,并减少一个敌人的生命值(这里简单模拟为移除一个敌人)  
            if GameAPI.game_state['enemy_positions']:  
                GameAPI.game_state['enemy_positions'].pop(0)  
        elif action == 'throw_grenade':  
            # 假设投掷手榴弹会立即结束游戏(模拟玩家自杀)  
            GameAPI.game_state['player_health'] = 0  
        elif action == 'retreat':  
            # 假设撤退会恢复一些生命值  
            GameAPI.game_state['player_health'] += 10 if GameAPI.game_state['player_health'] < 100 else 0  
      
    @staticmethod  
    def get_reward():  
        # 返回执行动作后的奖励  
        if GameAPI.is_game_over():  
            return -100  # 游戏结束,返回大负值作为惩罚  
        enemies_remaining = len(GameAPI.game_state['enemy_positions'])  
        return -enemies_remaining  # 敌人越少,奖励越高(负值表示我们想要最小化这个数量)   
  
class Node:  
    def __init__(self, game_state, parent=None, action=None):  
        self.game_state = game_state  
        self.parent = parent  
        self.action = action  
        self.children = []  
        self.visits = 0  
        self.total_reward = 0  
        self.untried_actions = game_state.get_available_actions()  
  
    def select_child(self):  
        scores = [(child.total_reward / child.visits) + sqrt(2 * log(self.visits) / child.visits) if child.visits > 0 else float('inf')  
                  for child in self.children]  
        return self.children[scores.index(max(scores))]  
  
    def expand(self):  
        action = random.choice(self.untried_actions)  
        new_game_state = self.game_state.copy()  
        new_game_state.apply_action(action)  
        child_node = Node(new_game_state, self, action)  
        self.children.append(child_node)  
        self.untried_actions.remove(action)  
        return child_node  
  
    def update(self, result):  
        self.visits += 1  
        self.total_reward += result  
  
    def __repr__(self):  
        return f"[A:{self.action} V:{self.visits} R:{self.total_reward}]"  
  
class GameState:  
    def __init__(self):  
        self.state = GameAPI.get_game_state()  
  
    def is_terminal(self):  
        return GameAPI.is_game_over()  
  
    def get_available_actions(self):  
        return GameAPI.get_available_actions()  
  
    def copy(self):  
        new_state = GameState()  
        # 这里应该深拷贝游戏状态,具体实现依赖于游戏状态的复杂性  
        new_state.state = self.state  # 假设游戏状态是一个简单的可赋值对象  
        return new_state  
  
    def apply_action(self, action):  
        GameAPI.apply_action(action)  
        self.state = GameAPI.get_game_state()  
  
    def get_reward(self):  
        return GameAPI.get_reward()  
  
def simulate(node):  
    while not node.game_state.is_terminal():  
        action = random.choice(node.game_state.get_available_actions())  
        node.game_state.apply_action(action)  
    return node.game_state.get_reward()  
  
def backpropagate(node, result):  
    while node:  
        node.update(result)  
        node = node.parent  
  
def mcts(root, num_iterations):  
    for _ in range(num_iterations):  
        node = root  
        while node.untried_actions == [] and node.children != []:  
            node = node.select_child()  
        if node.untried_actions != []:  
            node = node.expand()  
        result = simulate(node)  
        backpropagate(node, result)  
  
# 示例用法  
game_state = GameState()  
root = Node(game_state)  
num_iterations = 1000  
mcts(root, num_iterations)  
best_child = max(root.children, key=lambda child: child.visits)  
print("推荐动作:", best_child.action)  
print("访问次数:", best_child.visits)

使用这个模拟的GameAPI类,你可以运行之前定义的MCTS算法,并根据模拟的游戏状态来选择最佳动作。

但是在实际应用中,你需要将GameAPI类中的方法实现为与你的FPS游戏API进行交互的代码。

通过以上3个实例,可以对MCTS算法有一点了解了吧,去实现写代码吧~~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1910566.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python数据获取:从基础到实践,一场数据探索之旅

目录 一、引言 二、理解数据获取的基本概念 三、使用Python进行网络数据抓取 3.1 基础工具&#xff1a;requests库 3.2 解析HTML&#xff1a;BeautifulSoup库 3.3 实战案例&#xff1a;抓取网页新闻列表 四、从文件中读取数据 4.1 使用pandas读取CSV文件 4.2 读取Exce…

LORAHUB: EFFICIENT CROSS-TASK GENERALIZATION VIA DYNAMIC LORA COMPOSITION

文章汇总 动机 效果如上&#xff1a;希望将多个任务训练得到的LoRA组合起来&#xff0c;效果比单独一个任务得到的LoRA效果更好。 愿景&#xff1a;那未来我们每个人都贡献出自己训练出来的LoRA&#xff0c;之后通过LoRAHub简单组合起来&#xff0c;就可以得到适用于多任务且功…

从零开始搭建vite开发环境

准备 nodejs 18 pnpm https://vitejs.cn/ 开始 pnpm init pnpm add -D vite新建index.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width…

昇思Mindspore25天学习打卡Day20:DCGAN生成漫画头像

昇思Mindspore25天学习打卡Day20&#xff1a;DCGAN生成漫画头像 1 GAN基础原理2 DCGAN原理3 数据准备与处理数据处理 4 构造网络4.1 生成器4.2 判别器 5 模型训练损失函数优化器训练模型 6 结果展示7 训练结束打上标签和时间 在下面的教程中&#xff0c;我们将通过示例代码说明…

[Linux]安装+使用虚拟机

首先下载&#xff08;提取码 &#xff1a; ssjf&#xff09;虚拟机&#xff08;应该是必须要下载17的了 &#xff0c; 我刚开始下载了15,16的在解决了不兼容的问题后频繁出现蓝屏的 &#xff09; 刚开始我遇见了 小问题 --》 在查看了以下两篇blog就解决了 虚拟机无法打开,…

STM32 IIC详解(软件模拟)

目录 一、IIC协议基本原理 1.IIC协议概述 2.时序图分析 二、代码分析 1.IIC初始化 2.IIC起始信号 3.IIC发送数据 4.获取应答信号 5.读一个字节 6.产生ACK应答 7.不产生ACK应答 IIC&#xff08;Inter-Integrated Circuit&#xff09;在嵌入式系统中是一种常见的数据通…

考研数学130+的强化复习规划(附暑假经验分享)

考研数学强化是最关键的提高阶段&#xff01; 有的同学强化阶段做的好&#xff0c;甚至能冲击到130这个分数&#xff01;所以&#xff0c;大家一定要重视考研数学强化&#xff0c;特别是暑期两个月的时间。 先说一下强化误区&#xff01; 很多同学基本上就是6月结束基础&…

如何压缩视频大小不改变画质,视频太大怎么压缩变小

在现代生活中&#xff0c;视频已经成为我们记录生活、分享快乐的重要工具。但随之而来的问题就是视频文件体积过大&#xff0c;不仅占用大量存储空间&#xff0c;还难以在社交平台上快速分享。别担心&#xff0c;下面我就来教大家几种简单有效的方法&#xff0c;让视频文件轻松…

春秋杯 snack入土为安的第二天

不嘻嘻&#xff0c;签到题做了两天&#xff0c;先用pyinstxtractor.py&#xff08;找最新版本。。红温&#xff09;把exe转化为pyc&#xff0c;用在线反编译pycdc来反编译&#xff0c;最后的key在一个文件夹里key.pyc切记用python3.3版本&#xff08;红温&#xff09;。 # 假设…

在 PostgreSQL 里如何处理数据的版本跟踪和回滚?

文章目录 一、事务二、保存点三、使用版本控制扩展四、审计表和触发器五、使用时间戳列六、比较和还原数据七、考虑数据备份和恢复八、结论 在数据库管理中&#xff0c;数据的版本跟踪和回滚是非常重要的功能&#xff0c;有助于在数据操作出现错误或需要回滚到特定状态时进行有…

RAG的学习与实践——LangChain和LlamaIndex学习笔记

RAG RAG(Retrieval Augmented Generation)系统&#xff0c;代表“检索增强生成”。RAG由五个关键步骤组成&#xff1a; 加载&#xff1a;这是指将数据从其所在位置&#xff08;无论是文本文件、PDF、其他网站、数据库还是 API&#xff09;获取到您的管道中。LlamaHub提供数百…

自定义@AnonymousAccess注解

一.目的&#xff1a; 自定义AnonymousAccess注解&#xff0c;可以直接在controller上添加该注解使请求绕过权限验证进行匿名访问&#xff0c;便于快速调用调试以及部分不需要进行安全验证的接口。而不是每次都需要去SecurityConfig文件中进行修改。 二.流程&#xff1a; 三.实…

软件项目运维服务方案(Word原件)

1.项目情况 2.服务简述 2.1服务内容 2.2服务方式 2.3服务要求 2.4服务流程 2.5工作流程 2.6业务关系 2.7培训 3.资源提供 3.1项目组成员 3.2服务保障 软件文档全套下载&#xff1a;本文末个人名片直接获取或者进主页。

【峟思】智能一体化水位监测系统的创新应用与优势解析

在全球气候变化与城市化加速的双重挑战下&#xff0c;极端天气事件频发&#xff0c;城市内涝、河流泛滥等水位灾害对社会安全和经济稳定构成了严峻威胁。为有效应对这些挑战&#xff0c;智能一体化水位监测系统应运而生&#xff0c;凭借其高效、精准、智能的技术特性&#xff0…

PostgreSQL 里怎样解决多租户数据隔离的性能问题?

文章目录 一、多租户数据隔离的性能问题分析&#xff08;一&#xff09;大规模数据存储和查询&#xff08;二&#xff09;并发访问和锁争用&#xff08;三&#xff09;索引维护成本高&#xff08;四&#xff09;资源分配不均 二、解决方案&#xff08;一&#xff09;数据分区&a…

行至第11年,追光动画距离“中国皮克斯”还有多远?

百花奖提名名单公布后&#xff0c;入围最佳影片大奖的唯一一部动画电影《长安三万里》&#xff0c;竟然成为了获奖呼声最高的电影。 去年暑期档上映的《长安三万里》以18.24亿票房一跃成为中国影史动画电影票房亚军&#xff0c;虽然这个数据在今年春节档被《熊出没逆转时空》超…

【苍穹外卖】Day2 手把手敲完细节

目录 1. 新增员工 1.1 需求分析和设计 1.2 代码开发 ①定义DTO类&#xff1a;(在sky-pojo里&#xff09; ②EmployeeController中创建新增员工方法save() ③EmployeeService里声明save方法&#xff08;altenter&#xff09; ④EmployeeServiceImpl中实现save方法 ⑤在E…

喜讯丨美格智能通过国际EcoVadis平台认证企业社会责任并荣获承诺奖章,彰显可持续发展实力

作为全球领先的无线通信模组及解决方案提供商&#xff0c;美格智能在社会责任领域再创新高。近日&#xff0c;美格智能凭借在企业社会责任和可持续性采购发展方面的卓越表现&#xff0c;通过国际在线权威评价机构EcoVadis对公司环境、劳工与人权、商业道德、可持续采购等方面审…

线性回归笔记

https://blog.51cto.com/u_16213589/7682076 残差图 多元回归-最小二乘法-残差分析笔记 一.多元线性回归模型的假设 我们需要进行以下六个假设&#xff0c;这些假设是经典的多元线性回归模型有效的前提&#xff1a; 1、因变量Y和自变量X1&#xff0c;X2&#xff0c;…&#…

文献阅读:基于测序的空间转录组方法的系统比较

文献介绍 文献题目&#xff1a; Systematic comparison of sequencing-based spatial transcriptomic methods 研究团队&#xff1a; 田鲁亦&#xff08;广州实验室&#xff09;、刘晓东&#xff08;西湖大学&#xff09; 发表时间&#xff1a; 2024-07-04 发表期刊&#xff…