feat: add production campaigns, gameplay labs, and review documentation
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import { random } from './core.js';
|
||||
|
||||
export const PRODUCTION_PLAN_VERSION = '2026-09-12-r1';
|
||||
export const PRODUCTION_CAMPAIGN = {
|
||||
id: 'v0.5', revision: 1, chapterSize: 50,
|
||||
chapters: ['初见弯路', '朝内的出口', '绕行花园', '轻轻让路', '环里的风景', '花瓣初开', '交织之间', '两岸来信', '回旋的发现', '层层放行', '走进花心', '曲径相逢', '另一侧的出口', '编织新路', '旋开的花园', '从容穿行', '旧路新发现', '花与回声', '千回百转', '一路盛放'],
|
||||
};
|
||||
export const EXPERIENCE_KINDS = {
|
||||
tour: { name: '长路巡游', lesson: '点一枚棋子,跟着它沿弯路找到出口。', intent: '直接享受完整行进;多个出口提供连续点击的空间。' },
|
||||
gate: { name: '清挡放行', lesson: '先让挡路的棋子离开,再放出里面的长路。', intent: '移走清楚可见的挡子,为后面的长路打开出口。' },
|
||||
contrast: { name: '轻巧反差', lesson: '朝内也有出路,试着转动底盘再出发。', intent: '朝内的目标通过一次旋转接上长路;位置和箭头保持不变。' },
|
||||
turn: { name: '旋转换路', lesson: '先放出能走的棋子,再转出另一条路。', intent: '棋盘初步释放后,转动轨道建立新的离场机会。' },
|
||||
stages: { name: '分段释放', lesson: '一片一片清开,让不同区域的路线接连畅通。', intent: '清挡和换路分段展开,经过至少两次换路后放出主路线。' },
|
||||
};
|
||||
|
||||
const families = ['petals', 'orbits', 'spiral', 'switchback', 'weave', 'crossing'];
|
||||
// Teaching introduces a small set of actions. Later blocks vary their beat
|
||||
// length/order; chapter boundaries are production units, not difficulty cliffs.
|
||||
const introduction = [
|
||||
['switchback', 'tour', 2, 3], ['orbits', 'tour', 2, 4],
|
||||
['petals', 'gate', 2, 5], ['spiral', 'contrast', 2, 5],
|
||||
['weave', 'tour', 2, 4], ['crossing', 'gate', 2, 6],
|
||||
['orbits', 'turn', 2, 6], ['petals', 'tour', 3, 5],
|
||||
['switchback', 'gate', 3, 7], ['spiral', 'turn', 3, 7],
|
||||
];
|
||||
const beats = [
|
||||
['tour', 'gate', 'contrast', 'tour', 'turn', 'gate', 'stages', 'tour', 'gate'],
|
||||
['gate', 'tour', 'turn', 'contrast', 'gate', 'tour', 'stages', 'turn'],
|
||||
['contrast', 'gate', 'tour', 'turn', 'stages', 'tour', 'gate'],
|
||||
];
|
||||
|
||||
export function productionSlot(index) {
|
||||
if (!Number.isInteger(index) || index < 0 || index >= 1000) throw new RangeError('Production slot must be 0–999');
|
||||
const chapter = Math.floor(index / 50), local = index % 50;
|
||||
const rng = random(55012026 + index * 7919);
|
||||
const phrase = beats[(chapter + Math.floor(local / 9)) % beats.length];
|
||||
let kind = phrase[(local + chapter * 3) % phrase.length];
|
||||
let family = families[(local + Math.floor(local / 6) * 2 + chapter * 5) % families.length];
|
||||
let radius = chapter < 2 ? 3 : chapter < 5 ? 3 + (rng() > .65 ? 1 : 0) : 3 + Math.floor(rng() * 3);
|
||||
let target = (kind === 'tour' ? 5 : 8) + Math.min(6, Math.floor(chapter / 3)) + Math.floor(rng() * 4);
|
||||
if (local === 49) { family = 'petals'; kind = chapter < 2 ? 'tour' : 'stages'; radius = chapter < 2 ? 3 : 5; target = chapter < 2 ? 7 : 14; }
|
||||
if (index < introduction.length) [family, kind, radius, target] = introduction[index];
|
||||
if (index < 30 && kind === 'stages') kind = 'turn';
|
||||
// A long open route reserves real space. Familiarity permits new relations,
|
||||
// but does not create room for arbitrary extra pieces on a small board.
|
||||
const capacity = ['contrast', 'turn'].includes(kind) ? { 2: 6, 3: 9, 4: 12, 5: 14 } : { 2: 6, 3: 11, 4: 14, 5: 17 };
|
||||
target = Math.min(target, capacity[radius]);
|
||||
// Chapter-sheet review found 849 and 850 too similar in both silhouette and
|
||||
// release rhythm. A woven breather makes the final layered flower distinct.
|
||||
if (index === 848) { family = 'weave'; kind = 'tour'; radius = 4; target = 8; }
|
||||
return {
|
||||
index, number: index + 1, chapter: chapter + 1, chapterName: PRODUCTION_CAMPAIGN.chapters[chapter],
|
||||
family, kind, radius, target, variant: Math.floor(index / 6),
|
||||
minHeroBends: index === 0 ? 3 : radius === 2 ? 5 : 7,
|
||||
maxHeroBends: radius === 2 ? 22 : radius === 3 ? 36 : 70,
|
||||
seed: 55000000 + index * 1009,
|
||||
phase: chapter < 2 ? 'learn' : chapter < 6 ? 'practice' : chapter < 12 ? 'combine' : 'fluent',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user