Appearance
地牢生成
这页按实际楼层生成顺序阅读。普通层是第 1-3 层:先切到本层随机流,建棋盘、决定地形、造墙、放玩家,再放职业建筑、普通怪物、奖励、Boss、特殊建筑和起点文本。第 4 层会提前分流到 BuildLastFloor,是另一套最终层逻辑。
普通层第 1 层 8 x 8;第 2、3 层 10 x 10。地形、墙、怪物、奖励和 Boss 都在同一层生成过程中确定。
最终层第 4 层直接清墙、全图可见,并在中心放 Throne 和 FinalBoss,不生成普通怪物、商店、奖励和普通 Boss。
地形普通层从尚未出现的普通地形中均匀抽取;地形会保存到 floorEnvironments,并影响怪物与 Boss 的候选权重。
墙每个格子按洗牌顺序尝试变墙;只有变墙后地图仍连通,才再投 50% 成为墙。
放置普通层的放置顺序会影响后续判断:玩家和酒馆占格后,怪物、奖励、Boss 都只能在未占用格上继续生成。
0. 随机入口
| 种子 / 状态 | 在地牢生成里的用途 | 互相影响 |
|---|---|---|
| 初始种子 | 创建游戏或解析种子串时得到的起点,用来派生每层楼层种子和升级奖励种子。 | 改变它会改变整局可复现内容。 |
| 第 1 / 2 / 3 层楼层种子 | BuildBoard(depth) 会按当前层切到对应楼层种子,生成棋盘、墙、地形、怪物、奖励、Boss 和位置。 | 每层是独立入口;第 1 层生成不会推进第 2 层楼层种子。 |
| 地牢全局随机 | 楼层生成期间大量使用 RandomFloat、RandomRange、RandomNormal 和洗牌;生成后部分地牢行动也继续使用它。 | 同一条流上的后续操作会互相推进,例如变形术、寻宝、宝箱、商店重算。 |
| 升级奖励种子 | 升级奖励单独保存,不被楼层造墙、怪物和奖励建筑消耗。 | 楼层生成消耗再多随机,也不会直接吃掉升级奖励序列。 |
| floorBoss / floorEnvironments | 保存第 1-3 层已经生成或从存档恢复的 Boss 与地形。 | 它们是生成结果状态。若 floorBoss 非空,CreateBoss 直接使用固定 Boss;若 floorEnvironments 不是 NONE,同层直接复用该地形。 |
| 战斗内随机 | 起手洗牌、战斗内随机弃牌和部分战斗效果。 | 不参与地牢地图生成;详见 随机数机制。 |
同一层内部是一条连续流水线:造墙洗牌、50% 造墙判定、怪物等级、怪物放置、奖励名、奖励位置、Boss 选择和 Boss 位置,都会按顺序消耗本层随机流。不同层种子、升级奖励种子和战斗内随机则是分开的入口。
1. 普通层总流程
普通层指第 1-3 层。第 4 层在 PopulateDungeon 开头直接进入 BuildLastFloor,跳过下表的普通层流程。
| 顺序 | 阶段 | 生成结果 | 后续影响 |
|---|---|---|---|
| 1 | Initialize | 创建 Tile[,]、allTiles、每个 Tile 的坐标和棋盘引用。 | 之后所有随机选格、连通检查、地形贴图和对象放置都基于这张棋盘。 |
| 2 | 地形 | 读取或抽取 floorEnvironment。 | 决定地板 / 墙体贴图,并作为普通怪物和 Boss 出现权重的环境字段。 |
| 3 | BuildMaze | 逐格尝试变墙,保证剩余可走格始终连通。 | 墙会影响后续 RandomUnusedTile、怪物割点、奖励区域和 Boss 位置。 |
| 4 | 玩家位置 | RandomUnusedTile 放 PlayerSprite。 | PlayerTile 成为距离、威胁距离、Bard 第 1 层酒馆和起点文本的参考点。 |
| 5 | AddTaverns | Bard 职业可能放 Tavern。 | 酒馆占用格子,后续怪物、奖励和 Boss 不能直接占同一个未移动格。 |
| 6 | AddMonsters | 选择普通怪物位置、生成怪物等级、按地形权重选择怪物种类。 | 怪物格会产生威胁,后续 AddRewards 会用这些威胁切分奖励区域。 |
| 7 | AddRewards | 生成奖励名列表,按威胁区域摆放奖励建筑,并在末尾创建普通 Boss。 | 奖励和 Boss 都会占格;Boss 死亡后才会产生普通楼梯。 |
| 8 | AddTraps / AddWeirdFeature | 当前 build 的 AddTraps 为空;第 2 层以后可能添加特殊建筑。 | 特殊建筑是普通奖励流程之外的额外地图对象。 |
| 9 | LevelStart | 在 PlayerTile 创建楼层起点文本。 | 只提供进入楼层的文本提示,不参与墙、怪物或奖励权重。 |
2. Initialize:棋盘与 Tile
| 项目 | 规则 |
|---|---|
| 第 1 层 | 8 x 8,共 64 个 Tile。 |
| 第 2 / 3 层 | 10 x 10,共 100 个 Tile。 |
| 第 4 层 | 同样按后续层尺寸建盘,但随后 BuildLastFloor 会清墙、全图可见,并改用最终层对象。 |
| TileAt | 先检查坐标是否在棋盘内;越界返回空,合法坐标返回 board[x, y]。 |
| allTiles | Initialize 会把每个 Tile 追加到 allTiles。BuildMaze、AddMonsters 和随机选格都会反复使用这个列表。 |
3. 地形:floorEnvironment
普通层使用 Dungeon、Water、Volcano、Forest、Crypt、Mountain 六种真实地形。地形不参与墙数量计算,但会决定地板 / 墙体贴图,并影响普通怪物与普通 Boss 的环境权重。
新生成普通层时,代码会排除 LAST、NONE,以及之前普通层已经抽到的地形,再从剩余地形里均匀抽一个。因此第 1 层是 6 选 1,第 2 层是剩余 5 选 1,第 3 层是剩余 4 选 1。
| 楼层 | 抽取规则 | 概率 | 种子关系 |
|---|---|---|---|
| 第 1 层 | 排除 LAST 和 NONE 后,在 6 种普通地形里抽。 | 每种普通地形 1/6。 | 由第 1 层楼层种子的当前随机流决定。 |
| 第 2 层 | 继续排除第 1 层已出现的地形。 | 剩余 5 种普通地形各 1/5。 | 由第 2 层楼层种子决定,但候选列表会读取第 1 层保存的地形。 |
| 第 3 层 | 继续排除第 1、2 层已出现的地形。 | 剩余 4 种普通地形各 1/4。 | 由第 3 层楼层种子决定,但候选列表会读取前两层保存的地形。 |
| 第 4 层 | 不抽普通地形,直接设置为 LAST。 | 固定。 | 最终层逻辑直接写入,不走普通怪物 / Boss 地形权重。 |
| 后台值 | 地形 | 用途 |
|---|---|---|
| 0 | Dungeon | 普通地形;参与普通怪物和普通 Boss 的 Dungeon 权重。 |
| 1 | Water | 普通地形;参与 Water 权重。 |
| 2 | Volcano | 普通地形;参与 Volcano 权重。 |
| 3 | Forest | 普通地形;参与 Forest 权重。 |
| 4 | Crypt | 普通地形;参与 Crypt 权重。 |
| 5 | Mountain | 普通地形;参与 Mountain 权重,也会被 LightEnvironment 识别为明亮环境。 |
| 6 | LAST | 最终层地形。普通层抽地形时会主动排除它。 |
| 7 | NONE | 未指定 / 初始占位。floorEnvironments 初始为 NONE;普通层首次生成时看到 NONE 才会抽真实地形。 |
| 后台值 | 地形 | 地板 Tile | 墙 Tile | 说明 |
|---|---|---|---|---|
| 0 | Dungeon | DungeonTileFloor | DungeonTileWall | 基础地牢地形。 |
| 1 | Water | WaterTileFloor | WaterTileWall WaterTileWall1 WaterTileWall2 WaterTileWall3 WaterTileWall4 | 水域有多张墙体变体。 |
| 2 | Volcano | VolcanoTileFloor | VolcanoTileWall | 火山地形。 |
| 3 | Forest | ForestTileFloor | ForestTileWall | 森林地形。 |
| 4 | Crypt | CryptTileFloor | CryptTileWall | 墓穴地形。 |
| 5 | Mountain | MountainTileFloor | MountainTileWall | 山脉地形;LightEnvironment 只识别这个值。 |
| 6 | LAST | FinalTileFloor | 无墙图 | 最终层地形。第四层会清掉所有墙,因此没有实际墙图。 |
4. BuildMaze:墙与连通
BuildMaze 先把 allTiles 洗牌,然后按洗牌后的顺序逐格尝试变墙。每个格子最多尝试一次,成功条件有两层:CanDelete 必须允许这个格子变墙,随后 RandomFloat < 0.5 才真正把 Tile.impassable 设为 true。
| 环节 | 具体规则 | 结果 |
|---|---|---|
| 洗牌 | Utility.Shuffle(allTiles) 决定检查顺序。 | 越早检查的格子越容易成为墙;越晚检查时,连通约束通常更严格。 |
| CanDelete | 如果目标格已经是墙,直接拒绝;否则临时把它设为 impassable。 | 临时状态只用于测试,不代表最终变墙。 |
| IsConnected | 统计所有非墙格,从第一个非墙格开始做四向连通搜索,搜索时排除 BlocksMovement 的格子。 | 如果搜索到的格子数等于全图非墙格数量,说明删掉这个格子后地图仍是一整块。 |
| 50% 判定 | 通过连通检查后,再投 RandomFloat < 0.5。 | 只有这一步也通过,格子才永久变成墙。 |
这一步不是寻找一条固定入口到出口路线,而是维护全图可走区连通。斜角接触不算连通;只要某个格子变墙会把地图切成两块,它就不会被删掉。
| 楼层 | 棋盘 | 总格子 | 常见墙数 | 样本范围 | 样本均值 | 剩余可走格 |
|---|---|---|---|---|---|---|
| 第 1 层 | 8 x 8 | 64 | 约 24-27 | 20-30 | 25.1 | 34-44 |
| 第 2 层 | 10 x 10 | 100 | 约 38-42 | 34-47 | 39.9 | 53-66 |
| 第 3 层 | 10 x 10 | 100 | 约 38-42 | 34-47 | 39.9 | 53-66 |
这里的墙数是样本体感范围,不是硬上限。真正墙数由楼层种子、洗牌顺序、连通检查和每次 50% 判定共同决定。
5. PlayerSprite 与 Bard 酒馆
造墙结束后,普通层会用 RandomUnusedTile 选择一个未占用格创建 PlayerSprite。此后 PlayerTile 会成为本层的关键参考点:怪物距离排序、威胁距离、Bard 第 1 层酒馆位置和 LevelStart 都会围绕它计算。
| 对象 | 生成规则 | 后续影响 |
|---|---|---|
| PlayerSprite | 从可删除且未占用的空格中随机选一个。 | 该格不再是 unused;后续对象不会直接占用玩家所在格。 |
| Bard Tavern | 只有职业是 Bard 时 AddTaverns 才继续。第 1 层放在 PlayerTile 的随机未使用邻格;第 2、3 层放在随机未使用格。 | Tavern 是 DungeonFeature,会占用格子,并参与后续 Tile.IsUnused 判断。 |
| Musical Champion | 若第 1 层且 WINBARD2 属性存在,会额外在随机未使用格创建第二个 Tavern。 | Bard 开局可能拥有更多酒馆入口。 |
6. AddMonsters:普通怪物
AddMonsters 分两件事:先选怪物格,再生成怪物等级和怪物种类。位置选择不是平均撒点,而是先尽量占关键通道,再按格子形状概率补怪,最后不足时回填。
| 阶段 | 具体规则 | 结果 |
|---|---|---|
| 数量 | 第 1 层固定 6 只;第 2、3 层为 RandomRange(9, 11)。 | 决定 selected_tiles 的目标数量。 |
| 割点预选 | FindBestCutVertex 最多成功 5 次。每次成功后,把该格加入 selected_tiles 并临时设为 impassable。 | 优先把怪物放在封住后会切开 0 威胁通路的关键位置。 |
| 邻格临时阻挡 | 对已选位置的未阻挡邻格临时设为 impassable。 | 降低怪物直接贴在一起的概率。 |
| 随机放怪 | 洗牌 allTiles,依次检查 Tile.IsUnused 且 RandomFloat < Tile.MonsterPercent。 | 格子形状会影响被接受概率。 |
| 回填 | 如果随机阶段没放够,从同一批洗牌 allTiles 里继续找 unused 且未选中的格子补足。 | 尽量达到本层目标怪物数量。 |
| 释放临时墙 | 清除邻格和已选怪物格上的临时 impassable。 | 这些格子只是选点时临时阻挡,最终怪物格仍然可作为战斗入口。 |
| 距离排序 | 对 selected_tiles 计算 GetStartDistances,并按距离从近到远排序。 | 等级列表按排序后顺序落位,所以远处通常更容易对应高等级。 |
| 楼层 | 怪物数量 | 基础等级 | 等级总和目标 |
|---|---|---|---|
| 1 | 6 | 1、2、3 | 13 |
| 2 | RandomRange(9, 11) | 4、5、6 | 54 |
| 3 | RandomRange(9, 11) | 7、8、9 | 70 |
等级列表先按基础等级生成权重:每个基础等级得到 RandomFloat + 0.5,归一化后乘以怪物数量,再截断为各等级数量。
每只怪物随后有等级波动:10% 概率 -1,15% 概率 +1,5% 概率 +2;前三个波动额外偏低,分别带 -0.15、-0.10、-0.05 修正。
等级会被限制在当前层基础范围内,并且最高不超过 10。如果总等级低于目标值,会随机挑还能提升的怪物继续 +1,直到达到目标。
| 方法 | 具体作用 | 影响到的结果 |
|---|---|---|
| FindDeletableSquares | 从全图格子里找“临时变墙后地图仍保持连通”的格子。它内部会用 CanDelete / IsConnected 检查。 | 给割点检测提供候选;这里不是直接生成新墙。 |
| Tile.IsUnused | 过滤已经是墙、或已经放了 DungeonFeature 的格子。怪物、建筑、玩家等都会让格子不再是 unused。 | 放怪和放奖励只会在真正空格上继续尝试。 |
| Tile.CanBeACut | 局部形状预筛。它看上下左右四个正交邻格,以及四个转角连接缺口;至少 2 个正交邻格、且缺口数大于 1,才可能成为切点。 | 快速排除不可能切开通路的格子,后续仍要经过 IsUnused 和区域数量检查。 |
| FindCutVertexInfos | 先记录当前 GetThreatComponents 的区域数量;再临时把候选格设为 impassable,重新计算区域数量;如果数量增加,就记录这个候选格和切开后的区域列表。 | 确认“封住这个格会把 0 威胁通路切成更多块”。 |
| GetThreatComponents | 把 impassable 格、以及 Tile.GetThreat 不为 0 的格子都当作屏障,只对剩下的 0 威胁可走格做四向 flood fill。 | 得到“被墙和怪物隔开的安全空地区域”,不是普通全图连通块。 |
| GetStartDistances / TileDistanceSort | 从玩家起点算普通距离,并按距离给已经选中的怪物格排序。 | 影响怪物等级和位置的配对。 |
| 格子形状 | 判定 | 怪物尝试放置概率 |
|---|---|---|
| 直线双向通道 | 左右都可走且上下不可走,或上下都可走且左右不可走。也就是总开口数 = 2,且两个开口在同一轴线上。 | 30% |
| 四向交叉 | 上下左右 4 个邻格都存在且都不是 impassable。 | 15% |
| 拐角 / T 字路口 | 总开口数 = 2 或 3,但不满足直线双向通道。2 个开口且互相垂直时是拐角;3 个开口时是 T 字路口。 | 10% |
| 死路 / 边缘 / 孤立格 | 总开口数不是 2、3、4 的其他情况,主要是 0 或 1 个可走邻格。 | 5% |
普通怪物类型权重
怪物类型选择使用 MonsterData 的地形权重。候选必须同时满足:普通怪物类型、当前等级落在 min/max 区间内、当前地形权重大于 0。最终概率不是表中权重本身,而是该怪物权重除以当前候选池总权重。普通怪物还会受 seen 计数影响:本层已经生成过的内部名会被临时降权。
普通怪物权重
| 怪物 | 等级 | 地牢 | 水域 | 火山 | 森林 | 墓穴 | 山脉 |
|---|---|---|---|---|---|---|---|
| Akami Shaman | 1-4 | 0 | 10 | 0 | 5 | 0 | 0 |
| Disciple of Chaos | 1-4 | 3 | 0 | 10 | 0 | 3 | 0 |
| Giant Spider | 1-4 | 0 | 5 | 0 | 5 | 5 | 0 |
| Goblin | 1-4 | 10 | 0 | 5 | 0 | 0 | 0 |
| Griffon | 1-4 | 0 | 0 | 0 | 5 | 0 | 10 |
| Kobold | 1-4 | 10 | 0 | 5 | 0 | 0 | 0 |
| Mage | 1-10 | 2 | 2 | 2 | 2 | 2 | 2 |
| Ooze | 1-4 | 0 | 5 | 5 | 0 | 5 | 0 |
| Orc | 1-4 | 10 | 0 | 5 | 0 | 0 | 0 |
| Piranha | 1-4 | 0 | 10 | 0 | 10 | 0 | 0 |
| Pixie | 1-4 | 0 | 5 | 0 | 10 | 0 | 5 |
| Priest | 1-10 | 2 | 2 | 2 | 2 | 2 | 2 |
| Skeleton | 1-4 | 5 | 0 | 0 | 0 | 10 | 0 |
| Thief | 1-10 | 2 | 2 | 2 | 2 | 2 | 2 |
| Ussuri Tracker | 1-4 | 0 | 0 | 0 | 10 | 0 | 5 |
| Vampire Bat | 1-4 | 5 | 0 | 0 | 0 | 10 | 5 |
| Warrior | 1-10 | 2 | 2 | 2 | 2 | 2 | 2 |
| Wyvern | 1-4 | 0 | 0 | 0 | 10 | 0 | 5 |
| Zombie | 1-4 | 5 | 0 | 0 | 0 | 10 | 0 |
| Goblin Hoarder | 3-6 | 0 | 0 | 0 | 0 | 0 | 0 |
| Akami Muckcaller | 4-7 | 0 | 10 | 0 | 5 | 0 | 0 |
| Akami Stormcaller | 4-7 | 0 | 10 | 0 | 5 | 0 | 0 |
| Brownie | 4-7 | 0 | 5 | 0 | 10 | 0 | 5 |
| Clone | 4-7 | 5 | 0 | 5 | 0 | 5 | 0 |
| Faerie Rogue | 4-7 | 0 | 5 | 0 | 10 | 0 | 5 |
| Ghoul | 4-7 | 5 | 0 | 0 | 0 | 10 | 0 |
| Goblin Mechanist | 4-7 | 10 | 0 | 5 | 0 | 0 | 0 |
| Harpy | 4-7 | 0 | 0 | 0 | 3 | 0 | 10 |
| Medusa | 4-7 | 5 | 0 | 0 | 5 | 5 | 0 |
| Siren | 4-7 | 0 | 10 | 0 | 5 | 0 | 0 |
| Stone Golem | 4-7 | 5 | 0 | 10 | 0 | 0 | 10 |
| Troll | 4-7 | 5 | 0 | 5 | 0 | 0 | 10 |
| Ussuri Hunter | 4-7 | 0 | 0 | 0 | 10 | 0 | 5 |
| Air Elemental | 5-10 | 0 | 0 | 0 | 0 | 0 | 10 |
| Banshee | 5-7 | 0 | 5 | 0 | 0 | 10 | 0 |
| Earth Elemental | 5-10 | 0 | 0 | 0 | 10 | 0 | 0 |
| Fire Elemental | 5-10 | 0 | 0 | 10 | 0 | 0 | 0 |
| Ghost | 5-10 | 0 | 5 | 0 | 0 | 10 | 0 |
| Mimic | 5-10 | 0 | 0 | 0 | 0 | 0 | 0 |
| Ussuri Ambusher | 5-7 | 0 | 0 | 0 | 10 | 0 | 5 |
| Water Elemental | 5-10 | 0 | 10 | 0 | 0 | 0 | 0 |
| Wisp | 5-7 | 0 | 5 | 0 | 10 | 0 | 10 |
| Wraith | 5-7 | 5 | 0 | 5 | 0 | 10 | 0 |
| Demon | 7-10 | 10 | 0 | 5 | 0 | 5 | 0 |
| Efreet | 7-10 | 0 | 0 | 10 | 0 | 0 | 10 |
| Hag | 7-10 | 0 | 10 | 0 | 10 | 0 | 0 |
| Hand of Glory | 7-10 | 0 | 5 | 0 | 0 | 10 | 5 |
| Red Dragon | 7-10 | 3 | 0 | 10 | 0 | 0 | 0 |
| Revenant | 7-10 | 5 | 0 | 3 | 0 | 10 | 0 |
| Sphinx | 7-10 | 5 | 0 | 0 | 5 | 0 | 10 |
| Storm Giant | 7-10 | 0 | 0 | 10 | 0 | 0 | 10 |
| Treant | 7-10 | 0 | 5 | 0 | 10 | 0 | 0 |
| White Dragon | 7-10 | 3 | 10 | 0 | 0 | 0 | 0 |
| Yellow Dragon | 7-10 | 3 | 0 | 0 | 0 | 0 | 10 |
| Shadow Dragon | 8-10 | 3 | 0 | 0 | 10 | 10 | 0 |
7. AddRewards:奖励、建筑与普通 Boss
AddRewards 发生在普通怪物之后。此时怪物已经占格并产生威胁,因此奖励摆放不是只看空格,而是先把地图切成威胁区域,再把奖励分配到这些区域里。
| 阶段 | 规则 |
|---|---|
| 基础奖励 | 每层先加入 3 个 Shop。 |
| 治疗分支 | 先投 1 次 RandomFloat。若大于 0.5:加入 1 个 HealingPool,再加入 depth + RandomRange(1, 2) 个 HealthPack;否则加入 depth * 2 + RandomRange(2, 4) 个 HealthPack。 |
| 服务建筑 | 修道院 / Monastery 33.3%;铁匠 / Blacksmith 33.4%;果昔小屋 / Smoothie Shack 33.3% |
| 额外随机奖励 | Game.RandomRange(2, 4) 次 GenerateRewardName。 |
| 成就 / 难度补充 | DRAGON1 每层加 TreasureChest;STEPS1 每层加 HealthPack;Kitten 加 HealingPool 和 TreasureChest;Grizzly Bear 加 HealthPack。 |
| 摆放逻辑 | 奖励名列表会先洗牌,再按“威胁组件”分配。威胁高的连通区域排在前面,但每次被选中后权重会衰减,所以奖励不会全部堆在同一片区域。 |
本阶段可能创建的对象
商店Shop · 经济每层奖励列表固定先加入 3 个;随机奖励名也可额外生成。
宝箱Treasure Chest · 奖励随机奖励名最高权重,打开后生成卡牌和可能的金币。
治疗包Health Pack · 回复治疗分支和随机奖励名都可能生成,治疗量随楼层增加。
治疗池Healing Pool · 回复治疗分支、随机奖励名和低难度补偿都可能生成。
铁匠Blacksmith · 强化服务奖励三选一或随机奖励名生成,用于升级牌。
修道院Monastery · 净化服务奖励三选一或随机奖励名生成,用于删牌。
果昔小屋Smoothie Shack · 奖励服务奖励三选一或随机奖励名生成。
拟态宝箱Mimic Chest · 遭遇第 2 层以后随机奖励名可生成,打开后变为 Mimic。
地精囤积者Goblin Hoarder · 遭遇奖励名抽中后直接创建的携金怪物遭遇,会用防守牌争取逃走。| 区域方法 | 具体作用 | 结果 |
|---|---|---|
| GetToPlayerThreats | 从玩家位置出发生成威胁距离表;移动到相邻格时会加上该格 Tile.GetThreat。 | 越需要跨过高等级怪物才能到达的区域,威胁距离越高。 |
| Tile.GetThreat | 汇总格子上 DungeonFeature 的 Threat;普通 DungeonFeature 默认 0,Monster.Threat 返回怪物等级。 | 怪物格既会阻断 0 威胁区域,也会提高威胁距离。 |
| GetThreatComponents | 排除墙和非 0 威胁格,只把剩余 0 威胁空地做四向 flood fill。 | 得到 AddRewards 使用的安全空地区域列表。 |
| ThreatComponent | 保存区域格子列表、区域威胁距离、可用空格 openSquares 和权重。 | 奖励会按这些组件分配,而不是直接全图随机撒点。 |
| ThreatComponent.Pick | 区域被选中后 openSquares 减 1,权重从 1 递减到 0.5、0.15、0.05,之后再被选中会基本耗尽;可用空格不足时也会直接耗尽。 | 避免奖励全部堆在同一个区域。 |
奖励名列表
GenerateRewards 先生成奖励名列表,AddRewards 再洗牌这个列表并逐个放置。每个奖励实际创建时会调用 GenerateRewardByName;其中 TreasureChest、MimicChest、Shop、Monastery、Blacksmith、SmoothieShack 等会进入各自建筑逻辑。
GenerateRewardName 抽到 GoblinHoarder 时,地图上创建的是 Goblin Hoarder 怪物;它不是可打开建筑,而是怪物遭遇。它携带较多金币,并会用 Cower、Hide 等防守牌争取逃走。
| 楼层组 | 奖励名 | 概率 |
|---|---|---|
| 第 1 层 | 宝箱 / Treasure Chest | 40% |
| 第 1 层 | 治疗包 / Health Pack | 15% |
| 第 1 层 | 商店 / Shop | 15% |
| 第 1 层 | 地精囤积者 / Goblin Hoarder | 10% |
| 第 1 层 | 铁匠 / Blacksmith | 5% |
| 第 1 层 | 治疗池 / Healing Pool | 5% |
| 第 1 层 | 修道院 / Monastery | 5% |
| 第 1 层 | 果昔小屋 / Smoothie Shack | 5% |
| 第 2 层以后 | 宝箱 / Treasure Chest | 40% |
| 第 2 层以后 | 治疗包 / Health Pack | 15% |
| 第 2 层以后 | 商店 / Shop | 15% |
| 第 2 层以后 | 铁匠 / Blacksmith | 5% |
| 第 2 层以后 | 地精囤积者 / Goblin Hoarder | 5% |
| 第 2 层以后 | 治疗池 / Healing Pool | 5% |
| 第 2 层以后 | 拟态宝箱 / Mimic Chest | 5% |
| 第 2 层以后 | 修道院 / Monastery | 5% |
| 第 2 层以后 | 果昔小屋 / Smoothie Shack | 5% |
金币预算
AddRewards 会先用 TotalGoldTarget 计算本层总金币目标,再除以洗牌后的奖励数量得到平均值。
奖励放置时使用 multiplier 调整金币预算:初始为 1 + 奖励数量 x 0.025,每放一个奖励后减少 0.05。
每个奖励传入的 goldTarget 是 int(平均值 x 当前 multiplier)。这会让前面的奖励预算略高,后面的奖励预算逐步下降。
普通 Boss
Boss 是 AddRewards 的末尾步骤,不是单独在怪物阶段生成。
Boss 基础等级:第 1 层 4 级,第 2 层 7 级,第 3 层 10 级。
如果 floorBoss 指定了固定内部名,就直接使用;否则 MonsterFinder.ChooseBoss 会按环境权重选择,并排除之前楼层已经出现过的 Boss。
Boss 位置优先从已排序 ThreatComponent 里找 CanDelete 候选格;如果选中的 Boss 格已有建筑,会先把原建筑移动到随机未使用格,再创建 Boss。
如果没有合适的组件候选,会扫描全图非墙且 CanDelete 的格子,最后才退回 RandomUnusedTile。
如果生成的是 Lich,会临时阻塞 Boss 格,在玩家连通区域额外放置 Lich Hunter。
巫妖7-10 级 · Boss普通 Boss 选择到 Lich 时,会触发伴随的 Lich Hunter 放置逻辑。
巫妖猎手Lich Hunter · 遭遇Lich Boss 生成后额外创建在玩家连通区域,不来自普通奖励名列表。Boss 权重
| 怪物 | 等级 | 地牢 | 水域 | 火山 | 森林 | 墓穴 | 山脉 |
|---|---|---|---|---|---|---|---|
| Akami Ascendant | 4-7 | 0 | 10 | 0 | 5 | 0 | 0 |
| Cumulo Nimbus | 4-7 | 0 | 0 | 0 | 0 | 0 | 10 |
| Gelatinous Cube | 4-7 | 10 | 3 | 0 | 0 | 3 | 0 |
| Genie | 4-7 | 0 | 3 | 5 | 0 | 0 | 10 |
| Giant Shark | 4-10 | 0 | 10 | 0 | 0 | 0 | 0 |
| Goblin King | 4-7 | 10 | 0 | 5 | 0 | 0 | 0 |
| Magmadon | 4-10 | 0 | 0 | 10 | 0 | 0 | 0 |
| Mime | 4-7 | 2 | 2 | 2 | 2 | 2 | 2 |
| Unicorn | 4-7 | 0 | 0 | 0 | 10 | 0 | 0 |
| Ussuri War Queen | 4-7 | 0 | 0 | 0 | 10 | 0 | 5 |
| Vampire | 4-7 | 3 | 0 | 0 | 0 | 10 | 0 |
| Chromatic Demon | 7-10 | 0 | 5 | 5 | 5 | 0 | 5 |
| Hydra | 7-10 | 0 | 5 | 0 | 5 | 5 | 0 |
| Ice Queen | 7-10 | 0 | 5 | 0 | 10 | 0 | 0 |
| Kraken | 7-10 | 0 | 10 | 0 | 5 | 0 | 0 |
| Lich | 7-10 | 3 | 0 | 0 | 0 | 10 | 0 |
| Phoenix | 7-10 | 5 | 0 | 10 | 0 | 0 | 10 |
| Titan | 7-10 | 5 | 0 | 5 | 0 | 0 | 10 |
8. AddTraps、特殊建筑和出口
| 环节 | 规则 | 玩家实际看到的结果 |
|---|---|---|
| AddTraps | 当前 build 中是空方法。 | 普通层不会在这里额外生成陷阱。 |
| AddWeirdFeature | 第 2 层以后才进入特殊建筑逻辑;不是页面上 3 类均分。随机数小于 0.70 时生成祭坛,再从 6 种祭坛均匀选 1 个;0.70 到 0.85 是 MushroomPatch;0.85 以上是 Brainsucker。 | 这些建筑独立于普通奖励名列表,放在随机未使用格。 |
| LevelStart | 最后在 PlayerTile 创建 LevelStart。 | 提供楼层开场文本,不参与地图连通、怪物、奖励或 Boss 选择。 |
| 普通楼梯 | 普通层初始生成时不预放 Stair。普通 Boss 被摧毁时,Monster.Destroy 会在 Boss 所在 Tile 创建 Stair。 | 楼梯位置等于普通 Boss 格。 |
特殊建筑图
祭坛Altar · 事件特殊建筑分支合计 70%;命中后 6 种祭坛均匀选择,每种约 11.67%。
蘑菇丛Mushroom Patch · 事件特殊建筑分支 15%;完成后复制自己选择的牌。
吸脑者事件Brainsucker · 事件特殊建筑分支 15%;按偏好结算交出的牌。9. BuildLastFloor:第四层
第四层不是“第 3 层再加难度”。PopulateDungeon 发现 depth == 4 时会直接调用 BuildLastFloor,不再执行 BuildMaze、AddTaverns、AddMonsters、AddRewards、普通 Boss、AddTraps 和 AddWeirdFeature。
| 阶段 | 规则 | 结果 |
|---|---|---|
| 地形 | environment 固定为 LAST,贴图使用 FinalTileFloor。 | 不使用普通地形权重。 |
| 墙和可见性 | 遍历全部 Tile,把 impassable 清为 false,并把 visible 设为 true。 | 第四层没有迷宫墙,也不需要探索迷雾。 |
| 中心点 | TileAt(5, 5) 是固定中心。 | BuildLastFloor 在这里创建 Throne 和 FinalBoss。 |
| 玩家位置 | PlayerSprite 放到随机未使用格。 | LevelStart 仍创建在玩家当前格。 |
| 最终结算 | 第四层用 Throne / Claim the Throne 作为最终交互。 | 不生成普通向下楼梯。 |
Throne最终层交互对象BuildLastFloor 在中心格创建;用于最终结算入口。
梦境之主Lord of the DreamBuildLastFloor 在中心格创建的最终 Boss。Lord of the Dream 使用 FinalBoss 类,不在普通 MonsterData 怪物权重表里。
最终战会生成三组 BossAttr。它们控制最终 Boss 的核心规则,例如法令、贡品、选择、额外回合、抗性、毒、装备和卡组补强。
Portent 的 FinalBossText 会把当前 BossAttr 转成玩家可见提示;Polymorph / Wild Shape 命中 FinalBoss 特殊分支时,会重新生成这些属性。
DungeonTileFloor
DungeonTileWall
WaterTileFloor
WaterTileWall
WaterTileWall1
WaterTileWall2
WaterTileWall3
WaterTileWall4
VolcanoTileFloor
VolcanoTileWall
ForestTileFloor
ForestTileWall
CryptTileFloor
CryptTileWall
MountainTileFloor
MountainTileWall
FinalTileFloor