Skip to content

Instantly share code, notes, and snippets.

@surma
Last active August 9, 2021 23:23
Show Gist options
  • Save surma/c17ba203a4974215caf414c8bd4fc612 to your computer and use it in GitHub Desktop.
Save surma/c17ba203a4974215caf414c8bd4fc612 to your computer and use it in GitHub Desktop.
Getting Started with your own Understand-style puzzle
node_modules
package-lock.json
function O(o,e){return new DOMPoint(o.x-e.x,o.y-e.y,o.z-e.z,o.w-e.w)}function x(o,e){return o===void 0||e===void 0?!1:o.x===e.x&&o.y===e.y&&o.z===e.z&&o.w===e.w}function R(o,e){return e.x>=o.left&&e.x<o.right&&e.y>=o.top&&e.y<o.bottom}var u;(function(r){r[r.DidAdvance=0]="DidAdvance",r[r.CannotAdvance=1]="CannotAdvance",r[r.EndOfPuzzle=2]="EndOfPuzzle",r[r.YouWon=3]="YouWon"})(u||(u={}));var m;(function(n){n[n.SQUARE=0]="SQUARE",n[n.EDGE=1]="EDGE",n[n.VERTEX=2]="VERTEX"})(m||(m={}));var f;(function(r){r[r.Up=0]="Up",r[r.Left=1]="Left",r[r.Down=2]="Down",r[r.Right=3]="Right"})(f||(f={}));var v=new Map([[0,new DOMPoint(0,-1,0,0)],[1,new DOMPoint(-1,0,0,0)],[3,new DOMPoint(1,0,0,0)],[2,new DOMPoint(0,1,0,0)]]);var c;(function(t){t[t.SQUARE=0]="SQUARE",t[t.CIRCLE=1]="CIRCLE"})(c||(c={}));function*z(o,e){for(let t=0;t<e;t++)for(let n=0;n<o;n++)yield new DOMPoint(n,t,0,1)}function A(o,e){return o.some(t=>t.x===e.x&&t.y===e.y)}function k(o){return[...v.entries()].find(([e,t])=>x(o,t))?.[0]}function P(){return{path:[]}}function F(o,{canAdvanceFreely:e=!1,startIdx:t=0}={}){let n=t,r=o.map(()=>{}),C=P();return{getInitPath(){return r[n]??[]},async setGameState(i){C=i,await o[n].setGameState(i)},getDrawCommands(){return o[n].getDrawCommands()},canWalk(i){return o[n].canWalk(i)},checkRules(){let i=o[n].checkRules();return i.every(s=>s)&&(r[n]=C.path),i},go(i){return n+i==o.length&&r.every(d=>d!==void 0)?u.YouWon:n+i==o.length?u.EndOfPuzzle:n+i<0?u.EndOfPuzzle:i<0?(n+=i,u.DidAdvance):e?(n+=i,u.DidAdvance):r.slice(0,n+i).every(s=>s!==void 0)?(n+=i,u.DidAdvance):u.CannotAdvance}}}var E={white:{r:255,g:255,b:255,a:255},black:{r:0,g:0,b:0,a:255},transparent:{r:0,g:0,b:0,a:0}};function S(o,e,t){return t<0&&(t+=1),t>1&&(t-=1),t<1/6?o+(e-o)*6*t:t<1/2?e:t<2/3?o+(e-o)*(2/3-t)*6:o}function a(o,e,t){let n,r,C;if(e==0)n=r=C=t;else{let i=t<.5?t*(1+e):t+e-t*e,d=2*t-i;n=S(d,i,o+1/3),r=S(d,i,o),C=S(d,i,o-1/3)}return{r:Math.round(n*255),g:Math.round(r*255),b:Math.round(C*255),a:255}}var h={green:{backgroundColor:a(128/360,.46,.77),selectedColor:a(128/360,.48,.65),lineColor:a(120/360,1,.32)},orange:{backgroundColor:a(19/360,.7,.85),selectedColor:a(19/360,.67,.76),lineColor:a(19/360,.67,.51)},darkgreen:{backgroundColor:a(128/360,.19,.74),selectedColor:a(128/360,.18,.61),lineColor:a(136/360,1,.18)},yellow:{backgroundColor:a(60/360,.41,.74),selectedColor:a(60/360,.41,.62),lineColor:a(60/360,1,.27)},blue:{backgroundColor:a(240/360,.51,.8),selectedColor:a(240/360,.59,.7),lineColor:a(240/360,.75,.4)}},L=.1,y=.9,g=.1,G=.5;function D(o){let{colorScheme:e,width:t,height:n,checkRules:r,symbols:C=[]}=o,i=new DOMRect(0,0,t,n),d=[...z(t,n)].flatMap(l=>[{type:m.VERTEX,shape:c.SQUARE,backgroundColor:e.lineColor,position:l,size:y,symbol:"",symbolColor:E.transparent,symbolSize:1},{type:m.VERTEX,shape:c.SQUARE,backgroundColor:e.backgroundColor,position:l,size:y-g,symbol:p(l,o)?.shape?.empty??"",symbolColor:e.lineColor,symbolSize:G}]),s=P();return{go(l){return u.YouWon},setGameState(l){s=l},checkRules(){return r(s.path,o)},canWalk(l){return R(i,l)&&!A(s.path,l)},getInitPath(){return[]},getDrawCommands(){return{gridSize:[t,n],backgroundColor:e.backgroundColor,barBackgroundColor:e.lineColor,barFontColor:e.selectedColor,closeButtonColor:e.lineColor,commands:[...s.path.flatMap((l,M,U)=>M===0?[]:[{type:m.EDGE,edge:{start:l,direction:k(O(U.at(M-1),l))},backgroundColor:e.lineColor,size:L,symbol:"",symbolSize:0,symbolColor:E.transparent}]),...d,...s.path.flatMap(l=>[{type:m.VERTEX,position:l,shape:c.SQUARE,backgroundColor:e.selectedColor,size:y-g,symbol:p(l,o)?.shape?.filled??"",symbolSize:G,symbolColor:e.lineColor}]),...s.path.length>0?[{type:m.VERTEX,position:s.path[0],shape:c.SQUARE,backgroundColor:e.selectedColor,size:y-g,symbol:"",symbolSize:0,symbolColor:E.transparent},{type:m.VERTEX,position:s.path[0],shape:c.SQUARE,backgroundColor:e.lineColor,size:y-2*g,symbol:"",symbolSize:0,symbolColor:E.transparent},{type:m.VERTEX,position:s.path[0],shape:c.SQUARE,backgroundColor:e.selectedColor,size:y-3*g,symbol:"",symbolSize:0,symbolColor:E.transparent}]:[]]}}}}function p(o,e){return e.symbols.find(t=>x(o,t.position))}var b={CIRCLE_STAR:{empty:"\u272A\uFE0E"},CROSS_IN_CIRCLE:{empty:"\u2A02\uFE0E"},CIRCLE:{empty:"\u25CB\uFE0E",filled:"\u25CF\uFE0E"},ARROW_LEFT:{empty:"\u2906\uFE0E"},ARROW_RIGHT:{empty:"\u2907\uFE0E"},SQUARE:{empty:"\u25A1\uFE0E",filled:"\u25A0\uFE0E"},TRIANGLE_DOWN:{empty:"\u25BD\uFE0E",filled:"\u25BC\uFE0E"},TRIANGLE_RIGHT:{empty:"\u25B7\uFE0E",filled:"\u25B6\uFE0E"},TRIANGLE_LEFT:{empty:"\u25C1\uFE0E",filled:"\u25C0\uFE0E"},TRIANGLE_UP:{empty:"\u25B3\uFE0E",filled:"\u25B2\uFE0E"},STAR:{empty:"\u2606\uFE0E",filled:"\u2605\uFE0E"},PENTAGON:{empty:"\u2B20\uFE0E",filled:"\u2B1F\uFE0E"}};function w(o,e){let t=p(o?.[0],e)?.shape===b.CIRCLE,n=p(o?.[o.length-1],e)?.shape===b.SQUARE;return[t,n]}async function me(){return F([D({width:3,height:1,colorScheme:h.green,checkRules:w,symbols:[{position:new DOMPoint(0,0,0,1),shape:b.CIRCLE},{position:new DOMPoint(2,0,0,1),shape:b.SQUARE}]}),D({width:3,height:1,colorScheme:h.green,checkRules:w,symbols:[{position:new DOMPoint(2,0,0,1),shape:b.CIRCLE},{position:new DOMPoint(0,0,0,1),shape:b.SQUARE}]}),D({width:2,height:2,colorScheme:h.green,checkRules:w,symbols:[{position:new DOMPoint(0,0,0,1),shape:b.CIRCLE},{position:new DOMPoint(1,1,0,1),shape:b.SQUARE}]})],{canAdvanceFreely:!0})}export{me as default};
import { Path } from "mazemerizing/src/puzzle";
import { linearAdvancement } from "mazemerizing/src/sdk/linear-advancement";
import {
colorPalettes,
symbolAtPosition,
understandLevel,
UnderstandLevelParams,
} from "mazemerizing/src/sdk/understand/sdk";
import { UnicodeSymbols } from "mazemerizing/src/unicode";
function checkRules(path: Path, params: UnderstandLevelParams): boolean[] {
const startedInCircle =
symbolAtPosition(path?.[0], params)?.shape === UnicodeSymbols.CIRCLE;
const endedInSquare =
symbolAtPosition(path?.[path.length - 1], params)?.shape === UnicodeSymbols.SQUARE;
return [startedInCircle, endedInSquare];
}
export default async function () {
return linearAdvancement(
[
understandLevel({
width: 3,
height: 1,
colorScheme: colorPalettes.green,
checkRules,
symbols: [
{ position: new DOMPoint(0, 0, 0, 1), shape: UnicodeSymbols.CIRCLE },
{ position: new DOMPoint(2, 0, 0, 1), shape: UnicodeSymbols.SQUARE },
],
}),
understandLevel({
width: 3,
height: 1,
colorScheme: colorPalettes.green,
checkRules,
symbols: [
{ position: new DOMPoint(2, 0, 0, 1), shape: UnicodeSymbols.CIRCLE },
{ position: new DOMPoint(0, 0, 0, 1), shape: UnicodeSymbols.SQUARE },
],
}),
understandLevel({
width: 2,
height: 2,
colorScheme: colorPalettes.green,
checkRules,
symbols: [
{ position: new DOMPoint(0, 0, 0, 1), shape: UnicodeSymbols.CIRCLE },
{ position: new DOMPoint(1, 1, 0, 1), shape: UnicodeSymbols.SQUARE },
],
}),
],
{ canAdvanceFreely: true }
);
}
{
"private": true,
"scripts": {
"build": "esbuild --bundle --minify --format=esm --target=chrome92,safari14 --outdir=. main.ts"
},
"dependencies": {
"mazemerizing": "^0.0.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment