@blkc-code/render-canvas 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/office.js ADDED
@@ -0,0 +1,119 @@
1
+ /** Puts a world on a canvas: sizing, the frame loop, and pointer and keyboard input. */
2
+ import { drawWorld, TILE } from "./draw.js";
3
+ import { agentAt, applyUpdate, createWorld, step } from "./world.js";
4
+ const SAFE_COLOUR = /^(#[0-9a-f]{3,8}|rgba?\([\d\s.,%/]+\)|hsla?\([\d\s.,%/a-z]+\))$/i;
5
+ function readPalette(canvas) {
6
+ const styles = getComputedStyle(canvas);
7
+ const token = (name, fallback) => {
8
+ const value = styles.getPropertyValue(name).trim();
9
+ return SAFE_COLOUR.test(value) ? value : fallback;
10
+ };
11
+ return {
12
+ primary: token("--blkc-color-primary", "#3b82f6"),
13
+ accent: token("--blkc-color-accent", "#f59e0b"),
14
+ background: token("--blkc-color-background", "#1a1a2e"),
15
+ text: token("--blkc-color-text", "#ffffff"),
16
+ };
17
+ }
18
+ /** Draw an office and keep it running until destroy(). */
19
+ export function createOffice(canvas, scene = {}, options = {}) {
20
+ const world = createWorld(scene);
21
+ const context = canvas.getContext("2d");
22
+ if (!context)
23
+ throw new Error("This browser can't draw to a canvas.");
24
+ const c = context;
25
+ const width = world.cols * TILE;
26
+ const height = world.rows * TILE;
27
+ const palette = readPalette(canvas);
28
+ const still = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
29
+ let selected;
30
+ let scale = 0;
31
+ let time = 0;
32
+ let last = 0;
33
+ let frame = 0;
34
+ let visible = true;
35
+ let destroyed = false;
36
+ const paint = () => {
37
+ c.setTransform(scale, 0, 0, scale, 0, 0);
38
+ c.imageSmoothingEnabled = false;
39
+ drawWorld(c, world, time, palette, selected);
40
+ };
41
+ // The backing store is a whole multiple of the art, so every pixel stays square and text stays sharp.
42
+ const resize = () => {
43
+ const shown = canvas.getBoundingClientRect().width || width;
44
+ const ratio = typeof devicePixelRatio === "number" ? devicePixelRatio : 1;
45
+ const next = Math.max(1, Math.ceil((shown * ratio) / width));
46
+ if (next === scale)
47
+ return;
48
+ scale = next;
49
+ canvas.width = width * scale;
50
+ canvas.height = height * scale;
51
+ paint();
52
+ };
53
+ const loop = (now) => {
54
+ if (destroyed)
55
+ return;
56
+ frame = requestAnimationFrame(loop);
57
+ if (!visible) {
58
+ last = now;
59
+ return;
60
+ }
61
+ const dt = Math.min((now - last) / 1000 || 0, 0.1); // a stalled tab mustn't teleport people
62
+ last = now;
63
+ time += dt;
64
+ step(world, dt);
65
+ paint();
66
+ };
67
+ const select = (id) => {
68
+ const next = id === selected ? undefined : id;
69
+ selected = next;
70
+ options.onSelect?.(selected);
71
+ if (still)
72
+ paint();
73
+ };
74
+ const pointerTile = (event) => {
75
+ const box = canvas.getBoundingClientRect();
76
+ return { x: ((event.clientX - box.left) / box.width) * world.cols, y: ((event.clientY - box.top) / box.height) * world.rows };
77
+ };
78
+ const onDown = (event) => {
79
+ const { x, y } = pointerTile(event);
80
+ select(agentAt(world, x, y)?.id);
81
+ };
82
+ const onMove = (event) => {
83
+ const { x, y } = pointerTile(event);
84
+ canvas.style.cursor = agentAt(world, x, y) ? "pointer" : "default";
85
+ };
86
+ canvas.addEventListener("pointerdown", onDown);
87
+ canvas.addEventListener("pointermove", onMove);
88
+ const resizer = typeof ResizeObserver === "function" ? new ResizeObserver(resize) : undefined;
89
+ resizer?.observe(canvas);
90
+ const viewer = typeof IntersectionObserver === "function"
91
+ ? new IntersectionObserver((entries) => { visible = entries.some((entry) => entry.isIntersecting); })
92
+ : undefined;
93
+ viewer?.observe(canvas);
94
+ resize();
95
+ if (scale === 0) {
96
+ scale = 1;
97
+ paint();
98
+ }
99
+ if (!still)
100
+ frame = requestAnimationFrame(loop);
101
+ return {
102
+ world,
103
+ update(next) {
104
+ applyUpdate(world, next);
105
+ if (still)
106
+ paint();
107
+ },
108
+ select,
109
+ destroy() {
110
+ destroyed = true;
111
+ cancelAnimationFrame(frame);
112
+ resizer?.disconnect();
113
+ viewer?.disconnect();
114
+ canvas.removeEventListener("pointerdown", onDown);
115
+ canvas.removeEventListener("pointermove", onMove);
116
+ },
117
+ };
118
+ }
119
+ //# sourceMappingURL=office.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"office.js","sourceRoot":"","sources":["../src/office.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ "use strict";(()=>{var E={desk:{w:3,h:2,spot:{x:1,y:2}},coffee:{w:2,h:1,spot:{x:0,y:1}},water:{w:1,h:1,spot:{x:0,y:1}},sofa:{w:3,h:1,spot:{x:1,y:1}},plant:{w:1,h:1},board:{w:4,h:1,spot:{x:1,y:1}},shelf:{w:2,h:1,spot:{x:0,y:1}},server:{w:1,h:1},table:{w:3,h:2,spot:{x:1,y:2}},rug:{w:4,h:3,solid:!1}},ct=["working","thinking","blocked","reviewing","idle","done","away"],ut=["todo","doing","done"],dt=["wood","carpet","tile"],C={cols:26,rows:17,rooms:[{id:"studio",name:"Studio",x:1,y:3,w:15,h:13,floor:"wood"},{id:"lounge",name:"Lounge",x:17,y:3,w:8,h:6,floor:"carpet"},{id:"quests",name:"Quests",x:17,y:10,w:8,h:6,floor:"tile"}],doors:[{x:16,y:6},{x:16,y:13},{x:23,y:9}],furniture:[{type:"desk",x:2,y:4},{type:"desk",x:7,y:4},{type:"desk",x:12,y:4},{type:"desk",x:2,y:10},{type:"desk",x:7,y:10},{type:"desk",x:12,y:10},{type:"plant",x:1,y:8},{type:"plant",x:15,y:8},{type:"server",x:15,y:15},{type:"server",x:14,y:15},{type:"shelf",x:1,y:15},{type:"coffee",x:19,y:3},{type:"water",x:21,y:3},{type:"sofa",x:22,y:3},{type:"rug",x:20,y:5},{type:"plant",x:24,y:8},{type:"board",x:19,y:10},{type:"table",x:19,y:13},{type:"plant",x:24,y:15}]},A=(t,e)=>typeof t=="number"&&Number.isFinite(t)?Math.floor(t):e,w=(t,e=120)=>typeof t=="string"?t.slice(0,e):"",S=(t,e)=>Array.isArray(t)?t.slice(0,e):[];function V(t){let e=2166136261;for(let n=0;n<t.length;n++)e=Math.imul(e^t.charCodeAt(n),16777619);return e>>>0}var Y=["#2b1b12","#5a3a22","#a8622d","#d9b36c","#20242e","#7d2f3f","#4a5568","#e5e7eb"],Q=["#f4d3b5","#e8b98f","#c98d62","#9c6644","#6f4530","#4e2f20"],J=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316"],_=(t,e)=>typeof t=="string"&&/^#[0-9a-f]{3,8}$/i.test(t)?t:e,F=(t,e,n)=>n*t.cols+e;function R(t,e,n){return e>=0&&n>=0&&e<t.cols&&n<t.rows&&t.walkable[F(t,e,n)]===!0}function Z(t,e,n){if(!R(t,n.x,n.y))return null;if(e.x===n.x&&e.y===n.y)return[];let i=new Int32Array(t.cols*t.rows).fill(-1),r=F(t,e.x,e.y);i[r]=r;let s=[r];for(let o=0;o<s.length;o++){let a=s[o],u=a%t.cols,l=Math.floor(a/t.cols);if(u===n.x&&l===n.y){let h=[];for(let p=a;p!==r;p=i[p])h.unshift({x:p%t.cols,y:Math.floor(p/t.cols)});return h}for(let[h,p]of[[0,1],[0,-1],[1,0],[-1,0]]){let x=u+h,k=l+p;if(!R(t,x,k))continue;let M=F(t,x,k);i[M]===-1&&(i[M]=a,s.push(M))}}return null}function tt(t,e){let n=w(t?.id,60)||`agent-${e+1}`,i=V(n),r=ct.includes(t?.state)?t.state:"idle";return{id:n,name:w(t?.name,24)||n,role:w(t?.role,40),state:r,task:w(t?.task,120),hair:_(t?.hair,Y[i%Y.length]),skin:_(t?.skin,Q[(i>>>4)%Q.length]),shirt:_(t?.shirt,J[(i>>>8)%J.length]),x:0,y:0,path:[],facing:"down",walking:!1,rest:0,seed:i}}function et(t){return{title:w(t?.title,80),state:ut.includes(t?.state)?t.state:"todo",agent:w(t?.agent,60)}}function B(t={}){let e=Array.isArray(t?.rooms)&&t.rooms.length>0,n=Math.min(Math.max(A(t?.cols,e?20:C.cols),6),64),i=Math.min(Math.max(A(t?.rows,e?14:C.rows),6),40),r=e?S(t.rooms,40):C.rooms,s=e?S(t.doors,60):C.doors,o=Array.isArray(t?.furniture)?S(t.furniture,300):e?[]:C.furniture,a=r.map(c=>{let b=Math.min(Math.max(A(c?.x,0),0),n),y=Math.min(Math.max(A(c?.y,0),0),i);return{name:w(c?.name,24),x:b,y,w:Math.min(Math.max(A(c?.w,0),0),n-b),h:Math.min(Math.max(A(c?.h,0),0),i-y),floor:dt.includes(c?.floor)?c.floor:"wood"}}),u=new Array(n*i).fill(!1),l=(c,b,y)=>{c>=0&&b>=0&&c<n&&b<i&&(u[b*n+c]=y)};for(let c of a)for(let b=c.y;b<c.y+c.h;b++)for(let y=c.x;y<c.x+c.w;y++)l(y,b,!0);let h=s.map(c=>({x:A(c?.x,-1),y:A(c?.y,-1)})).filter(c=>c.x>=0&&c.y>=0);for(let c of h)l(c.x,c.y,!0);let p=o.filter(c=>c&&Object.hasOwn(E,c.type)).map(c=>({type:c.type,x:A(c.x,-99),y:A(c.y,-99)}));for(let c of p){let b=E[c.type];if(b.solid!==!1)for(let y=c.y;y<c.y+b.h;y++)for(let T=c.x;T<c.x+b.w;T++)l(T,y,!1)}let x={cols:n,rows:i,rooms:a,doors:h,furniture:p,walkable:u,agents:S(t?.agents,40).map(tt),tasks:S(t?.tasks,60).map(et),spots:{lounge:[],board:[]}},k=c=>{let b=E[c.type].spot;if(!b)return;let y={x:c.x+b.x,y:c.y+b.y};return R(x,y.x,y.y)?y:void 0},M=p.filter(c=>c.type==="desk").map(k).filter(c=>!!c);for(let c of p){let b=k(c);b&&((c.type==="coffee"||c.type==="sofa"||c.type==="water"||c.type==="shelf")&&x.spots.lounge.push(b),(c.type==="board"||c.type==="table")&&x.spots.board.push(b))}return x.agents.forEach((c,b)=>{c.seat=M[b],nt(x,c)}),x}function ht(t){for(let e=0;e<t.rows;e++)for(let n=0;n<t.cols;n++)if(R(t,n,e))return{x:n,y:e};return{x:0,y:0}}function I(t,e){let n=i=>i.length>0?i[(e.seed+Math.floor(e.rest*1e3))%i.length]:void 0;switch(e.state){case"working":case"thinking":case"blocked":return e.seat??n(t.spots.lounge);case"reviewing":return n(t.spots.board)??e.seat;case"idle":case"done":return n(t.spots.lounge)??e.seat;default:return}}function nt(t,e){let n=I(t,e)??e.seat??ht(t);e.x=n.x,e.y=n.y,e.path=[],e.walking=!1,e.facing=O(e)?"up":"down",e.rest=2+e.seed%50/10}var O=t=>(t.state==="working"||t.state==="thinking"||t.state==="blocked")&&t.seat!==void 0&&t.seat.x===t.x&&t.seat.y===t.y&&t.path.length===0;function ot(t,e,n){if(!n)return;let i={x:Math.round(e.x),y:Math.round(e.y)};e.path=Z(t,i,n)??[]}function D(t,e){for(let n of t.agents)if(n.state!=="away"){if(n.path.length>0){let i=n.path[0],r=i.x-n.x,s=i.y-n.y,o=Math.hypot(r,s),a=3.2*e;Math.abs(r)>Math.abs(s)?n.facing=r>0?"right":"left":s!==0&&(n.facing=s>0?"down":"up"),n.walking=!0,o<=a?(n.x=i.x,n.y=i.y,n.path.shift()):(n.x+=r/o*a,n.y+=s/o*a);continue}n.walking=!1,n.state==="idle"&&(n.rest-=e,n.rest<=0&&(n.seed=V(String(n.seed)),n.rest=3+n.seed%60/10,ot(t,n,I(t,n)))),O(n)&&(n.facing="up")}}function P(t,e){if(Array.isArray(e.tasks)&&(t.tasks=S(e.tasks,60).map(et)),!Array.isArray(e.agents))return;let n=new Map(t.agents.map(r=>[r.id,r])),i=t.furniture.filter(r=>r.type==="desk").map(r=>({x:r.x+1,y:r.y+2})).filter(r=>R(t,r.x,r.y));t.agents=S(e.agents,40).map((r,s)=>{let o=tt(r,s),a=n.get(o.id);return o.seat=i[s],a?(Object.assign(a,{name:o.name,role:o.role,task:o.task,hair:o.hair,skin:o.skin,shirt:o.shirt,seat:o.seat}),a.state!==o.state&&(a.state=o.state,o.state!=="away"&&ot(t,a,I(t,a))),a):(nt(t,o),o)})}function L(t,e,n){let i,r=1/0;for(let s of t.agents){if(s.state==="away")continue;let o=e-(s.x+.5),a=n-(s.y+.1),u=Math.hypot(o,a);Math.abs(o)<.8&&a>-1.6&&a<1.1&&u<r&&(i=s,r=u)}return i}var d=16,f=(t,e,n,i,r,s)=>{t.fillStyle=e,t.fillRect(Math.round(n),Math.round(i),r,s)},bt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hssssssh..","..ssessess..","..ssssssss..","...ssssss..."],pt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","...ssssss..."],yt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hhssssss..","..hhsssess..","..hsssssss..","...ssssss..."],mt=["..tttttttt..",".tttttttttt.",".stttttttts.",".stTTTTTTts."],xt=["...tttttt...","...tttttt...","...ttsttt...","...TTsTTT..."],gt=["..llllllll..","..lll..lll..","..lll..lll..","..bbb..bbb.."],kt=["..llllllll..","..lll..lll..","..bbb..lll..",".......bbb.."],Mt=["..llllllll..","..lll..lll..","..lll..bbb..","..bbb......."],At=["...llllll...","...lll.lll..","...lll.lll..","...bbb.bbb.."],St=["...llllll...","..lll..lll..",".lll....lll.",".bb......bb."],wt=["...llllll...","...llllll...","....llll....","....bbbb...."];function $(t,e,n,i,r,s=!1){e.forEach((o,a)=>{for(let u=0;u<o.length;u++){let l=o[s?o.length-1-u:u],h=r[l];h&&f(t,h,n+u,i+a,1,1)}})}function Tt(t,e){let n=parseInt(t.slice(1).padEnd(6,t.slice(-1)),16),i=r=>Math.max(0,Math.min(255,(n>>r&255)+e));return`rgb(${i(16)},${i(8)},${i(0)})`}function vt(t,e,n,i){let r=e.x*d+2,s=O(e),o={h:e.hair,s:e.skin,e:"#1a1a24",t:e.shirt,T:Tt(e.shirt,-36),l:"#39415a",b:"#1f2433"},a=Math.floor(n*8+e.seed)%2===0,u=!e.walking&&Math.floor(n*1.5+e.seed%7)%2===0?1:0,l=s?11:15,h=e.y*d+(s?6:-1)-(e.walking&&a?1:0);s&&(f(t,"#1f2937",r+1,e.y*d+3,10,9),f(t,"#374151",r+2,e.y*d+11,8,3),f(t,"#111827",r+5,e.y*d+14,2,2)),t.fillStyle="rgba(0,0,0,0.25)",t.fillRect(Math.round(r+2),Math.round(e.y*d+14),8,2),i&&(t.fillStyle="rgba(255,255,255,0.28)",t.fillRect(Math.round(r-1),Math.round(e.y*d+13),14,4));let p=e.facing==="left"||e.facing==="right",x=p?yt:e.facing==="up"?pt:bt,k=p?xt:mt,M=e.walking?p?a?St:wt:a?kt:Mt:p?At:gt,c=e.facing==="left";if($(t,x,r,h-l+u*0,o,c),$(t,k,r,h-l+x.length,o,c),!s)$(t,M,r,h-l+x.length+k.length,o,c);else if(e.state==="working"){let b=Math.floor(n*9+e.seed)%2;f(t,e.skin,r+1+b,h-l+x.length+3,1,1),f(t,e.skin,r+10-(1-b),h-l+x.length+3,1,1)}}function W(t,e,n,i){f(t,"#111827",e-1,n-1,13,11),f(t,"#ffffff",e,n,11,9),f(t,"#ffffff",e+4,n+9,3,1),f(t,"#111827",e+4,n+10,3,1),i(e,n)}function Et(t,e,n){let i=Math.round(e.x*d+2),r=Math.round(e.y*d-26+(O(e)?8:0)),s=Math.floor(n*2+e.seed%3)%2===0;if(e.state==="blocked")W(t,i,r,(o,a)=>{f(t,s?"#dc2626":"#991b1b",o+5,a+1,2,5),f(t,s?"#dc2626":"#991b1b",o+5,a+7,2,1)});else if(e.state==="thinking"){let o=Math.floor(n*3)%4;W(t,i,r,(a,u)=>{for(let l=0;l<3;l++)f(t,l<o?"#111827":"#d1d5db",a+2+l*3,u+4,2,2)})}else if(e.state==="reviewing"&&!e.walking)W(t,i,r,(o,a)=>{f(t,"#2563eb",o+4,a+1,4,1),f(t,"#2563eb",o+7,a+2,1,2),f(t,"#2563eb",o+5,a+4,2,1),f(t,"#2563eb",o+5,a+5,1,1),f(t,"#2563eb",o+5,a+7,1,1)});else if(e.state==="done"){let o=s?"#f59e0b":"#fbbf24";W(t,i,r,(a,u)=>{f(t,o,a+5,u+1,1,7),f(t,o,a+2,u+3,7,2),f(t,o,a+4,u+2,3,5)})}}function Ot(t,e,n){for(let i=e.y;i<e.y+e.h;i++)for(let r=e.x;r<e.x+e.w;r++){let s=r*d,o=i*d;if(e.floor==="carpet"){f(t,"#4c4f7a",s,o,d,d);for(let a=0;a<6;a++)f(t,"#55588a",s+(r*7+a*5)%15,o+(i*3+a*7)%15,1,1)}else if(e.floor==="tile")f(t,(r+i)%2===0?"#cfd8e3":"#bcc7d4",s,o,d,d),f(t,"#aab5c2",s,o+15,d,1),f(t,"#aab5c2",s+15,o,1,d);else{f(t,"#a06f45",s,o,d,d);let a=i%2===0?0:8;f(t,"#8f6039",s,o+7,d,1),f(t,"#8f6039",s,o+15,d,1),f(t,"#8f6039",s+(a+r*8)%16,o,1,7),f(t,"#ad7c52",s+3,o+3,4,1)}}}var it="#2f3350",Ct="#565c86",Rt="#454a70";function Lt(t,e,n){let i=new Set;for(let r of e.rooms)for(let s=r.y;s<r.y+r.h;s++)for(let o=r.x;o<r.x+r.w;o++)i.add(`${o},${s}`);for(let r of e.doors)i.add(`${r.x},${r.y}`);for(let r=0;r<e.rows;r++)for(let s=0;s<e.cols;s++){if(i.has(`${s},${r}`))continue;let o=s*d,a=r*d;i.has(`${s},${r+1}`)?(f(t,Ct,o,a,d,d),f(t,Rt,o,a+13,d,3),f(t,n.primary,o,a+12,d,1),s%4===3&&r<=3&&(f(t,"#1f2937",o+1,a+1,14,9),f(t,"#8ed0ff",o+2,a+2,12,7),f(t,"#bfe6ff",o+3,a+3,4,2),f(t,"#1f2937",o+8,a+2,1,7))):f(t,it,o,a,d,d)}for(let r of e.doors)f(t,"#6b4a2f",r.x*d,r.y*d,d,d),f(t,"#7c5637",r.x*d+2,r.y*d,12,d)}function Wt(t,e,n,i,r,s,o){if(f(t,"#6b4427",e+1,n+13,46,17),f(t,"#8a5a33",e+1,n+11,46,11),f(t,"#a06c3f",e+1,n+11,46,2),f(t,"#4a2e1a",e+3,n+22,3,9),f(t,"#4a2e1a",e+42,n+22,3,9),f(t,"#111827",e+15,n-1,18,13),f(t,"#374151",e+22,n+12,4,2),i){f(t,"#0f2a2e",e+16,n,16,11);let a=Math.floor(r*3+s%13);for(let u=0;u<4;u++){let l=3+((s>>u)+(a+u)*7)%11;f(t,u%2===0?o.primary:"#7dd3fc",e+17,n+1+u*2.5,l,1)}t.fillStyle="rgba(125,211,252,0.10)",t.fillRect(e+11,n+11,26,8)}else f(t,"#1f2937",e+16,n,16,11),f(t,"#374151",e+18,n+2,3,1);f(t,"#d1d5db",e+17,n+15,14,4),f(t,"#9ca3af",e+18,n+16,12,1),f(t,"#f3f4f6",e+38,n+14,4,4),f(t,o.primary,e+38,n+16,4,1)}function _t(t,e,n,i){f(t,"#2b2118",e,n-11,64,26),f(t,"#d9c29c",e+2,n-9,60,22);let r={todo:"#fde68a",doing:"#93c5fd",done:"#86efac"},s=8;i.tasks.slice(0,s*2).forEach((o,a)=>{let u=a%s,l=Math.floor(a/s);f(t,"#00000033",e+5+u*7,n-6+l*9,6,7),f(t,r[o.state],e+4+u*7,n-7+l*9,6,7),f(t,"#00000040",e+5+u*7,n-5+l*9,4,1)})}function st(t,e,n,i,r){let s=e.x*d,o=e.y*d;switch(e.type){case"desk":{let a=e.x+1,u=e.y+2,l=n.agents.find(h=>h.seat?.x===a&&h.seat?.y===u&&O(h)&&h.state!=="blocked");Wt(t,s,o,!!l,i,l?.seed??0,r);break}case"coffee":f(t,"#374151",s,o+2,32,14),f(t,"#6b7280",s,o+2,32,2),f(t,"#111827",s+4,o-8,14,14),f(t,"#ef4444",s+15,o-5,2,2),f(t,"#f3f4f6",s+8,o+3,5,4),f(t,"#f3f4f6",s+22,o-1,5,5);for(let a=0;a<3;a++)t.fillStyle="rgba(255,255,255,0.45)",t.fillRect(s+9+Math.round(Math.sin(i*2+a)*1.5),o-1-(i*8+a*4)%9,1,2);break;case"water":f(t,"#e5e7eb",s+3,o+3,10,13),f(t,"#7dd3fc",s+4,o-7,8,10),f(t,"#bae6fd",s+5,o-6,2,8),f(t,"#3b82f6",s+5,o+6,2,2);break;case"sofa":f(t,r.primary,s+1,o-6,46,9),f(t,"#00000030",s+1,o+1,46,2),f(t,"#4b5563",s,o+3,48,11),f(t,"#6b7280",s+3,o+3,20,7),f(t,"#6b7280",s+25,o+3,20,7),f(t,"#374151",s,o+12,48,3);break;case"plant":f(t,"#92400e",s+4,o+9,8,7),f(t,"#b45309",s+3,o+8,10,2);for(let[a,u,l,h]of[[6,-3,4,11],[2,0,5,6],[9,1,5,6],[4,-6,3,6],[9,-5,3,5]])f(t,"#15803d",s+a,o+u,l,h);f(t,"#22c55e",s+7,o-3,2,8),f(t,"#22c55e",s+3,o+1,2,3);break;case"board":_t(t,s,o,n);break;case"shelf":f(t,"#5b3a21",s,o-12,32,28);for(let a=0;a<2;a++){f(t,"#3b2413",s+2,o-10+a*13,28,11);for(let u=0;u<8;u++){let l=["#ef4444","#3b82f6","#10b981","#f59e0b","#8b5cf6"][(u*3+a)%5];f(t,l,s+3+u*3,o-8+a*13+u%3,2,9-u%3)}}break;case"server":f(t,"#111827",s+1,o-12,14,28);for(let a=0;a<5;a++){f(t,"#1f2937",s+2,o-11+a*5,12,4);let u=Math.floor(i*3+a*2+e.x)%3!==0;f(t,u?"#22c55e":"#14532d",s+3,o-10+a*5,1,1),f(t,a%2===0?"#f59e0b":"#3b82f6",s+5,o-10+a*5,1,1)}break;case"table":f(t,"#57534e",s+2,o+14,44,14),f(t,"#78716c",s+2,o+3,44,14),f(t,"#a8a29e",s+2,o+3,44,2),f(t,"#f9fafb",s+10,o+6,8,6),f(t,"#f9fafb",s+28,o+8,8,6);break;case"rug":f(t,r.primary,s,o,64,48),t.fillStyle="rgba(0,0,0,0.35)",t.fillRect(s+3,o+3,58,42),f(t,r.primary,s+6,o+6,52,1),f(t,r.primary,s+6,o+41,52,1);break}}function Ft(t,e){t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";for(let n of e.rooms){if(!n.name)continue;let i=n.name.toUpperCase(),r=n.x*d+3,s=n.y*d-12;t.fillStyle="rgba(0,0,0,0.45)",t.fillText(i,r+1,s+1),t.fillStyle="rgba(255,255,255,0.85)",t.fillText(i,r,s)}}function Bt(t,e,n,i){let r=e.name;t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let s=Math.ceil(t.measureText(r).width)+5,o=e.x*d+8,a=Math.round(Math.max(1,Math.min(i-s-1,o-s/2))),u=Math.round(e.y*d+15);t.fillStyle=n?"#ffffff":"rgba(17,24,39,0.82)",t.fillRect(a,u,s,10),t.fillStyle=n?"#111827":"#ffffff",t.fillText(r,a+2.5,u+1.5)}function It(t,e,n){let i=[],r="";for(let s of e.split(/\s+/)){let o=r?`${r} ${s}`:s;t.measureText(o).width>n&&r?(i.push(r),r=s):r=o}return r&&i.push(r),i.slice(0,3)}var rt={working:"Working",thinking:"Thinking",blocked:"Blocked",reviewing:"Reviewing",idle:"On a break",done:"Finished",away:"Away"};function Dt(t,e,n){t.font="7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let i=It(t,e.task||rt[e.state]||"",104),r=114,s=18+i.length*9+3,o=Math.round(Math.max(2,Math.min(n-r-2,e.x*d+8-r/2))),a=Math.round(Math.max(2,e.y*d-s-22));f(t,"#111827",o-1,a-1,r+2,s+2),f(t,"#ffffff",o,a,r,s),t.fillStyle="#111827",t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.fillText(`${e.name}: ${rt[e.state]??""}`.slice(0,26),o+4,a+4),t.fillStyle="#374151",t.font="7px ui-monospace, Menlo, Consolas, monospace",i.forEach((u,l)=>t.fillText(u,o+4,a+15+l*9))}function Pt(t,e,n){if(e.tasks.length===0)return;let i=e.tasks.filter(o=>o.state==="done").length,r=`QUESTS ${i}/${e.tasks.length}`;t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let s=96;f(t,"rgba(17,24,39,0.85)",4,4,s,20),t.fillStyle="#ffffff",t.fillText(r,8,6.5),f(t,"#374151",8,16,s-8,4),f(t,n.primary,8,16,Math.round((s-8)*i/e.tasks.length),4)}function at(t,e,n,i,r){let s=e.cols*d;f(t,it,0,0,s,e.rows*d);for(let l of e.rooms)Ot(t,l,i);Lt(t,e,i);for(let l of e.furniture)l.type==="rug"&&st(t,l,e,n,i);let o=[];for(let l of e.furniture)l.type!=="rug"&&o.push({depth:(l.y+E[l.type].h)*d-2,draw:()=>st(t,l,e,n,i)});let a=e.agents.filter(l=>l.state!=="away");for(let l of a)o.push({depth:l.y*d+14,draw:()=>vt(t,l,n,l.id===r)});o.sort((l,h)=>l.depth-h.depth);for(let l of o)l.draw();Ft(t,e);for(let l of a)Bt(t,l,l.id===r,s);for(let l of a)l.id!==r&&Et(t,l,n);Pt(t,e,i);let u=a.find(l=>l.id===r);u&&Dt(t,u,s)}var $t=/^(#[0-9a-f]{3,8}|rgba?\([\d\s.,%/]+\)|hsla?\([\d\s.,%/a-z]+\))$/i;function Ht(t){let e=getComputedStyle(t),n=(i,r)=>{let s=e.getPropertyValue(i).trim();return $t.test(s)?s:r};return{primary:n("--blkc-color-primary","#3b82f6"),accent:n("--blkc-color-accent","#f59e0b"),background:n("--blkc-color-background","#1a1a2e"),text:n("--blkc-color-text","#ffffff")}}function H(t,e={},n={}){let i=B(e),r=t.getContext("2d");if(!r)throw new Error("This browser can't draw to a canvas.");let s=r,o=i.cols*d,a=i.rows*d,u=Ht(t),l=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches,h,p=0,x=0,k=0,M=0,c=!0,b=!1,y=()=>{s.setTransform(p,0,0,p,0,0),s.imageSmoothingEnabled=!1,at(s,i,x,u,h)},T=()=>{let m=t.getBoundingClientRect().width||o,v=Math.max(1,Math.ceil(m*(typeof devicePixelRatio=="number"?devicePixelRatio:1)/o));v!==p&&(p=v,t.width=o*p,t.height=a*p,y())},U=m=>{if(b)return;if(M=requestAnimationFrame(U),!c){k=m;return}let g=Math.min((m-k)/1e3||0,.1);k=m,x+=g,D(i,g),y()},X=m=>{h=m===h?void 0:m,n.onSelect?.(h),l&&y()},G=m=>{let g=t.getBoundingClientRect();return{x:(m.clientX-g.left)/g.width*i.cols,y:(m.clientY-g.top)/g.height*i.rows}},K=m=>{let{x:g,y:v}=G(m);X(L(i,g,v)?.id)},j=m=>{let{x:g,y:v}=G(m);t.style.cursor=L(i,g,v)?"pointer":"default"};t.addEventListener("pointerdown",K),t.addEventListener("pointermove",j);let q=typeof ResizeObserver=="function"?new ResizeObserver(T):void 0;q?.observe(t);let z=typeof IntersectionObserver=="function"?new IntersectionObserver(m=>{c=m.some(g=>g.isIntersecting)}):void 0;return z?.observe(t),T(),p===0&&(p=1,y()),l||(M=requestAnimationFrame(U)),{world:i,update(m){P(i,m),l&&y()},select:X,destroy(){b=!0,cancelAnimationFrame(M),q?.disconnect(),z?.disconnect(),t.removeEventListener("pointerdown",K),t.removeEventListener("pointermove",j)}}}var lt=new Map;function Nt(t,e){lt.set(t,e)}function Ut(t,e,n){let i=[...n.querySelectorAll("button[data-blkc-agent]")],r=H(t,e,{onSelect(s){for(let o of i)o.setAttribute("aria-pressed",String(o.dataset.blkcAgent===s))}});for(let s of i)s.disabled=!1,s.addEventListener("click",()=>r.select(s.dataset.blkcAgent));return r}Nt("office",Ut);var ft=new WeakSet;function N(t=document){let e=[];for(let n of t.querySelectorAll("canvas[data-blkc-canvas]")){if(ft.has(n))continue;let i=lt.get(n.dataset.blkcCanvas??"");if(!i)continue;let r=n.closest("[data-blkc-canvas-root]")??n.parentElement??n,s=r.querySelector("script[data-blkc-canvas-data]"),o={};try{o=JSON.parse(s?.textContent||"{}")}catch{o={}}ft.add(n);let a=i(n,o,r);e.push({element:n,destroy:()=>a.destroy()})}return e}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>N()):N();})();
2
+ /**
3
+ * BLKC Render-Canvas.
4
+ *
5
+ * A canvas Block is ordinary markup from @blkc-code/render-web plus its data, and this
6
+ * package brings it to life. Call mountCanvasBlocks() once the page is in the document:
7
+ * a <canvas data-blkc-canvas="office"> with a JSON <script> beside it starts running.
8
+ *
9
+ * @package @blkc-code/render-canvas
10
+ * @license Apache-2.0
11
+ */
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;IACtC,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;AAC3E,CAAC;KAAM,CAAC;IACN,iBAAiB,EAAE,CAAC;AACtB,CAAC"}
@@ -0,0 +1,11 @@
1
+ "use strict";(()=>{var E={desk:{w:3,h:2,spot:{x:1,y:2}},coffee:{w:2,h:1,spot:{x:0,y:1}},water:{w:1,h:1,spot:{x:0,y:1}},sofa:{w:3,h:1,spot:{x:1,y:1}},plant:{w:1,h:1},board:{w:4,h:1,spot:{x:1,y:1}},shelf:{w:2,h:1,spot:{x:0,y:1}},server:{w:1,h:1},table:{w:3,h:2,spot:{x:1,y:2}},rug:{w:4,h:3,solid:!1}},ct=["working","thinking","blocked","reviewing","idle","done","away"],ut=["todo","doing","done"],dt=["wood","carpet","tile"],C={cols:26,rows:17,rooms:[{id:"studio",name:"Studio",x:1,y:3,w:15,h:13,floor:"wood"},{id:"lounge",name:"Lounge",x:17,y:3,w:8,h:6,floor:"carpet"},{id:"quests",name:"Quests",x:17,y:10,w:8,h:6,floor:"tile"}],doors:[{x:16,y:6},{x:16,y:13},{x:23,y:9}],furniture:[{type:"desk",x:2,y:4},{type:"desk",x:7,y:4},{type:"desk",x:12,y:4},{type:"desk",x:2,y:10},{type:"desk",x:7,y:10},{type:"desk",x:12,y:10},{type:"plant",x:1,y:8},{type:"plant",x:15,y:8},{type:"server",x:15,y:15},{type:"server",x:14,y:15},{type:"shelf",x:1,y:15},{type:"coffee",x:19,y:3},{type:"water",x:21,y:3},{type:"sofa",x:22,y:3},{type:"rug",x:20,y:5},{type:"plant",x:24,y:8},{type:"board",x:19,y:10},{type:"table",x:19,y:13},{type:"plant",x:24,y:15}]},A=(t,e)=>typeof t=="number"&&Number.isFinite(t)?Math.floor(t):e,w=(t,e=120)=>typeof t=="string"?t.slice(0,e):"",S=(t,e)=>Array.isArray(t)?t.slice(0,e):[];function V(t){let e=2166136261;for(let n=0;n<t.length;n++)e=Math.imul(e^t.charCodeAt(n),16777619);return e>>>0}var Y=["#2b1b12","#5a3a22","#a8622d","#d9b36c","#20242e","#7d2f3f","#4a5568","#e5e7eb"],Q=["#f4d3b5","#e8b98f","#c98d62","#9c6644","#6f4530","#4e2f20"],J=["#3b82f6","#ef4444","#10b981","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316"],_=(t,e)=>typeof t=="string"&&/^#[0-9a-f]{3,8}$/i.test(t)?t:e,F=(t,e,n)=>n*t.cols+e;function R(t,e,n){return e>=0&&n>=0&&e<t.cols&&n<t.rows&&t.walkable[F(t,e,n)]===!0}function Z(t,e,n){if(!R(t,n.x,n.y))return null;if(e.x===n.x&&e.y===n.y)return[];let i=new Int32Array(t.cols*t.rows).fill(-1),r=F(t,e.x,e.y);i[r]=r;let s=[r];for(let o=0;o<s.length;o++){let a=s[o],u=a%t.cols,l=Math.floor(a/t.cols);if(u===n.x&&l===n.y){let h=[];for(let p=a;p!==r;p=i[p])h.unshift({x:p%t.cols,y:Math.floor(p/t.cols)});return h}for(let[h,p]of[[0,1],[0,-1],[1,0],[-1,0]]){let x=u+h,k=l+p;if(!R(t,x,k))continue;let M=F(t,x,k);i[M]===-1&&(i[M]=a,s.push(M))}}return null}function tt(t,e){let n=w(t?.id,60)||`agent-${e+1}`,i=V(n),r=ct.includes(t?.state)?t.state:"idle";return{id:n,name:w(t?.name,24)||n,role:w(t?.role,40),state:r,task:w(t?.task,120),hair:_(t?.hair,Y[i%Y.length]),skin:_(t?.skin,Q[(i>>>4)%Q.length]),shirt:_(t?.shirt,J[(i>>>8)%J.length]),x:0,y:0,path:[],facing:"down",walking:!1,rest:0,seed:i}}function et(t){return{title:w(t?.title,80),state:ut.includes(t?.state)?t.state:"todo",agent:w(t?.agent,60)}}function B(t={}){let e=Array.isArray(t?.rooms)&&t.rooms.length>0,n=Math.min(Math.max(A(t?.cols,e?20:C.cols),6),64),i=Math.min(Math.max(A(t?.rows,e?14:C.rows),6),40),r=e?S(t.rooms,40):C.rooms,s=e?S(t.doors,60):C.doors,o=Array.isArray(t?.furniture)?S(t.furniture,300):e?[]:C.furniture,a=r.map(c=>{let b=Math.min(Math.max(A(c?.x,0),0),n),y=Math.min(Math.max(A(c?.y,0),0),i);return{name:w(c?.name,24),x:b,y,w:Math.min(Math.max(A(c?.w,0),0),n-b),h:Math.min(Math.max(A(c?.h,0),0),i-y),floor:dt.includes(c?.floor)?c.floor:"wood"}}),u=new Array(n*i).fill(!1),l=(c,b,y)=>{c>=0&&b>=0&&c<n&&b<i&&(u[b*n+c]=y)};for(let c of a)for(let b=c.y;b<c.y+c.h;b++)for(let y=c.x;y<c.x+c.w;y++)l(y,b,!0);let h=s.map(c=>({x:A(c?.x,-1),y:A(c?.y,-1)})).filter(c=>c.x>=0&&c.y>=0);for(let c of h)l(c.x,c.y,!0);let p=o.filter(c=>c&&Object.hasOwn(E,c.type)).map(c=>({type:c.type,x:A(c.x,-99),y:A(c.y,-99)}));for(let c of p){let b=E[c.type];if(b.solid!==!1)for(let y=c.y;y<c.y+b.h;y++)for(let T=c.x;T<c.x+b.w;T++)l(T,y,!1)}let x={cols:n,rows:i,rooms:a,doors:h,furniture:p,walkable:u,agents:S(t?.agents,40).map(tt),tasks:S(t?.tasks,60).map(et),spots:{lounge:[],board:[]}},k=c=>{let b=E[c.type].spot;if(!b)return;let y={x:c.x+b.x,y:c.y+b.y};return R(x,y.x,y.y)?y:void 0},M=p.filter(c=>c.type==="desk").map(k).filter(c=>!!c);for(let c of p){let b=k(c);b&&((c.type==="coffee"||c.type==="sofa"||c.type==="water"||c.type==="shelf")&&x.spots.lounge.push(b),(c.type==="board"||c.type==="table")&&x.spots.board.push(b))}return x.agents.forEach((c,b)=>{c.seat=M[b],nt(x,c)}),x}function ht(t){for(let e=0;e<t.rows;e++)for(let n=0;n<t.cols;n++)if(R(t,n,e))return{x:n,y:e};return{x:0,y:0}}function I(t,e){let n=i=>i.length>0?i[(e.seed+Math.floor(e.rest*1e3))%i.length]:void 0;switch(e.state){case"working":case"thinking":case"blocked":return e.seat??n(t.spots.lounge);case"reviewing":return n(t.spots.board)??e.seat;case"idle":case"done":return n(t.spots.lounge)??e.seat;default:return}}function nt(t,e){let n=I(t,e)??e.seat??ht(t);e.x=n.x,e.y=n.y,e.path=[],e.walking=!1,e.facing=O(e)?"up":"down",e.rest=2+e.seed%50/10}var O=t=>(t.state==="working"||t.state==="thinking"||t.state==="blocked")&&t.seat!==void 0&&t.seat.x===t.x&&t.seat.y===t.y&&t.path.length===0;function ot(t,e,n){if(!n)return;let i={x:Math.round(e.x),y:Math.round(e.y)};e.path=Z(t,i,n)??[]}function D(t,e){for(let n of t.agents)if(n.state!=="away"){if(n.path.length>0){let i=n.path[0],r=i.x-n.x,s=i.y-n.y,o=Math.hypot(r,s),a=3.2*e;Math.abs(r)>Math.abs(s)?n.facing=r>0?"right":"left":s!==0&&(n.facing=s>0?"down":"up"),n.walking=!0,o<=a?(n.x=i.x,n.y=i.y,n.path.shift()):(n.x+=r/o*a,n.y+=s/o*a);continue}n.walking=!1,n.state==="idle"&&(n.rest-=e,n.rest<=0&&(n.seed=V(String(n.seed)),n.rest=3+n.seed%60/10,ot(t,n,I(t,n)))),O(n)&&(n.facing="up")}}function P(t,e){if(Array.isArray(e.tasks)&&(t.tasks=S(e.tasks,60).map(et)),!Array.isArray(e.agents))return;let n=new Map(t.agents.map(r=>[r.id,r])),i=t.furniture.filter(r=>r.type==="desk").map(r=>({x:r.x+1,y:r.y+2})).filter(r=>R(t,r.x,r.y));t.agents=S(e.agents,40).map((r,s)=>{let o=tt(r,s),a=n.get(o.id);return o.seat=i[s],a?(Object.assign(a,{name:o.name,role:o.role,task:o.task,hair:o.hair,skin:o.skin,shirt:o.shirt,seat:o.seat}),a.state!==o.state&&(a.state=o.state,o.state!=="away"&&ot(t,a,I(t,a))),a):(nt(t,o),o)})}function L(t,e,n){let i,r=1/0;for(let s of t.agents){if(s.state==="away")continue;let o=e-(s.x+.5),a=n-(s.y+.1),u=Math.hypot(o,a);Math.abs(o)<.8&&a>-1.6&&a<1.1&&u<r&&(i=s,r=u)}return i}var d=16,f=(t,e,n,i,r,s)=>{t.fillStyle=e,t.fillRect(Math.round(n),Math.round(i),r,s)},bt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hssssssh..","..ssessess..","..ssssssss..","...ssssss..."],pt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","..hhhhhhhh..","...ssssss..."],yt=["...hhhhhh...","..hhhhhhhh..","..hhhhhhhh..","..hhssssss..","..hhsssess..","..hsssssss..","...ssssss..."],mt=["..tttttttt..",".tttttttttt.",".stttttttts.",".stTTTTTTts."],xt=["...tttttt...","...tttttt...","...ttsttt...","...TTsTTT..."],gt=["..llllllll..","..lll..lll..","..lll..lll..","..bbb..bbb.."],kt=["..llllllll..","..lll..lll..","..bbb..lll..",".......bbb.."],Mt=["..llllllll..","..lll..lll..","..lll..bbb..","..bbb......."],At=["...llllll...","...lll.lll..","...lll.lll..","...bbb.bbb.."],St=["...llllll...","..lll..lll..",".lll....lll.",".bb......bb."],wt=["...llllll...","...llllll...","....llll....","....bbbb...."];function $(t,e,n,i,r,s=!1){e.forEach((o,a)=>{for(let u=0;u<o.length;u++){let l=o[s?o.length-1-u:u],h=r[l];h&&f(t,h,n+u,i+a,1,1)}})}function Tt(t,e){let n=parseInt(t.slice(1).padEnd(6,t.slice(-1)),16),i=r=>Math.max(0,Math.min(255,(n>>r&255)+e));return`rgb(${i(16)},${i(8)},${i(0)})`}function vt(t,e,n,i){let r=e.x*d+2,s=O(e),o={h:e.hair,s:e.skin,e:"#1a1a24",t:e.shirt,T:Tt(e.shirt,-36),l:"#39415a",b:"#1f2433"},a=Math.floor(n*8+e.seed)%2===0,u=!e.walking&&Math.floor(n*1.5+e.seed%7)%2===0?1:0,l=s?11:15,h=e.y*d+(s?6:-1)-(e.walking&&a?1:0);s&&(f(t,"#1f2937",r+1,e.y*d+3,10,9),f(t,"#374151",r+2,e.y*d+11,8,3),f(t,"#111827",r+5,e.y*d+14,2,2)),t.fillStyle="rgba(0,0,0,0.25)",t.fillRect(Math.round(r+2),Math.round(e.y*d+14),8,2),i&&(t.fillStyle="rgba(255,255,255,0.28)",t.fillRect(Math.round(r-1),Math.round(e.y*d+13),14,4));let p=e.facing==="left"||e.facing==="right",x=p?yt:e.facing==="up"?pt:bt,k=p?xt:mt,M=e.walking?p?a?St:wt:a?kt:Mt:p?At:gt,c=e.facing==="left";if($(t,x,r,h-l+u*0,o,c),$(t,k,r,h-l+x.length,o,c),!s)$(t,M,r,h-l+x.length+k.length,o,c);else if(e.state==="working"){let b=Math.floor(n*9+e.seed)%2;f(t,e.skin,r+1+b,h-l+x.length+3,1,1),f(t,e.skin,r+10-(1-b),h-l+x.length+3,1,1)}}function W(t,e,n,i){f(t,"#111827",e-1,n-1,13,11),f(t,"#ffffff",e,n,11,9),f(t,"#ffffff",e+4,n+9,3,1),f(t,"#111827",e+4,n+10,3,1),i(e,n)}function Et(t,e,n){let i=Math.round(e.x*d+2),r=Math.round(e.y*d-26+(O(e)?8:0)),s=Math.floor(n*2+e.seed%3)%2===0;if(e.state==="blocked")W(t,i,r,(o,a)=>{f(t,s?"#dc2626":"#991b1b",o+5,a+1,2,5),f(t,s?"#dc2626":"#991b1b",o+5,a+7,2,1)});else if(e.state==="thinking"){let o=Math.floor(n*3)%4;W(t,i,r,(a,u)=>{for(let l=0;l<3;l++)f(t,l<o?"#111827":"#d1d5db",a+2+l*3,u+4,2,2)})}else if(e.state==="reviewing"&&!e.walking)W(t,i,r,(o,a)=>{f(t,"#2563eb",o+4,a+1,4,1),f(t,"#2563eb",o+7,a+2,1,2),f(t,"#2563eb",o+5,a+4,2,1),f(t,"#2563eb",o+5,a+5,1,1),f(t,"#2563eb",o+5,a+7,1,1)});else if(e.state==="done"){let o=s?"#f59e0b":"#fbbf24";W(t,i,r,(a,u)=>{f(t,o,a+5,u+1,1,7),f(t,o,a+2,u+3,7,2),f(t,o,a+4,u+2,3,5)})}}function Ot(t,e,n){for(let i=e.y;i<e.y+e.h;i++)for(let r=e.x;r<e.x+e.w;r++){let s=r*d,o=i*d;if(e.floor==="carpet"){f(t,"#4c4f7a",s,o,d,d);for(let a=0;a<6;a++)f(t,"#55588a",s+(r*7+a*5)%15,o+(i*3+a*7)%15,1,1)}else if(e.floor==="tile")f(t,(r+i)%2===0?"#cfd8e3":"#bcc7d4",s,o,d,d),f(t,"#aab5c2",s,o+15,d,1),f(t,"#aab5c2",s+15,o,1,d);else{f(t,"#a06f45",s,o,d,d);let a=i%2===0?0:8;f(t,"#8f6039",s,o+7,d,1),f(t,"#8f6039",s,o+15,d,1),f(t,"#8f6039",s+(a+r*8)%16,o,1,7),f(t,"#ad7c52",s+3,o+3,4,1)}}}var it="#2f3350",Ct="#565c86",Rt="#454a70";function Lt(t,e,n){let i=new Set;for(let r of e.rooms)for(let s=r.y;s<r.y+r.h;s++)for(let o=r.x;o<r.x+r.w;o++)i.add(`${o},${s}`);for(let r of e.doors)i.add(`${r.x},${r.y}`);for(let r=0;r<e.rows;r++)for(let s=0;s<e.cols;s++){if(i.has(`${s},${r}`))continue;let o=s*d,a=r*d;i.has(`${s},${r+1}`)?(f(t,Ct,o,a,d,d),f(t,Rt,o,a+13,d,3),f(t,n.primary,o,a+12,d,1),s%4===3&&r<=3&&(f(t,"#1f2937",o+1,a+1,14,9),f(t,"#8ed0ff",o+2,a+2,12,7),f(t,"#bfe6ff",o+3,a+3,4,2),f(t,"#1f2937",o+8,a+2,1,7))):f(t,it,o,a,d,d)}for(let r of e.doors)f(t,"#6b4a2f",r.x*d,r.y*d,d,d),f(t,"#7c5637",r.x*d+2,r.y*d,12,d)}function Wt(t,e,n,i,r,s,o){if(f(t,"#6b4427",e+1,n+13,46,17),f(t,"#8a5a33",e+1,n+11,46,11),f(t,"#a06c3f",e+1,n+11,46,2),f(t,"#4a2e1a",e+3,n+22,3,9),f(t,"#4a2e1a",e+42,n+22,3,9),f(t,"#111827",e+15,n-1,18,13),f(t,"#374151",e+22,n+12,4,2),i){f(t,"#0f2a2e",e+16,n,16,11);let a=Math.floor(r*3+s%13);for(let u=0;u<4;u++){let l=3+((s>>u)+(a+u)*7)%11;f(t,u%2===0?o.primary:"#7dd3fc",e+17,n+1+u*2.5,l,1)}t.fillStyle="rgba(125,211,252,0.10)",t.fillRect(e+11,n+11,26,8)}else f(t,"#1f2937",e+16,n,16,11),f(t,"#374151",e+18,n+2,3,1);f(t,"#d1d5db",e+17,n+15,14,4),f(t,"#9ca3af",e+18,n+16,12,1),f(t,"#f3f4f6",e+38,n+14,4,4),f(t,o.primary,e+38,n+16,4,1)}function _t(t,e,n,i){f(t,"#2b2118",e,n-11,64,26),f(t,"#d9c29c",e+2,n-9,60,22);let r={todo:"#fde68a",doing:"#93c5fd",done:"#86efac"},s=8;i.tasks.slice(0,s*2).forEach((o,a)=>{let u=a%s,l=Math.floor(a/s);f(t,"#00000033",e+5+u*7,n-6+l*9,6,7),f(t,r[o.state],e+4+u*7,n-7+l*9,6,7),f(t,"#00000040",e+5+u*7,n-5+l*9,4,1)})}function st(t,e,n,i,r){let s=e.x*d,o=e.y*d;switch(e.type){case"desk":{let a=e.x+1,u=e.y+2,l=n.agents.find(h=>h.seat?.x===a&&h.seat?.y===u&&O(h)&&h.state!=="blocked");Wt(t,s,o,!!l,i,l?.seed??0,r);break}case"coffee":f(t,"#374151",s,o+2,32,14),f(t,"#6b7280",s,o+2,32,2),f(t,"#111827",s+4,o-8,14,14),f(t,"#ef4444",s+15,o-5,2,2),f(t,"#f3f4f6",s+8,o+3,5,4),f(t,"#f3f4f6",s+22,o-1,5,5);for(let a=0;a<3;a++)t.fillStyle="rgba(255,255,255,0.45)",t.fillRect(s+9+Math.round(Math.sin(i*2+a)*1.5),o-1-(i*8+a*4)%9,1,2);break;case"water":f(t,"#e5e7eb",s+3,o+3,10,13),f(t,"#7dd3fc",s+4,o-7,8,10),f(t,"#bae6fd",s+5,o-6,2,8),f(t,"#3b82f6",s+5,o+6,2,2);break;case"sofa":f(t,r.primary,s+1,o-6,46,9),f(t,"#00000030",s+1,o+1,46,2),f(t,"#4b5563",s,o+3,48,11),f(t,"#6b7280",s+3,o+3,20,7),f(t,"#6b7280",s+25,o+3,20,7),f(t,"#374151",s,o+12,48,3);break;case"plant":f(t,"#92400e",s+4,o+9,8,7),f(t,"#b45309",s+3,o+8,10,2);for(let[a,u,l,h]of[[6,-3,4,11],[2,0,5,6],[9,1,5,6],[4,-6,3,6],[9,-5,3,5]])f(t,"#15803d",s+a,o+u,l,h);f(t,"#22c55e",s+7,o-3,2,8),f(t,"#22c55e",s+3,o+1,2,3);break;case"board":_t(t,s,o,n);break;case"shelf":f(t,"#5b3a21",s,o-12,32,28);for(let a=0;a<2;a++){f(t,"#3b2413",s+2,o-10+a*13,28,11);for(let u=0;u<8;u++){let l=["#ef4444","#3b82f6","#10b981","#f59e0b","#8b5cf6"][(u*3+a)%5];f(t,l,s+3+u*3,o-8+a*13+u%3,2,9-u%3)}}break;case"server":f(t,"#111827",s+1,o-12,14,28);for(let a=0;a<5;a++){f(t,"#1f2937",s+2,o-11+a*5,12,4);let u=Math.floor(i*3+a*2+e.x)%3!==0;f(t,u?"#22c55e":"#14532d",s+3,o-10+a*5,1,1),f(t,a%2===0?"#f59e0b":"#3b82f6",s+5,o-10+a*5,1,1)}break;case"table":f(t,"#57534e",s+2,o+14,44,14),f(t,"#78716c",s+2,o+3,44,14),f(t,"#a8a29e",s+2,o+3,44,2),f(t,"#f9fafb",s+10,o+6,8,6),f(t,"#f9fafb",s+28,o+8,8,6);break;case"rug":f(t,r.primary,s,o,64,48),t.fillStyle="rgba(0,0,0,0.35)",t.fillRect(s+3,o+3,58,42),f(t,r.primary,s+6,o+6,52,1),f(t,r.primary,s+6,o+41,52,1);break}}function Ft(t,e){t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";for(let n of e.rooms){if(!n.name)continue;let i=n.name.toUpperCase(),r=n.x*d+3,s=n.y*d-12;t.fillStyle="rgba(0,0,0,0.45)",t.fillText(i,r+1,s+1),t.fillStyle="rgba(255,255,255,0.85)",t.fillText(i,r,s)}}function Bt(t,e,n,i){let r=e.name;t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let s=Math.ceil(t.measureText(r).width)+5,o=e.x*d+8,a=Math.round(Math.max(1,Math.min(i-s-1,o-s/2))),u=Math.round(e.y*d+15);t.fillStyle=n?"#ffffff":"rgba(17,24,39,0.82)",t.fillRect(a,u,s,10),t.fillStyle=n?"#111827":"#ffffff",t.fillText(r,a+2.5,u+1.5)}function It(t,e,n){let i=[],r="";for(let s of e.split(/\s+/)){let o=r?`${r} ${s}`:s;t.measureText(o).width>n&&r?(i.push(r),r=s):r=o}return r&&i.push(r),i.slice(0,3)}var rt={working:"Working",thinking:"Thinking",blocked:"Blocked",reviewing:"Reviewing",idle:"On a break",done:"Finished",away:"Away"};function Dt(t,e,n){t.font="7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let i=It(t,e.task||rt[e.state]||"",104),r=114,s=18+i.length*9+3,o=Math.round(Math.max(2,Math.min(n-r-2,e.x*d+8-r/2))),a=Math.round(Math.max(2,e.y*d-s-22));f(t,"#111827",o-1,a-1,r+2,s+2),f(t,"#ffffff",o,a,r,s),t.fillStyle="#111827",t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.fillText(`${e.name}: ${rt[e.state]??""}`.slice(0,26),o+4,a+4),t.fillStyle="#374151",t.font="7px ui-monospace, Menlo, Consolas, monospace",i.forEach((u,l)=>t.fillText(u,o+4,a+15+l*9))}function Pt(t,e,n){if(e.tasks.length===0)return;let i=e.tasks.filter(o=>o.state==="done").length,r=`QUESTS ${i}/${e.tasks.length}`;t.font="bold 7px ui-monospace, Menlo, Consolas, monospace",t.textBaseline="top";let s=96;f(t,"rgba(17,24,39,0.85)",4,4,s,20),t.fillStyle="#ffffff",t.fillText(r,8,6.5),f(t,"#374151",8,16,s-8,4),f(t,n.primary,8,16,Math.round((s-8)*i/e.tasks.length),4)}function at(t,e,n,i,r){let s=e.cols*d;f(t,it,0,0,s,e.rows*d);for(let l of e.rooms)Ot(t,l,i);Lt(t,e,i);for(let l of e.furniture)l.type==="rug"&&st(t,l,e,n,i);let o=[];for(let l of e.furniture)l.type!=="rug"&&o.push({depth:(l.y+E[l.type].h)*d-2,draw:()=>st(t,l,e,n,i)});let a=e.agents.filter(l=>l.state!=="away");for(let l of a)o.push({depth:l.y*d+14,draw:()=>vt(t,l,n,l.id===r)});o.sort((l,h)=>l.depth-h.depth);for(let l of o)l.draw();Ft(t,e);for(let l of a)Bt(t,l,l.id===r,s);for(let l of a)l.id!==r&&Et(t,l,n);Pt(t,e,i);let u=a.find(l=>l.id===r);u&&Dt(t,u,s)}var $t=/^(#[0-9a-f]{3,8}|rgba?\([\d\s.,%/]+\)|hsla?\([\d\s.,%/a-z]+\))$/i;function Ht(t){let e=getComputedStyle(t),n=(i,r)=>{let s=e.getPropertyValue(i).trim();return $t.test(s)?s:r};return{primary:n("--blkc-color-primary","#3b82f6"),accent:n("--blkc-color-accent","#f59e0b"),background:n("--blkc-color-background","#1a1a2e"),text:n("--blkc-color-text","#ffffff")}}function H(t,e={},n={}){let i=B(e),r=t.getContext("2d");if(!r)throw new Error("This browser can't draw to a canvas.");let s=r,o=i.cols*d,a=i.rows*d,u=Ht(t),l=typeof matchMedia=="function"&&matchMedia("(prefers-reduced-motion: reduce)").matches,h,p=0,x=0,k=0,M=0,c=!0,b=!1,y=()=>{s.setTransform(p,0,0,p,0,0),s.imageSmoothingEnabled=!1,at(s,i,x,u,h)},T=()=>{let m=t.getBoundingClientRect().width||o,v=Math.max(1,Math.ceil(m*(typeof devicePixelRatio=="number"?devicePixelRatio:1)/o));v!==p&&(p=v,t.width=o*p,t.height=a*p,y())},U=m=>{if(b)return;if(M=requestAnimationFrame(U),!c){k=m;return}let g=Math.min((m-k)/1e3||0,.1);k=m,x+=g,D(i,g),y()},X=m=>{h=m===h?void 0:m,n.onSelect?.(h),l&&y()},G=m=>{let g=t.getBoundingClientRect();return{x:(m.clientX-g.left)/g.width*i.cols,y:(m.clientY-g.top)/g.height*i.rows}},K=m=>{let{x:g,y:v}=G(m);X(L(i,g,v)?.id)},j=m=>{let{x:g,y:v}=G(m);t.style.cursor=L(i,g,v)?"pointer":"default"};t.addEventListener("pointerdown",K),t.addEventListener("pointermove",j);let q=typeof ResizeObserver=="function"?new ResizeObserver(T):void 0;q?.observe(t);let z=typeof IntersectionObserver=="function"?new IntersectionObserver(m=>{c=m.some(g=>g.isIntersecting)}):void 0;return z?.observe(t),T(),p===0&&(p=1,y()),l||(M=requestAnimationFrame(U)),{world:i,update(m){P(i,m),l&&y()},select:X,destroy(){b=!0,cancelAnimationFrame(M),q?.disconnect(),z?.disconnect(),t.removeEventListener("pointerdown",K),t.removeEventListener("pointermove",j)}}}var lt=new Map;function Nt(t,e){lt.set(t,e)}function Ut(t,e,n){let i=[...n.querySelectorAll("button[data-blkc-agent]")],r=H(t,e,{onSelect(s){for(let o of i)o.setAttribute("aria-pressed",String(o.dataset.blkcAgent===s))}});for(let s of i)s.disabled=!1,s.addEventListener("click",()=>r.select(s.dataset.blkcAgent));return r}Nt("office",Ut);var ft=new WeakSet;function N(t=document){let e=[];for(let n of t.querySelectorAll("canvas[data-blkc-canvas]")){if(ft.has(n))continue;let i=lt.get(n.dataset.blkcCanvas??"");if(!i)continue;let r=n.closest("[data-blkc-canvas-root]")??n.parentElement??n,s=r.querySelector("script[data-blkc-canvas-data]"),o={};try{o=JSON.parse(s?.textContent||"{}")}catch{o={}}ft.add(n);let a=i(n,o,r);e.push({element:n,destroy:()=>a.destroy()})}return e}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>N()):N();})();
2
+ /**
3
+ * BLKC Render-Canvas.
4
+ *
5
+ * A canvas Block is ordinary markup from @blkc-code/render-web plus its data, and this
6
+ * package brings it to life. Call mountCanvasBlocks() once the page is in the document:
7
+ * a <canvas data-blkc-canvas="office"> with a JSON <script> beside it starts running.
8
+ *
9
+ * @package @blkc-code/render-canvas
10
+ * @license Apache-2.0
11
+ */
@@ -0,0 +1,49 @@
1
+ /** What a Kit writes to describe an office. All of it is plain JSON. */
2
+ export type AgentState = "working" | "thinking" | "blocked" | "reviewing" | "idle" | "done" | "away";
3
+ export type TaskState = "todo" | "doing" | "done";
4
+ export type FloorStyle = "wood" | "carpet" | "tile";
5
+ export type FurnitureType = "desk" | "coffee" | "sofa" | "plant" | "board" | "shelf" | "server" | "table" | "rug" | "water";
6
+ export interface OfficeRoom {
7
+ id?: string;
8
+ name?: string;
9
+ x: number;
10
+ y: number;
11
+ w: number;
12
+ h: number;
13
+ floor?: FloorStyle;
14
+ }
15
+ export interface OfficeDoor {
16
+ x: number;
17
+ y: number;
18
+ }
19
+ export interface OfficeFurniture {
20
+ type: FurnitureType;
21
+ x: number;
22
+ y: number;
23
+ }
24
+ export interface OfficeAgent {
25
+ id: string;
26
+ name?: string;
27
+ role?: string;
28
+ state?: AgentState;
29
+ task?: string;
30
+ /** Character colours. Anything left out is picked from the id. */
31
+ hair?: string;
32
+ skin?: string;
33
+ shirt?: string;
34
+ }
35
+ export interface OfficeTask {
36
+ title: string;
37
+ state?: TaskState;
38
+ agent?: string;
39
+ }
40
+ export interface OfficeScene {
41
+ cols?: number;
42
+ rows?: number;
43
+ rooms?: OfficeRoom[];
44
+ doors?: OfficeDoor[];
45
+ furniture?: OfficeFurniture[];
46
+ agents?: OfficeAgent[];
47
+ tasks?: OfficeTask[];
48
+ }
49
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAExE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AACrG,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAClD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AACpD,MAAM,MAAM,aAAa,GACrB,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC;AAEpG,MAAM,WAAW,UAAU;IAAG,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAE;AAC1H,MAAM,WAAW,UAAU;IAAG,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;AACpD,MAAM,WAAW,eAAe;IAAG,IAAI,EAAE,aAAa,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;AAC9E,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,UAAU;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAEhF,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;IACrB,SAAS,CAAC,EAAE,eAAe,EAAE,CAAC;IAC9B,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /** What a Kit writes to describe an office. All of it is plain JSON. */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,wEAAwE"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * The office as data: which tiles can be walked on, who is where, and where they are
3
+ * heading. Nothing in here touches a canvas, so all of it can be tested.
4
+ */
5
+ import type { AgentState, FloorStyle, FurnitureType, OfficeDoor, OfficeFurniture, OfficeRoom, OfficeScene, TaskState } from "./types.js";
6
+ export declare const MAX_COLS = 64;
7
+ export declare const MAX_ROWS = 40;
8
+ export declare const WALK_SPEED = 3.2;
9
+ /** Footprint in tiles, and where someone stands to use it, relative to its corner. */
10
+ export declare const FURNITURE: Record<FurnitureType, {
11
+ w: number;
12
+ h: number;
13
+ solid?: boolean;
14
+ spot?: {
15
+ x: number;
16
+ y: number;
17
+ };
18
+ }>;
19
+ export declare const DEFAULT_LAYOUT: {
20
+ cols: number;
21
+ rows: number;
22
+ rooms: OfficeRoom[];
23
+ doors: OfficeDoor[];
24
+ furniture: OfficeFurniture[];
25
+ };
26
+ export interface Room {
27
+ name: string;
28
+ x: number;
29
+ y: number;
30
+ w: number;
31
+ h: number;
32
+ floor: FloorStyle;
33
+ }
34
+ export interface Item {
35
+ type: FurnitureType;
36
+ x: number;
37
+ y: number;
38
+ }
39
+ export interface Task {
40
+ title: string;
41
+ state: TaskState;
42
+ agent: string;
43
+ }
44
+ export interface Agent {
45
+ id: string;
46
+ name: string;
47
+ role: string;
48
+ state: AgentState;
49
+ task: string;
50
+ hair: string;
51
+ skin: string;
52
+ shirt: string;
53
+ /** Position in tiles; x/y is the tile the feet are on. */
54
+ x: number;
55
+ y: number;
56
+ path: {
57
+ x: number;
58
+ y: number;
59
+ }[];
60
+ facing: "up" | "down" | "left" | "right";
61
+ walking: boolean;
62
+ seat?: {
63
+ x: number;
64
+ y: number;
65
+ };
66
+ /** Seconds until an idle agent picks somewhere new. */
67
+ rest: number;
68
+ seed: number;
69
+ }
70
+ export interface World {
71
+ cols: number;
72
+ rows: number;
73
+ rooms: Room[];
74
+ doors: OfficeDoor[];
75
+ furniture: Item[];
76
+ agents: Agent[];
77
+ tasks: Task[];
78
+ walkable: boolean[];
79
+ spots: {
80
+ lounge: {
81
+ x: number;
82
+ y: number;
83
+ }[];
84
+ board: {
85
+ x: number;
86
+ y: number;
87
+ }[];
88
+ };
89
+ }
90
+ export declare function hash(text: string): number;
91
+ export declare function isWalkable(world: World, x: number, y: number): boolean;
92
+ /** Shortest walk between two tiles, or null if they aren't connected. Excludes the start. */
93
+ export declare function findPath(world: World, from: {
94
+ x: number;
95
+ y: number;
96
+ }, to: {
97
+ x: number;
98
+ y: number;
99
+ }): {
100
+ x: number;
101
+ y: number;
102
+ }[] | null;
103
+ /** Build a world from a scene. Bad values are dropped or clamped, so it never throws. */
104
+ export declare function createWorld(scene?: OfficeScene): World;
105
+ /** Where this agent's current state wants them to be. */
106
+ export declare function goalFor(world: World, agent: Agent): {
107
+ x: number;
108
+ y: number;
109
+ } | undefined;
110
+ export declare const isSeated: (agent: Agent) => boolean;
111
+ /** Advance the whole office by `dt` seconds. */
112
+ export declare function step(world: World, dt: number): void;
113
+ /** Change what people are doing without restarting them. New agents appear at their goal. */
114
+ export declare function applyUpdate(world: World, scene: Pick<OfficeScene, "agents" | "tasks">): void;
115
+ /** Agent under a point given in tiles, nearest first. */
116
+ export declare function agentAt(world: World, x: number, y: number): Agent | undefined;
117
+ //# sourceMappingURL=world.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAe,UAAU,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAc,SAAS,EAAE,MAAM,YAAY,CAAC;AAElK,eAAO,MAAM,QAAQ,KAAK,CAAC;AAC3B,eAAO,MAAM,QAAQ,KAAK,CAAC;AAI3B,eAAO,MAAM,UAAU,MAAM,CAAC;AAE9B,sFAAsF;AACtF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAWvH,CAAC;AAMF,eAAO,MAAM,cAAc;;;WAOpB,UAAU,EAAE;WAC8C,UAAU,EAAE;eAQtE,eAAe,EAAE;CACvB,CAAC;AAMF,MAAM,WAAW,IAAI;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE;AACrG,MAAM,WAAW,IAAI;IAAG,IAAI,EAAE,aAAa,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE;AACnE,MAAM,WAAW,IAAI;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAExE,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjC,MAAM,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,EAAE,IAAI,EAAE,CAAC;IAClB,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE;QAAE,MAAM,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,KAAK,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,CAAC;CAClF;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIzC;AAYD,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEtE;AAED,6FAA6F;AAC7F,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EAAE,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,IAAI,CA6BtI;AA6BD,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,KAAK,GAAE,WAAgB,GAAG,KAAK,CAiE1D;AAOD,yDAAyD;AACzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAgBxF;AAYD,eAAO,MAAM,QAAQ,GAAI,OAAO,KAAK,KAAG,OAEqE,CAAC;AAQ9G,gDAAgD;AAChD,wBAAgB,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAmCnD;AAED,6FAA6F;AAC7F,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,IAAI,CAuB5F;AAED,yDAAyD;AACzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAc7E"}