人工智能强化学习深度学习【免费下载链接】open_spielOpenSpiel is a collection of environments and algorithms for research in general reinforcement learning and search/planning in games.项目地址https://gitcode.com/gh_mirrors/op/open_spiel点击查看免费下载state.is_terminal()是 OpenSpiel 中判断当前状态是否为终态游戏是否结束的核心状态查询方法几乎出现在每一个游戏循环、搜索树遍历与强化学习算法中。本文将基于 OpenSpiel 仓库的官方 API 文档结合 C 核心抽象层与 Python 绑定源码完整讲解该方法的使用方式、返回语义、底层实现原理及典型实战场景帮助你正确地在自研算法中利用终态判定驱动训练与评估流程。方法签名与返回语义在 OpenSpiel 的 Python 接口中每个状态对象State都提供is_terminal()方法is_terminal() - bool其语义为如果当前状态是终态游戏已经结束返回True否则返回False。该方法不接受任何参数返回值为布尔类型。它是状态节点类型判定方法族中的一员与之并列的还有is_initial_state()是否为初始状态、is_chance_node()是否为机会节点、is_simultaneous_node()是否为同时行动节点、is_player_node()是否为玩家决策节点、is_mean_field_node()是否为平均场节点等详见 核心 API 参考 中对应的 state_is_terminal.md 文档。官方文档示例精讲示例一井字棋tic_tac_toe官方文档给出的第一个示例是回合制游戏井字棋import pyspiel game pyspiel.load_game(tic_tac_toe) state game.new_initial_state() print(state.is_terminal()) # Output: False新创建的游戏初始状态下棋盘为空、双方均未获胜游戏显然尚未结束因此is_terminal()返回False。示例二石头剪刀布矩阵博弈matrix_rps第二个示例演示了同时行动博弈的终态判定import pyspiel game pyspiel.load_game(matrix_rps) state game.new_initial_state() print(state.is_terminal()) # Output: False state.apply_actions([1, 1]) print(state.is_terminal()) # Output: True这里matrix_rps是 OpenSpiel 内置的石头剪刀布矩阵博弈Rock, Paper, Scissors。初始状态下两位玩家尚未出招游戏未结束返回False随后state.apply_actions([1, 1])让两位玩家同时选择动作1即都出“布”由于矩阵博弈是单轮one-shot同时行动游戏联合动作一经应用状态立即变为终态is_terminal()返回True。值得说明的是apply_actions是同时行动博弈专用接口用于一次性提交所有玩家的联合动作而在回合制博弈中则应使用apply_action逐个玩家应用动作。这一点在两个示例的对比中体现得很清楚。源码级原理从 Python 绑定到 C 纯虚函数state.is_terminal()并非 Python 单独实现的逻辑而是直接绑定到 C 核心层的State::IsTerminal()。在 Python 绑定文件 open_spiel/python/pybind11/pyspiel.cc 中可以看到.def(is_terminal, State::IsTerminal)也就是说Python 侧每次调用state.is_terminal()都会调用 C 虚函数IsTerminal()。在状态基类 open_spiel/spiel.h 中该方法被声明为纯虚函数// Is this a terminal state? (i.e. has the game ended?) virtual bool IsTerminal() const 0;这意味着每一个具体游戏的状态类都必须实现该方法而“游戏是否结束”的具体判定规则完全由各游戏自定义。这也解释了为什么不同游戏对“终态”的定义可以完全不同回合制棋类游戏如井字棋、五子棋通常判定为“某一方达成获胜条件”或“棋盘已满无法继续落子”单轮矩阵博弈如matrix_rps判定为“联合动作已执行”扑克类游戏则通常判定为“所有玩家已完成全部下注轮并到达摊牌或弃牌阶段”。终态与收益的联动Rewards() 的默认实现IsTerminal()不仅驱动游戏循环的终止还直接影响收益计算。在 open_spiel/spiel.h 中Rewards()的默认实现以IsTerminal()为分界virtual std::vectordouble Rewards() const { if (IsTerminal()) { return Returns(); } else { return std::vectordouble(num_players_, 0.0); } }即终态时返回各玩家的最终收益Returns()非终态时返回全零向量。该默认实现只适用于“仅终局结算”的游戏对于存在中途奖励intermediate rewards的 RL 风格游戏子类必须同时重写Rewards()与Returns()。这从侧面说明了IsTerminal()在 OpenSpiel 收益模型GameType::RewardModel::kTerminal与kModelBased中的枢纽地位。两个代表游戏的终态判定实现井字棋条件组合判定在 open_spiel/games/tic_tac_toe/tic_tac_toe.cc 中井字棋的终态判定实现为bool TicTacToeState::IsTerminal() const { return outcome_ ! kInvalidPlayer || IsFull(); }即满足以下任一条件即为终态outcome_ ! kInvalidPlayer已有玩家连成一线获胜IsFull()9 个格子全部被占满平局。对应的收益实现Returns()tic_tac_toe.cc在玩家 0 获胜时返回{1.0, -1.0}玩家 1 获胜时返回{-1.0, 1.0}平局返回{0.0, 0.0}。可见is_terminal()返回True并不意味着一定存在赢家——平局同样属于终态。另外在 tic_tac_toe.cc 中LegalActions()也优先检查IsTerminal()终态时直接返回空列表避免在已结束的状态上继续落子。石头剪刀布矩阵博弈联合动作驱动matrix_rps属于 OpenSpiel 的矩阵博弈家族其状态类型MatrixState定义在 open_spiel/matrix_game.hbool IsTerminal() const override { return !joint_move_.empty(); }只要joint_move_联合动作记录非空即两位玩家都已出招状态即为终态。这与官方文档示例中apply_actions([1, 1])之后is_terminal()立即返回True的行为完全吻合。终态时的收益由 matrix_game.h 中的Returns()按行玩家与列玩家的效用矩阵查表得到非终态时两者均为 0。matrix_rps游戏本身在 open_spiel/games/matrix_games/matrix_games.cc 中注册两名玩家、同时行动kSimultaneous、确定性、零和kZeroSum、单轮kOneShot、终局奖励kTerminal。这些GameType属性正是理解“为何一步之后即为终态”的关键。实战在游戏循环与算法中使用 is_terminal通用游戏循环范式is_terminal()最常见的用法是驱动一个通用的对局循环。OpenSpiel 官方示例 open_spiel/python/examples/example.py 展示了完整范式while not state.is_terminal(): # The state can be three different types: chance node, # simultaneous node, or decision node if state.is_chance_node(): # Chance node: sample an outcome outcomes state.chance_outcomes() num_actions len(outcomes) print(Chance node, got str(num_actions) outcomes) action_list, prob_list zip(*outcomes) action np.random.choice(action_list, pprob_list) state.apply_action(action) elif state.is_simultaneous_node(): # Simultaneous node: sample actions for all players. ... else: # Decision node: sample a uniform random action. ...这个循环在每一轮开头都调用state.is_terminal()作为退出条件随后按节点类型分派处理。无论是机会节点掷骰子、洗牌、同时行动节点还是普通决策节点统一由这一个循环覆盖——这正是is_terminal()作为“通用状态查询”接口的价值所在。类似的while not state.is_terminal():循环模式还大量出现在 open_spiel/python/examples/mcts.py、open_spiel/python/examples/dots_and_boxes_example.py、open_spiel/python/examples/benchmark_games.py 等示例中是 OpenSpiel 生态中最主流的对局驱动方式。在搜索与求解算法中的关键作用在 MCTS、CFR 等树搜索算法中is_terminal()是递归展开的终止条件。以 open_spiel/python/algorithms/mcts.py 为例节点展开Expand、回溯BackUp等流程都依赖对终态的判定来决定是否继续生成子节点、是否直接以终局收益作为估值。在 open_spiel/python/algorithms/minimax.py 等极小极大求解器中叶子节点终态直接返回静态评估值Returns()非终态才递归搜索。可以说is_terminal()构成了几乎所有树形算法递归基base case的判定基础。结合其他状态查询方法使用在编写循环时is_terminal()通常与以下方法配合使用方法作用典型用途is_terminal()游戏是否结束循环退出条件、树搜索递归基is_chance_node()是否为机会节点决定是否按概率抽样is_simultaneous_node()是否为同时行动节点决定用apply_actions还是apply_actionis_player_node()是否为单个玩家决策节点决定是否为决策点legal_actions()当前合法动作列表终态时返回空列表returns()/player_return(p)各玩家累计收益终态后读取结算结果其中值得注意的细节是在终态下调用legal_actions()会返回空列表如 open_spiel/matrix_game.h 中if (IsTerminal()) return {};因此在编写算法时应先检查is_terminal()再查询合法动作避免对已结束状态执行无效操作。测试与验证OpenSpiel 的 Python 测试套件对初始状态的终态判定有明确断言。在 open_spiel/python/tests/pyspiel_test.py 中def test_othello(self): game pyspiel.load_game(othello) state game.new_initial_state() self.assertFalse(state.is_chance_node()) self.assertFalse(state.is_terminal()) self.assertEqual(state.legal_actions(), [19, 26, 37, 44]) def test_tic_tac_toe(self): game pyspiel.load_game(tic_tac_toe) state game.new_initial_state() self.assertFalse(state.is_chance_node()) self.assertFalse(state.is_terminal()) self.assertEqual(state.legal_actions(), [0, 1, 2, 3, 4, 5, 6, 7, 8])可以看到奥赛罗othello与井字棋的初始状态均被断言为非终态且初始合法动作列表完整。如果你在实现自定义游戏时发现is_terminal()行为异常可参考这类测试模式断言“初始状态非终态、执行完整动作序列后为终态、终态时legal_actions()为空”。使用注意事项小结终态不等于有赢家井字棋平局、矩阵博弈平局同样返回True应结合returns()区分胜负平。不同游戏的终态规则差异巨大IsTerminal()是纯虚函数语义完全由具体游戏实现切换游戏时不要假设终态触发的动作数一致。终态是“一次性”的分界一旦is_terminal()返回True通常不应再调用apply_action/apply_actions推进状态legal_actions()此时为空列表。收益读取要在终态之后默认Rewards()实现下非终态收益恒为 0真正的结算结果需在终态后通过returns()或player_return()获取。性能考量在 MCTS 等高频调用场景中is_terminal()会被反复执行其成本取决于具体游戏的判定逻辑如井字棋只需检查outcome_与棋盘是否填满成本极低。通过本文的介绍你应当能够熟练运用state.is_terminal()驱动 OpenSpiel 的游戏循环与树搜索算法并理解其在 C 核心层与 Python 绑定层的完整调用链Python 方法 → pyspiel.cc 绑定 → spiel.h 纯虚函数 → 各游戏状态类的自定义实现。这一理解将帮助你在编写自定义游戏或调试算法循环时快速定位终态判定相关的逻辑问题。赞分享人工智能强化学习深度学习【免费下载链接】open_spielOpenSpiel is a collection of environments and algorithms for research in general reinforcement learning and search/planning in games.项目地址https://gitcode.com/gh_mirrors/op/open_spiel点击查看免费下载相关推荐OpenSpiel 核心 API 详解new_initial_state() 与游戏初始状态OpenSpiel 核心 API 详解new_initial_state 与游戏初始状态 导读 new_initial_state 是 OpenSpiel 中人工智能强化学习深度学习OpenSpiel 游戏 API 详解max_move_number() 与 move_number 上限约束OpenSpiel 游戏 API 详解max_move_number 与 move_number 上限约束 导读 max_move_number 是 Open人工智能强化学习深度学习OpenSpiel 游戏方法 max_game_length() 详解决策节点上限的定义、源码实现与实战应用OpenSpiel 游戏方法 max_game_length 详解决策节点上限的定义、源码实现与实战应用 导读 max_game_length 是 OpenS人工智能强化学习深度学习创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考