feat(levels): assemble the 50-level campaign and the sheet to review it
The deep-lock construction cannot go below three turns, so it cannot supply an opening band — every level it makes lands mid-difficulty and the curve comes out flat. harvest-easy pulls the shallow end from the shipped v0.5 set, but only the 3% of it that holds up: 568 of 1000 need no rotation at all and 51 more are clearable by tapping at random, which is what the monkey threshold is for. 33 levels survive, at one and two turns. select-50 scores candidates on mechanical features only, spreads the pick evenly across that range, and caps any one route grammar at 36% so the campaign cannot quietly become one template repeated — the shipped 1000 turned out to be thirty. Weights are a flag, so refitting them from a round of agent ratings is a re-run rather than an edit. The result is a curve rather than a plateau: difficulty score 3.85 / 6.24 / 7.60 across the three bands, rotations 1.8 / 3.0 / 3.5, and every level keeps three or more opening choices with a show of at least a second. The 50 register as a playable campaign edition, so review happens in the real game; docs/review-50.html is the handover sheet, one card per level with the opening position drawn from the solver rather than sketched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+38
-3
@@ -2,8 +2,8 @@ import { LEVEL_THEMES, PIGMENTS, contrast, themeWithColors } from './design-toke
|
||||
|
||||
const makePigments=(colors,labels)=>colors.map((color,i)=>({name:labels?.[i]||PIGMENTS[i].name,color,arrow:contrast('#FFFFFF',color)>=4.5?'#FFFFFF':'#172D39'}));
|
||||
const names=['轻松','进阶','烧脑','挑战','每周挑战'];
|
||||
const themes=(backgrounds,titles,materials,palettes,descriptions)=>backgrounds.map((background,i)=>({
|
||||
...LEVEL_THEMES[i],name:titles[i],background,ink:contrast('#12202A',background)>=4.5?'#12202A':'#FFFFFF',
|
||||
const themes=(backgrounds,titles,materials,palettes,descriptions,inks)=>backgrounds.map((background,i)=>({
|
||||
...LEVEL_THEMES[i],name:titles[i],background,ink:inks?.[i]||(contrast('#12202A',background)>=4.5?'#12202A':'#FFFFFF'),
|
||||
description:descriptions?.[i]||`${names[i]}主题 · ${titles[i]}。`,materials:Array.isArray(materials)?materials[i]:materials,
|
||||
palette:palettes?.[i]||LEVEL_THEMES[i].palette,
|
||||
}));
|
||||
@@ -77,11 +77,46 @@ export const ART_DIRECTIONS=Object.freeze([
|
||||
[[0,1,2,3,4,5,7],[0,1,3,6,8,9,4],[1,2,3,5,9,10,0],[0,1,4,6,7,10,11],[0,2,3,4,5,8,10]],
|
||||
['保留实验页的雾蓝背景、暖白格面与陶橙/雾蓝棋子,扩展色同样保持哑光。','像暖砂色纸上的铅笔路线,陶橙、赭金与木棕带来温度。','浅鼠尾草纸底,灰绿轨道与蓝、苔绿棋子形成安静的冷暖关系。','灰白图纸与石墨蓝细线,用陶红、雾紫和钢蓝组织复杂路线。','深蓝灰图纸上保留细线与白箭头,暖色棋子像夜航中的小标记。']),
|
||||
pigments:makePigments(['#D66C4D','#477FC0','#668877','#B58943','#8B7297','#45868C','#B76260','#607B90','#B28168','#46765F','#6B8AAB','#9C7284'],['陶橙','雾蓝','鼠尾草','赭金','雾紫','湖青','陶红','钢蓝','暖木','松绿','烟蓝','藕灰']).map(p=>({...p,arrow:'#FFFFFF'}))},
|
||||
{id:'signpost',code:'06',name:'路标',en:'SIGNPOST',tag:'线路图',style:'signpost',accent:'#2F5FBF',paper:'#F6F2E9',journeyWorlds:true,layout:{rotation:'under-board',rim:.06},
|
||||
description:'棋盘是一张线路图:奶白卡片托在世界色上,墨蓝钢轨压在浅色路基里,端点在板边收口。棋子是路标:十二色统一白箭头,一圈细描边,方向一眼可读。',
|
||||
principles:['格线几乎不可见,路基与钢轨分两层,交叉不打架','棋子内缩露出端口,细描边加统一放大的白箭头','旋转按钮像压在纸上的印记,挂在棋盘两肩之下'],
|
||||
route:{exit:'#2F5FBF',exitGlow:'#C9D7F3',blocked:'#C4432F',blockedGlow:'#F3D3CB',hint:'#D9A227'},
|
||||
themes:themes(
|
||||
['#B7CBD3','#DBC4A6','#BBCBB1','#D7BAB5','#1F2C3B'],
|
||||
['晨雾','杏仁','苔原','暮砂','夜航'],
|
||||
[
|
||||
{board:'#F5F2EA',boardGrid:'#E9E3D6',track:'#3A5068',trackHalo:'#E2DBCC',rim:'#7B8F9C',base:'#95ACB6'},
|
||||
{board:'#F7F2E7',boardGrid:'#EAE3D3',track:'#3A5068',trackHalo:'#E4DCCA',rim:'#98836A',base:'#BFA483'},
|
||||
{board:'#F5F3E9',boardGrid:'#E8E4D6',track:'#3A5068',trackHalo:'#E1DCCC',rim:'#7E9077',base:'#9EB194'},
|
||||
{board:'#F7F1EA',boardGrid:'#EAE2D8',track:'#3A5068',trackHalo:'#E4DBCF',rim:'#9D817D',base:'#BB9C97'},
|
||||
{board:'#F6F2E9',boardGrid:'#E9E3D6',track:'#3A5068',trackHalo:'#E2DBCC',rim:'#55697C',base:'#121C27'},
|
||||
],
|
||||
[[0,2,5,3,1,8,6],[1,0,2,6,3,9,7],[3,6,1,0,4,10,2],[6,0,3,5,2,11,8],[2,5,0,6,1,9,3]],
|
||||
['晨雾蓝灰世界色配奶白卡片,靛蓝、松石与琥珀领色。','杏仁暖砂世界色,朱砂与靛蓝领色,像午后的纸面。','苔原灰绿世界色,紫藤与玫红提亮。','暮砂玫瑰灰世界色,玫红与靛蓝对照。','夜航深蓝灰世界色,奶白卡片像被灯照亮的图。']),
|
||||
pigments:makePigments(['#2F5FBF','#C4432F','#1C8378','#7A4EB8','#4A8235','#A8690C','#BF3A6B','#4A6B8A','#B0572F','#357358','#8A5C92','#5A6D7C'],['靛蓝','朱砂','松石','紫藤','苔绿','琥珀','玫红','钢蓝','赤陶','墨绿','藕紫','铁灰']).map(p=>({...p,arrow:'#FFFFFF'}))},
|
||||
{id:'macaron',code:'07',name:'马卡龙',en:'MACARON',tag:'参考 Meowdoku',style:'macaron',accent:'#E07416',paper:'#FBF6F0',journeyWorlds:true,layout:{rotation:'under-board',rim:.40},motion:{intro:720,pop:true,celebrate:720},hud:{level:'关卡',moves:'待解',tutorial:'入门'},
|
||||
description:'奶油色世界上托一张白色软托盘,六角格像带白缝的软糖砖,藕紫轨道压在糖砖上。棋子是糖果色圆角六角,白色贴纸边,粗圆头白箭头。反馈用果糖色说话:路线点亮、糖砖出场、离场撒星。',
|
||||
principles:['白托盘加白缝,格与格靠留白分开,不画格线','十二色统一白色粗箭头,与白缝同一套白','状态用颜色和弹跳表达:路线点亮、碰撞橘红、出场从左上角一波弹开'],
|
||||
route:{blocked:'#F0663A',hint:'#F7C948'},
|
||||
themes:themes(
|
||||
['#F5EFE7','#FBE6DA','#EEE8F6','#F9E2E8','#3E2E35'],
|
||||
['奶油','蜜桃','香芋','草莓牛奶','可可夜'],
|
||||
[
|
||||
{board:'#FADBCB',boardGrid:'#FFFFFF',track:'#96707B',trackHalo:'#FFFFFF',rings:['#FADBCB','#FAE9BE','#D6EEE1'],tray:'#FFFFFF',shadow:'#E6DDD6',shadowSoft:'#EEE7E0',blush:'#F9B9A6',blocked:'#F0663A',hint:'#F7C948',hintGlow:'#FCE7B5'},
|
||||
{board:'#FDE3D3',boardGrid:'#FFFFFF',track:'#976A66',trackHalo:'#FFFFFF',rings:['#FDE3D3','#FBEDC4','#F4D9E2'],tray:'#FFFFFF',shadow:'#EBD5C9',shadowSoft:'#F3DED4',blush:'#F9B9A6',blocked:'#F0663A',hint:'#F7C948',hintGlow:'#FCE7B5'},
|
||||
{board:'#E9E0F6',boardGrid:'#FFFFFF',track:'#78678F',trackHalo:'#FFFFFF',rings:['#E9E0F6','#F8E3EA','#D9EAF1'],tray:'#FFFFFF',shadow:'#DED6EA',shadowSoft:'#E6DFF0',blush:'#F9B9A6',blocked:'#F0663A',hint:'#F7C948',hintGlow:'#FCE7B5'},
|
||||
{board:'#FBDDE5',boardGrid:'#FFFFFF',track:'#966076',trackHalo:'#FFFFFF',rings:['#FBDDE5','#FDEBCF','#E3EEDA'],tray:'#FFFFFF',shadow:'#EAD0D8',shadowSoft:'#F1D9E0',blush:'#F9B9A6',blocked:'#F0663A',hint:'#F7C948',hintGlow:'#FCE7B5'},
|
||||
{board:'#F9E3D6',boardGrid:'#FFFFFF',track:'#8A6370',trackHalo:'#FFFFFF',rings:['#F9E3D6','#FAEBC8','#DAEBE3'],tray:'#FFF9F3',shadow:'#2A1E23',shadowSoft:'#34272C',blush:'#F9B9A6',blocked:'#F0663A',hint:'#F7C948',hintGlow:'#FCE7B5'},
|
||||
],
|
||||
[[0,5,3,2,6,1,4],[1,9,0,4,2,10,3],[6,7,4,2,11,5,3],[7,3,5,2,11,8,1],[4,0,2,6,1,9,3]],
|
||||
['奶油底、白托盘,草莓、蓝莓与抹茶领色,像一盒刚打开的马卡龙。','蜜桃奶油底,蜜柑与海盐蓝领色,暖一点、甜一点。','香芋奶油底,香芋紫与玫瑰领色,冷一点、静一点。','草莓牛奶底,玫瑰与抹茶对照,白托盘更亮。','可可夜底,白托盘像被灯照亮的甜品盘,薄荷与草莓最先出现。'],
|
||||
['#7A5560','#7C4E52','#5F4E78','#7B4658','#FBEFE6']),
|
||||
pigments:makePigments(['#EE5398','#E5680C','#AB8716','#4C9E5A','#369C94','#578BF0','#937DE4','#D06E93','#B5806A','#4A91D4','#8C68CC','#C56AC4'],['草莓','蜜柑','蜂蜜','抹茶','薄荷','蓝莓','香芋','玫瑰','可可','海盐','葡萄','洋李']).map(p=>({...p,arrow:'#FFFFFF'}))},
|
||||
]);
|
||||
export function artDirection(id){return ART_DIRECTIONS.find(d=>d.id===id)||ART_DIRECTIONS[0];}
|
||||
export function directionTheme(direction,themeId,count=7){
|
||||
const source=direction.themes.find(t=>t.id===themeId)||direction.themes[0];
|
||||
return {...themeWithColors(source,count),artStyle:direction.style,pigments:direction.pigments};
|
||||
return {...themeWithColors(source,count),artStyle:direction.style,pigments:direction.pigments,route:direction.route};
|
||||
}
|
||||
export function appearanceTile(tile,theme){
|
||||
const color=theme?.pigments?.[tile.color];
|
||||
|
||||
Reference in New Issue
Block a user