Files

161 lines
15 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
import json,html,csv,hashlib
root=Path(r'G:\项目\NumberSwipe-Variants');out=root/'design/demo-50';plan=json.loads((out/'demo-design.json').read_text(encoding='utf-8'));levels=plan['levels'];names={'big':'大格/异形','walls':'墙','direction':'方向','alternation':'双色','parity':'奇偶','rhythm-door':'步进门'}
def mech(l):return '+'.join(names[f] for f in l['features']) or '数字基础'
intro='''# NumberSwipe 50关DEMO设计与难度曲线
版本:2026-10-14 v1。面向首次接触的新玩家,目标是验证趣味性、规则理解与章节节奏。当前交付是关卡制作任务与目标曲线,没有具体坐标、作者解或50关可玩包。
## 研究如何适配本项目
研究正文来源:G:/下载/NumberSwipe_Research_H5.html。源文件SHA-256记录在demo-design.json;报告中的外部Zip统计未在本项目复算。采用有效分叉、区域风险、错误发现延迟、目标跨度、逻辑依赖和视觉操作负担的分层思路。公式权重、章节8/9/10节拍及报告首通指标均是待测假设。
本项目数字表示绝对访问步号,不能将Zip的编号升序直接迁移。每个拼块一步、每格恰好一次、共边移动、完整有序解唯一。按节点数量使用5–19格,不迁移研究报告6×6/7×7的面积规模。普通方格固定起点下目标格奇偶由天然二分图固定,奇偶优先放在大格或无双色的六边盘。双色严格交替时不叠加奇偶。方向通道仅用于单位方格整盘。步进门空盘关、起点也切换,出发前判门位、撤销恢复。单位方格门题主要判断通过方向;通过大格或含三角邻接的六边图才强调不同路线的到达状态。
保留当前五个原型及已认可的40关作为参考,不恢复相对步差、先后链、窗口或开关格。当前Variants没有奇偶判定,双色启用仍依赖mode名称:组合主线落地需独立增加features开关、奇偶判定/提示/求解器/必要性检查,并限制图示与实际规则一致。本轮不修改这些运行代码,不调整手机体验。
## 节拍选择
默认A:每10关第8关峰值、第9关释放、第10关收束。新机制采用演示→练习→变化→组合→巩固的五关单元;不要求每个10关章都新增规则。
B为对照:同一套题,把各章第8关移到第10关,9/10关前移为8/9。A/B拥有完全相同关卡ID和内容,只改变顺序。首次制作先校验A,再与B比较。不是随机动态调难。
前两关完成操作教学;大格与墙在1–10关;方向与双色在11–20关;奇偶与门在21–30关;六边迁移在31–40关;最后10关只深化组合。保留两次起点未知(37、38),不把起点未知作为所有关卡的固定难度旋钮。
目标分0–100是策划标尺,不是搜索节点数、通过概率或玩家实测难度。各章目标峰值40/46/50/58/72,最后一关54分收束,不在50关耗尽难度上限。释放题也必须有可解释的选择,避免机械蛇形或连续闭眼画。
## 五章目标
| 关卡 | 阶段 | 新内容 | 峰值关/目标分 |
|---|---|---|---|
| 1–10 | 覆盖、大格与墙 | 大格一步、永久墙 | 8/40 |
| 11–20 | 方向与双色 | 六种明确通道、换颜色 | 18/46 |
| 21–30 | 奇偶与步进门 | 步号奇偶、每步切换门 | 28/50 |
| 31–40 | 六边迁移与起点推理 | 六向邻接、未知起点 | 38/58 |
| 41–50 | 组合应用与收束 | 不新增规则 | 48/72 |
## 最新项目研究补充与桥接验证
已纳入原项目docs/一笔画竞品调研与关卡编排方案.md、2026-10-14补充的《一笔画深度调研-制作与难度证据.md》及45关结构审计JSON。该审计针对原项目26数字关+19六边关;本次另行读取Variants的40关,二者不能混为同一题库的验收。
技能依赖:覆盖/纠错→大格计步→枢纽出口→异形共边;基本共边→横竖端口→明确拐角→方向联合;精确步号与实际拼块图→单奇偶→双奇偶;步号与撤销→起步切换→通过方向→大格到达状态;熟悉墙→六向共边→旧规则迁移。未知起点依赖端点和步号推理,先小盘专项。
先制作并测试6道桥接样题,均计入50关:
|设计号|验证任务|控制变量|
|---|---|---|
|05|异形共边|只增加L形读盘,不叠奇偶或未知起点|
|13|拐角端口|只增加一种明确拐角,能解释反向通过|
|18|双色与墙联合|先掌握16/17,再测试异色出口保留|
|21|单奇偶|按节点计步,条件必要,不靠天然属性|
|24|双奇偶与区域|先掌握21–23,每条条件各自有效|
|28|大格与门位|先掌握26/27,检查实际步数关系|
教学测试按课程顺序。难度校准先让玩家学会对应规则,再交错代表题,避免把学习熟练或记忆同盘答案误判为题更容易。四层去重分别检查外观几何、真实邻接、约束配置、关键解法;几何相同且推理不同可以少量保留,四层等价仅限明确强化用途。
## 逐关制作任务
表中格数、约束预算与曲线为候选制作目标;盘面通过验证与试玩之前都不能标记为完成。格式是设计任务数据,不是游戏可直接读取的关卡JSON。
'''
md=intro
for ch in plan['chapters']:
md+=f"\n### 第{ch['id']}章 · {ch['title']}\n\n{ch['focus']}。\n\n|关|标题/功能|格数|机制|目标分|核心任务|\n|---:|---|---:|---|---:|---|\n"
for l in levels[(ch['id']-1)*10:ch['id']*10]:md+=f"|{l['displayOrder']}|{l['title']} · {l['role']}|{l['nodeCountTarget']}|{mech(l)}|{l['targetDifficulty']}|{l['teachingGoal']}|\n"
for l in levels[(ch['id']-1)*10:ch['id']*10]:
md+=f"\n#### {l['displayOrder']:02d} · {l['title']}\n\n- 盘面:{l['layoutIntent']}。\n- 条件预算:{l['constraintsBudget']}。\n- 顿悟:{l['teachingGoal']}。\n- 诱惑路线:{l['temptingRouteIntent']}。\n- 排除依据:{l['rejectionReason']}。\n- 目标:分值{l['targetDifficultyBand'][0]}–{l['targetDifficultyBand'][1]};有效关键选择{l['targetDecisionCount'][0]}–{l['targetDecisionCount'][1]}处;最长依赖约{l['targetDependencyDepth']}层;思考时间P50候选目标{l['thinkingSecondsP50Target'][0]}–{l['thinkingSecondsP50Target'][1]}秒。\n"
if l['sourceCandidates']:md+='- 原型参考:'+', '.join(l['sourceCandidates'])+';仅作构造参考,不能视为可直接复用。\n'
md+='''
## 51–100关及正式版衔接
50关验证后,先依据真人数据修改题与关序,再扩展51–100。优先用区域拓扑、空洞、对称/破对称、枢纽先后和线索位置开发新题,不要求增加规则或继续扩大盘面。每个新章先安排熟悉规则的热身,再形成局部峰谷;不规定第51关必须难于第50关。
优质DEMO题作为内容资产复用,正式首发前统一筛选重排。过难题可移入挑战包。上线后新增章节与主题包,旧内容只进行有依据的局部修正。levelId首次分配后保留;显示顺序由章节manifest决定。规则实质变化增加contentRevision,完全替换题目分配新ID。保存通关进度和分析记录时绑定ID与修订,不能只绑定第几关。
## 交付与状态
- index.html:离线规划页,筛选逐关任务、切换A/B曲线、查看详细设计。
- demo-design.json:50关任务、稳定ID、章节与A/B关序,所有任务标记design-only。
- difficulty-curve.csv:目标曲线与A/B位置;实测难度列留空。
- VALIDATION_PLAN.md:难度定义、机器人策略、机制必要性与真人测试标准。
- project-snapshot.json:现有40关的结构快照,只是几何指标,不是人类难度。
- plan-check.json:设计表一致性检查,不是50关唯一解验收。
本轮没有制作50个坐标盘面,没有给出真实作者解,没有完成真人难度或手机测试。
'''
(out/'DEMO_DESIGN.md').write_text(md,encoding='utf-8')
(out/'VALIDATION_PLAN.md').write_text('''# 制作与难度验证规划
## 1. 三类难度分开保存
- targetDifficulty:策划目标分,当前有值。
- staticFeatures / simulatedFeatures:盘面完成后采集,当前为空。
- humanDifficulty:真人数据校准后填写,当前为空。
报告权重0.25B+0.25C+0.20R+0.15S+0.10U+0.05V是候选,不直接作为排序真值;本轮不实现未经校准的综合评分器。所有指标保存规则/模型版本。不同机制的搜索节点数不可未经校准直接比较。
## 2. 指标的操作定义
|指标|测量办法|限制|
|---|---|---|
|有效决策数B|在固定策略机器人遇到至少两种未被其已掌握规则排除的移动时,记录一次决策|不是原始邻接度>=3的节点数量;不能用完整求解器提前认出唯一解再计数|
|强制比例F|固定策略机器人独立通过局部移动、固定步号及已掌握规则确定的追加数/总追加数|不能把唯一解中的所有步当成强制步;不能将度2比例视为F|
|封闭风险C|每个诱惑移动是否会切断剩余潜在图;记录局部可见或需跨区推断|门的潜在连通图保留未来可开的边,双色和永久墙按各自静态限制处理|
|错误发现延迟R|按约定诱惑策略,从首次偏离到出现可解释矛盾之间的追加数|分别记录自动冲突、局部死路、区域矛盾;不是撤销次数|
|数字跨度S|固定数字按步号排序的相邻差和最后尾段;同时保存最长未确定段|不使用空间距离;奇偶不等同固定数字|
|推理依赖U|人工说明中为确认关键选择需要连续使用的前提层数|先由策划标注,真人口述核对,不由机制数量替代|
|视觉操作V|路径转向、标记密度、边界歧义、触点与跨块连线可读性|与逻辑难度分开,手机优化留到玩法验证后|
## 3. 机器人方案(待实施)
A局部策略:固定数字与基本操作约束优先,倾向较近线索、少出口及边缘;不访问完整答案,记录诱惑选择与回退。策略、候选排序和随机种子固定,便于复现。
B规则策略:在A基础上使用端点/剩余区域连通/通道配对/拼块计步/奇偶/颜色/门位推理;逐项记录所用规则与推理次数。只评估定义范围内的推理,不能宣称等价人类。
C完整搜索:确认完整有序解唯一,解除约束生成反例,记录搜索规模与耗时。C的节点数只作计算诊断,不等于真人难度。
## 4. 盘面发布门槛
每关结构合法、完整解唯一;无1时搜所有起点;每条奇偶、每个方向通道、每堵墙、门、全局交替要求逐项解除后至少两解;辅助数字逐项删减,教学保留需写理由。约束预算是候选目标,不能为了凑墙数或标记数保留冗余。
主线支持features显式启用,必须由规则、操作、求解、提示共用判定。禁止把当前mode名称判双色的逻辑直接复制到组合主线。奇偶原始格不与数字同格;不可依靠天然方格或双色奇偶做无效装饰。方向只适用单位方格整盘;大格和六边不继承lr/du等端口判断。
步进门最多一道,空盘关,起点也切换;出发前判位、落格后切换;回退和重开恢复。单位方格固定起点的天然奇偶不因绕路改变,门题不写成任意绕一圈就能补拍;需要可变到达步号关系时用大格或三角邻接六边盘。
组合必须有明确的跨机制推理,并记录解除每一项后的完整反例;唯一解通过但主要靠枚举、长段机械填满的题仍须重做。
## 5. 玩家测试(待实施)
先找3–5名新玩家定性测试规则解释与明显枯燥点,再组织更大样本进行50关分会话测试。每关20–30人可暴露明显问题,不用于精确估计低频退出或A/B显著性;A/B需要根据实际方差和所需效应另算样本量。
记录实际开始、首次落格、首次偏离、冲突被发现、回退、重开、提示、完成、离开、下一关启动和下一会话返回。仅本地导出记录,不在本轮加入自动网络上传。
第一次尝试:从首次起手到首次重开、提示或结束;分别记录是否含回退。首次无提示且无回退完成、允许回退的无提示完成、最终完成分开统计,避免成功率口径混乱。
思考时间:从盘面可读到首次落格,加上绘制途中思考停顿的候选口径,后台时间剔除;另存开始到完成总耗时。暂停阈值需在原型事件采集前固定,当前设计时间目标不与总耗时混用。
单关统计P50/P75/P90时间、错误发现延迟、回退、提示、开始后退出、完成后下一关启动。退出分为卡关、无聊、正常结束会话、操作/显示问题,结合短口述或选择项;不能把退出全部解释成难度。
先以实际测量修正排序,不用本方案的秒数直接判定成败。教学关目标是理解规则;挑战关目标是可解释推理;释放关目标是减少负担并保持兴趣。重点检查8/18/28/38/48峰值,以及其后两关是否让玩家愿意继续。
A/B关序保持完全相同题库:A第8峰值、9/10释放;B把峰值移至章末。用户首次参与时固定分组,不在同一玩家每章切换,避免学习效应。比较完成后下一关启动和后续会话返回,同时检查新规则理解、提示与卡关退出;未达样本前只作定性观察,不宣布最优。
## 6. 数据契约(规划,不是运行关卡)
设计任务记录levelId、designKey、教学任务、候选几何/机制、目标分/目标带、目标关键选择与依赖、制作状态。具体cells/walls/doors及作者解只有制作完成才填写到独立关卡包。
关序manifest维护ID数组,A/B互为同集合排列。已发题重排不清空已通关进度;实质规则改变有revision;替换为新谜题分配新ID。
当前交付不承诺平台、网络、广告或周期上线日期。先做玩法曲线验证,再安排手机体验和release内容生产。
''',encoding='utf-8')
# Minimal static SVG: target scores only, no inference that it is a measured curve.
def curve(ids):
lookup={l['levelId']:l for l in levels};seq=[lookup[i]['targetDifficulty'] for i in ids];W,H=1060,320;L,T=50,20;pw,ph=990,245
parts=[f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W} {H}" role="img" aria-label="50关策划目标难度曲线,非实测"><rect width="1060" height="320" fill="#101e33"/>']
for v in (0,20,40,60,80,100):y=T+ph*(1-v/100);parts+=[f'<line x1="{L}" y1="{y}" x2="1040" y2="{y}" stroke="#30435d"/><text x="40" y="{y+4}" fill="#becddd" font-size="12" text-anchor="end">{v}</text>']
for pos in (1,10,20,30,40,50):x=L+pw*(pos-1)/49;parts+=[f'<text x="{x}" y="290" fill="#becddd" font-size="13" text-anchor="middle">{pos}</text>']
for c in range(5):x=L+pw*(c*10)/49;parts+=[f'<line x1="{x}" y1="20" x2="{x}" y2="265" stroke="#37516f" stroke-dasharray="4 5"/>']
points=' '.join(f'{L+pw*i/49:.2f},{T+ph*(1-v/100):.2f}' for i,v in enumerate(seq));parts+=[f'<polyline points="{points}" fill="none" stroke="#73d6c3" stroke-width="3"/>']
parts+=['<text x="1040" y="310" fill="#becddd" font-size="12" text-anchor="end">目标分 · 非实测 · 关序位置</text></svg>'];return ''.join(parts)
(out/'curve-a.svg').write_text(curve(plan['orders']['A']['levelIds']),encoding='utf-8');(out/'curve-b.svg').write_text(curve(plan['orders']['B']['levelIds']),encoding='utf-8')
print('Markdown specification, validation plan and A/B SVG curves written.')