You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改NES版《超级马里奥兄弟》1-1关卡寄存器指定马里奥起始位置?

解决gym-super-mario-bros里马里奥起始位置被重置的问题

为啥改了RAM还是回到初始位置

直接修改0x6d(页面寄存器)和0x86(页面内X偏移)会被游戏的关卡初始化逻辑覆盖——环境执行reset()时,游戏会从ROM的关卡数据中读取默认起始位置,自动覆盖你修改的寄存器值。另外,仅修改_x_position函数只是调整了位置的读取逻辑,并没有真正改变游戏内的初始状态。

具体解决办法

1. 选对修改RAM的时机

不要在环境初始化前修改RAM,等reset()完成后立刻写入目标寄存器值:

import gym_super_mario_bros
from nes_py.wrappers import JoypadSpace
from gym_super_mario_bros.actions import SIMPLE_MOVEMENT

env = gym_super_mario_bros.make('SuperMarioBros-v0')
env = JoypadSpace(env, SIMPLE_MOVEMENT)

# 先完成环境重置
obs = env.reset()
# 写入目标位置的RAM值(示例:绝对X坐标设为0x200)
env.unwrapped.ram[0x6D] = 0x2  # 设置页面寄存器
env.unwrapped.ram[0x86] = 0x00  # 设置页面内X偏移
# 同步修改绝对位置寄存器,避免游戏逻辑冲突
env.unwrapped.ram[0x0710] = 0x200

2. 修改环境初始化逻辑(永久生效)

如果需要每次重置环境都直接加载自定义起始位置,修改smb_env.py中的_reset方法,在游戏初始化完成后添加RAM写入代码:

# 在smb_env.py的_reset方法末尾添加以下内容
# 自定义起始位置:页面0x2,偏移0x00
self.ram[0x6D] = 0x2
self.ram[0x86] = 0x00
self.ram[0x0710] = 0x200

注意:修改库文件后,需确保Python能加载到修改后的版本,可选择重新安装库或调整文件路径。

3. 确保位置读取逻辑正确

修改_x_position函数时,要保证它能正确计算马里奥的绝对位置:

def _x_position(self) -> int:
    # 绝对X坐标 = 页面值 * 256 + 页面内偏移
    return (self.ram[0x6D] << 8) + self.ram[0x86]

避免仅读取单一寄存器导致位置显示错误。

额外提醒

  • 确认RAM地址匹配:不同ROM版本(如美版、日版)的RAM映射可能存在差异,要与你使用的游戏版本对应。
  • 选择合法位置:若设置的位置超出当前关卡的可加载区域,游戏可能会强制将马里奥拉回合法坐标,需选择关卡内的有效位置。

内容的提问来源于stack exchange,提问作者Edoardo Fazzari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 05:34:52