diff --git a/assets/tile-samples/tile_r1_c0.png b/assets/tile-samples/tile_r1_c0.png new file mode 100644 index 0000000..b759a0d Binary files /dev/null and b/assets/tile-samples/tile_r1_c0.png differ diff --git a/assets/tile-samples/tile_r1_c2.png b/assets/tile-samples/tile_r1_c2.png new file mode 100644 index 0000000..32f2a4b Binary files /dev/null and b/assets/tile-samples/tile_r1_c2.png differ diff --git a/assets/tile-samples/tile_r1_c6.png b/assets/tile-samples/tile_r1_c6.png new file mode 100644 index 0000000..4210948 Binary files /dev/null and b/assets/tile-samples/tile_r1_c6.png differ diff --git a/assets/tile-samples/tile_r20_c0.png b/assets/tile-samples/tile_r20_c0.png new file mode 100644 index 0000000..60eb96a Binary files /dev/null and b/assets/tile-samples/tile_r20_c0.png differ diff --git a/assets/tile-samples/tile_r30_c0.png b/assets/tile-samples/tile_r30_c0.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/tile-samples/tile_r30_c0.png differ diff --git a/assets/tile-samples/tile_r40_c0.png b/assets/tile-samples/tile_r40_c0.png new file mode 100644 index 0000000..eb6df53 Binary files /dev/null and b/assets/tile-samples/tile_r40_c0.png differ diff --git a/assets/tile-samples/tile_r5_c0.png b/assets/tile-samples/tile_r5_c0.png new file mode 100644 index 0000000..45e7d14 Binary files /dev/null and b/assets/tile-samples/tile_r5_c0.png differ diff --git a/assets/tile-samples/tile_r5_c2.png b/assets/tile-samples/tile_r5_c2.png new file mode 100644 index 0000000..a5625b8 Binary files /dev/null and b/assets/tile-samples/tile_r5_c2.png differ diff --git a/assets/tile-samples/tile_r5_c6.png b/assets/tile-samples/tile_r5_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/tile-samples/tile_r5_c6.png differ diff --git a/assets/verified-tiles/t_r0_c0.png b/assets/verified-tiles/t_r0_c0.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c0.png differ diff --git a/assets/verified-tiles/t_r0_c1.png b/assets/verified-tiles/t_r0_c1.png new file mode 100644 index 0000000..b5aeb0c Binary files /dev/null and b/assets/verified-tiles/t_r0_c1.png differ diff --git a/assets/verified-tiles/t_r0_c10.png b/assets/verified-tiles/t_r0_c10.png new file mode 100644 index 0000000..ecf6440 Binary files /dev/null and b/assets/verified-tiles/t_r0_c10.png differ diff --git a/assets/verified-tiles/t_r0_c11.png b/assets/verified-tiles/t_r0_c11.png new file mode 100644 index 0000000..af2fe12 Binary files /dev/null and b/assets/verified-tiles/t_r0_c11.png differ diff --git a/assets/verified-tiles/t_r0_c12.png b/assets/verified-tiles/t_r0_c12.png new file mode 100644 index 0000000..29c8794 Binary files /dev/null and b/assets/verified-tiles/t_r0_c12.png differ diff --git a/assets/verified-tiles/t_r0_c13.png b/assets/verified-tiles/t_r0_c13.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c13.png differ diff --git a/assets/verified-tiles/t_r0_c14.png b/assets/verified-tiles/t_r0_c14.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c14.png differ diff --git a/assets/verified-tiles/t_r0_c15.png b/assets/verified-tiles/t_r0_c15.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c15.png differ diff --git a/assets/verified-tiles/t_r0_c2.png b/assets/verified-tiles/t_r0_c2.png new file mode 100644 index 0000000..99e2c53 Binary files /dev/null and b/assets/verified-tiles/t_r0_c2.png differ diff --git a/assets/verified-tiles/t_r0_c3.png b/assets/verified-tiles/t_r0_c3.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c3.png differ diff --git a/assets/verified-tiles/t_r0_c4.png b/assets/verified-tiles/t_r0_c4.png new file mode 100644 index 0000000..5519bdf Binary files /dev/null and b/assets/verified-tiles/t_r0_c4.png differ diff --git a/assets/verified-tiles/t_r0_c5.png b/assets/verified-tiles/t_r0_c5.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c5.png differ diff --git a/assets/verified-tiles/t_r0_c6.png b/assets/verified-tiles/t_r0_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c6.png differ diff --git a/assets/verified-tiles/t_r0_c7.png b/assets/verified-tiles/t_r0_c7.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c7.png differ diff --git a/assets/verified-tiles/t_r0_c8.png b/assets/verified-tiles/t_r0_c8.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c8.png differ diff --git a/assets/verified-tiles/t_r0_c9.png b/assets/verified-tiles/t_r0_c9.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r0_c9.png differ diff --git a/assets/verified-tiles/t_r10_c0.png b/assets/verified-tiles/t_r10_c0.png new file mode 100644 index 0000000..aceaad0 Binary files /dev/null and b/assets/verified-tiles/t_r10_c0.png differ diff --git a/assets/verified-tiles/t_r10_c1.png b/assets/verified-tiles/t_r10_c1.png new file mode 100644 index 0000000..a83cc47 Binary files /dev/null and b/assets/verified-tiles/t_r10_c1.png differ diff --git a/assets/verified-tiles/t_r10_c10.png b/assets/verified-tiles/t_r10_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r10_c10.png differ diff --git a/assets/verified-tiles/t_r10_c11.png b/assets/verified-tiles/t_r10_c11.png new file mode 100644 index 0000000..305192b Binary files /dev/null and b/assets/verified-tiles/t_r10_c11.png differ diff --git a/assets/verified-tiles/t_r10_c12.png b/assets/verified-tiles/t_r10_c12.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r10_c12.png differ diff --git a/assets/verified-tiles/t_r10_c13.png b/assets/verified-tiles/t_r10_c13.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r10_c13.png differ diff --git a/assets/verified-tiles/t_r10_c14.png b/assets/verified-tiles/t_r10_c14.png new file mode 100644 index 0000000..ce7ba32 Binary files /dev/null and b/assets/verified-tiles/t_r10_c14.png differ diff --git a/assets/verified-tiles/t_r10_c15.png b/assets/verified-tiles/t_r10_c15.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r10_c15.png differ diff --git a/assets/verified-tiles/t_r10_c2.png b/assets/verified-tiles/t_r10_c2.png new file mode 100644 index 0000000..dafb2e8 Binary files /dev/null and b/assets/verified-tiles/t_r10_c2.png differ diff --git a/assets/verified-tiles/t_r10_c3.png b/assets/verified-tiles/t_r10_c3.png new file mode 100644 index 0000000..20e23fa Binary files /dev/null and b/assets/verified-tiles/t_r10_c3.png differ diff --git a/assets/verified-tiles/t_r10_c4.png b/assets/verified-tiles/t_r10_c4.png new file mode 100644 index 0000000..dafb2e8 Binary files /dev/null and b/assets/verified-tiles/t_r10_c4.png differ diff --git a/assets/verified-tiles/t_r10_c5.png b/assets/verified-tiles/t_r10_c5.png new file mode 100644 index 0000000..565b369 Binary files /dev/null and b/assets/verified-tiles/t_r10_c5.png differ diff --git a/assets/verified-tiles/t_r10_c6.png b/assets/verified-tiles/t_r10_c6.png new file mode 100644 index 0000000..2044ef9 Binary files /dev/null and b/assets/verified-tiles/t_r10_c6.png differ diff --git a/assets/verified-tiles/t_r10_c7.png b/assets/verified-tiles/t_r10_c7.png new file mode 100644 index 0000000..2f89b19 Binary files /dev/null and b/assets/verified-tiles/t_r10_c7.png differ diff --git a/assets/verified-tiles/t_r10_c8.png b/assets/verified-tiles/t_r10_c8.png new file mode 100644 index 0000000..78f5817 Binary files /dev/null and b/assets/verified-tiles/t_r10_c8.png differ diff --git a/assets/verified-tiles/t_r10_c9.png b/assets/verified-tiles/t_r10_c9.png new file mode 100644 index 0000000..2f89b19 Binary files /dev/null and b/assets/verified-tiles/t_r10_c9.png differ diff --git a/assets/verified-tiles/t_r11_c0.png b/assets/verified-tiles/t_r11_c0.png new file mode 100644 index 0000000..b3f685f Binary files /dev/null and b/assets/verified-tiles/t_r11_c0.png differ diff --git a/assets/verified-tiles/t_r11_c1.png b/assets/verified-tiles/t_r11_c1.png new file mode 100644 index 0000000..7af64f0 Binary files /dev/null and b/assets/verified-tiles/t_r11_c1.png differ diff --git a/assets/verified-tiles/t_r11_c10.png b/assets/verified-tiles/t_r11_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r11_c10.png differ diff --git a/assets/verified-tiles/t_r11_c11.png b/assets/verified-tiles/t_r11_c11.png new file mode 100644 index 0000000..496491e Binary files /dev/null and b/assets/verified-tiles/t_r11_c11.png differ diff --git a/assets/verified-tiles/t_r11_c12.png b/assets/verified-tiles/t_r11_c12.png new file mode 100644 index 0000000..4496d04 Binary files /dev/null and b/assets/verified-tiles/t_r11_c12.png differ diff --git a/assets/verified-tiles/t_r11_c13.png b/assets/verified-tiles/t_r11_c13.png new file mode 100644 index 0000000..57d4517 Binary files /dev/null and b/assets/verified-tiles/t_r11_c13.png differ diff --git a/assets/verified-tiles/t_r11_c14.png b/assets/verified-tiles/t_r11_c14.png new file mode 100644 index 0000000..bc60cc3 Binary files /dev/null and b/assets/verified-tiles/t_r11_c14.png differ diff --git a/assets/verified-tiles/t_r11_c15.png b/assets/verified-tiles/t_r11_c15.png new file mode 100644 index 0000000..aa70cdb Binary files /dev/null and b/assets/verified-tiles/t_r11_c15.png differ diff --git a/assets/verified-tiles/t_r11_c2.png b/assets/verified-tiles/t_r11_c2.png new file mode 100644 index 0000000..7af64f0 Binary files /dev/null and b/assets/verified-tiles/t_r11_c2.png differ diff --git a/assets/verified-tiles/t_r11_c3.png b/assets/verified-tiles/t_r11_c3.png new file mode 100644 index 0000000..3f1ce9a Binary files /dev/null and b/assets/verified-tiles/t_r11_c3.png differ diff --git a/assets/verified-tiles/t_r11_c4.png b/assets/verified-tiles/t_r11_c4.png new file mode 100644 index 0000000..7af64f0 Binary files /dev/null and b/assets/verified-tiles/t_r11_c4.png differ diff --git a/assets/verified-tiles/t_r11_c5.png b/assets/verified-tiles/t_r11_c5.png new file mode 100644 index 0000000..57a8d41 Binary files /dev/null and b/assets/verified-tiles/t_r11_c5.png differ diff --git a/assets/verified-tiles/t_r11_c6.png b/assets/verified-tiles/t_r11_c6.png new file mode 100644 index 0000000..fa26cb7 Binary files /dev/null and b/assets/verified-tiles/t_r11_c6.png differ diff --git a/assets/verified-tiles/t_r11_c7.png b/assets/verified-tiles/t_r11_c7.png new file mode 100644 index 0000000..fa26cb7 Binary files /dev/null and b/assets/verified-tiles/t_r11_c7.png differ diff --git a/assets/verified-tiles/t_r11_c8.png b/assets/verified-tiles/t_r11_c8.png new file mode 100644 index 0000000..c499e91 Binary files /dev/null and b/assets/verified-tiles/t_r11_c8.png differ diff --git a/assets/verified-tiles/t_r11_c9.png b/assets/verified-tiles/t_r11_c9.png new file mode 100644 index 0000000..fa26cb7 Binary files /dev/null and b/assets/verified-tiles/t_r11_c9.png differ diff --git a/assets/verified-tiles/t_r12_c0.png b/assets/verified-tiles/t_r12_c0.png new file mode 100644 index 0000000..937854c Binary files /dev/null and b/assets/verified-tiles/t_r12_c0.png differ diff --git a/assets/verified-tiles/t_r12_c1.png b/assets/verified-tiles/t_r12_c1.png new file mode 100644 index 0000000..7e15bdb Binary files /dev/null and b/assets/verified-tiles/t_r12_c1.png differ diff --git a/assets/verified-tiles/t_r12_c10.png b/assets/verified-tiles/t_r12_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r12_c10.png differ diff --git a/assets/verified-tiles/t_r12_c11.png b/assets/verified-tiles/t_r12_c11.png new file mode 100644 index 0000000..c52c8d6 Binary files /dev/null and b/assets/verified-tiles/t_r12_c11.png differ diff --git a/assets/verified-tiles/t_r12_c12.png b/assets/verified-tiles/t_r12_c12.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r12_c12.png differ diff --git a/assets/verified-tiles/t_r12_c13.png b/assets/verified-tiles/t_r12_c13.png new file mode 100644 index 0000000..dc29a04 Binary files /dev/null and b/assets/verified-tiles/t_r12_c13.png differ diff --git a/assets/verified-tiles/t_r12_c14.png b/assets/verified-tiles/t_r12_c14.png new file mode 100644 index 0000000..525a2f2 Binary files /dev/null and b/assets/verified-tiles/t_r12_c14.png differ diff --git a/assets/verified-tiles/t_r12_c15.png b/assets/verified-tiles/t_r12_c15.png new file mode 100644 index 0000000..3c53ed1 Binary files /dev/null and b/assets/verified-tiles/t_r12_c15.png differ diff --git a/assets/verified-tiles/t_r12_c2.png b/assets/verified-tiles/t_r12_c2.png new file mode 100644 index 0000000..fa60311 Binary files /dev/null and b/assets/verified-tiles/t_r12_c2.png differ diff --git a/assets/verified-tiles/t_r12_c3.png b/assets/verified-tiles/t_r12_c3.png new file mode 100644 index 0000000..77f9fe2 Binary files /dev/null and b/assets/verified-tiles/t_r12_c3.png differ diff --git a/assets/verified-tiles/t_r12_c4.png b/assets/verified-tiles/t_r12_c4.png new file mode 100644 index 0000000..1b3c8a2 Binary files /dev/null and b/assets/verified-tiles/t_r12_c4.png differ diff --git a/assets/verified-tiles/t_r12_c5.png b/assets/verified-tiles/t_r12_c5.png new file mode 100644 index 0000000..d98f881 Binary files /dev/null and b/assets/verified-tiles/t_r12_c5.png differ diff --git a/assets/verified-tiles/t_r12_c6.png b/assets/verified-tiles/t_r12_c6.png new file mode 100644 index 0000000..974f0c2 Binary files /dev/null and b/assets/verified-tiles/t_r12_c6.png differ diff --git a/assets/verified-tiles/t_r12_c7.png b/assets/verified-tiles/t_r12_c7.png new file mode 100644 index 0000000..7977c57 Binary files /dev/null and b/assets/verified-tiles/t_r12_c7.png differ diff --git a/assets/verified-tiles/t_r12_c8.png b/assets/verified-tiles/t_r12_c8.png new file mode 100644 index 0000000..8e45daf Binary files /dev/null and b/assets/verified-tiles/t_r12_c8.png differ diff --git a/assets/verified-tiles/t_r12_c9.png b/assets/verified-tiles/t_r12_c9.png new file mode 100644 index 0000000..ad66a09 Binary files /dev/null and b/assets/verified-tiles/t_r12_c9.png differ diff --git a/assets/verified-tiles/t_r13_c0.png b/assets/verified-tiles/t_r13_c0.png new file mode 100644 index 0000000..a8188dc Binary files /dev/null and b/assets/verified-tiles/t_r13_c0.png differ diff --git a/assets/verified-tiles/t_r13_c1.png b/assets/verified-tiles/t_r13_c1.png new file mode 100644 index 0000000..fcd4145 Binary files /dev/null and b/assets/verified-tiles/t_r13_c1.png differ diff --git a/assets/verified-tiles/t_r13_c10.png b/assets/verified-tiles/t_r13_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r13_c10.png differ diff --git a/assets/verified-tiles/t_r13_c11.png b/assets/verified-tiles/t_r13_c11.png new file mode 100644 index 0000000..dba934a Binary files /dev/null and b/assets/verified-tiles/t_r13_c11.png differ diff --git a/assets/verified-tiles/t_r13_c12.png b/assets/verified-tiles/t_r13_c12.png new file mode 100644 index 0000000..3b86d72 Binary files /dev/null and b/assets/verified-tiles/t_r13_c12.png differ diff --git a/assets/verified-tiles/t_r13_c13.png b/assets/verified-tiles/t_r13_c13.png new file mode 100644 index 0000000..dc29a04 Binary files /dev/null and b/assets/verified-tiles/t_r13_c13.png differ diff --git a/assets/verified-tiles/t_r13_c14.png b/assets/verified-tiles/t_r13_c14.png new file mode 100644 index 0000000..80e810f Binary files /dev/null and b/assets/verified-tiles/t_r13_c14.png differ diff --git a/assets/verified-tiles/t_r13_c15.png b/assets/verified-tiles/t_r13_c15.png new file mode 100644 index 0000000..3c53ed1 Binary files /dev/null and b/assets/verified-tiles/t_r13_c15.png differ diff --git a/assets/verified-tiles/t_r13_c2.png b/assets/verified-tiles/t_r13_c2.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r13_c2.png differ diff --git a/assets/verified-tiles/t_r13_c3.png b/assets/verified-tiles/t_r13_c3.png new file mode 100644 index 0000000..93a38e9 Binary files /dev/null and b/assets/verified-tiles/t_r13_c3.png differ diff --git a/assets/verified-tiles/t_r13_c4.png b/assets/verified-tiles/t_r13_c4.png new file mode 100644 index 0000000..17c4a6b Binary files /dev/null and b/assets/verified-tiles/t_r13_c4.png differ diff --git a/assets/verified-tiles/t_r13_c5.png b/assets/verified-tiles/t_r13_c5.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r13_c5.png differ diff --git a/assets/verified-tiles/t_r13_c6.png b/assets/verified-tiles/t_r13_c6.png new file mode 100644 index 0000000..43b8c65 Binary files /dev/null and b/assets/verified-tiles/t_r13_c6.png differ diff --git a/assets/verified-tiles/t_r13_c7.png b/assets/verified-tiles/t_r13_c7.png new file mode 100644 index 0000000..d59e04e Binary files /dev/null and b/assets/verified-tiles/t_r13_c7.png differ diff --git a/assets/verified-tiles/t_r13_c8.png b/assets/verified-tiles/t_r13_c8.png new file mode 100644 index 0000000..8b30d1e Binary files /dev/null and b/assets/verified-tiles/t_r13_c8.png differ diff --git a/assets/verified-tiles/t_r13_c9.png b/assets/verified-tiles/t_r13_c9.png new file mode 100644 index 0000000..d301269 Binary files /dev/null and b/assets/verified-tiles/t_r13_c9.png differ diff --git a/assets/verified-tiles/t_r14_c0.png b/assets/verified-tiles/t_r14_c0.png new file mode 100644 index 0000000..1eb338b Binary files /dev/null and b/assets/verified-tiles/t_r14_c0.png differ diff --git a/assets/verified-tiles/t_r14_c1.png b/assets/verified-tiles/t_r14_c1.png new file mode 100644 index 0000000..50e966d Binary files /dev/null and b/assets/verified-tiles/t_r14_c1.png differ diff --git a/assets/verified-tiles/t_r14_c10.png b/assets/verified-tiles/t_r14_c10.png new file mode 100644 index 0000000..7761805 Binary files /dev/null and b/assets/verified-tiles/t_r14_c10.png differ diff --git a/assets/verified-tiles/t_r14_c11.png b/assets/verified-tiles/t_r14_c11.png new file mode 100644 index 0000000..c2a95f1 Binary files /dev/null and b/assets/verified-tiles/t_r14_c11.png differ diff --git a/assets/verified-tiles/t_r14_c12.png b/assets/verified-tiles/t_r14_c12.png new file mode 100644 index 0000000..c03a301 Binary files /dev/null and b/assets/verified-tiles/t_r14_c12.png differ diff --git a/assets/verified-tiles/t_r14_c13.png b/assets/verified-tiles/t_r14_c13.png new file mode 100644 index 0000000..5f94ad9 Binary files /dev/null and b/assets/verified-tiles/t_r14_c13.png differ diff --git a/assets/verified-tiles/t_r14_c14.png b/assets/verified-tiles/t_r14_c14.png new file mode 100644 index 0000000..e0fe81f Binary files /dev/null and b/assets/verified-tiles/t_r14_c14.png differ diff --git a/assets/verified-tiles/t_r14_c15.png b/assets/verified-tiles/t_r14_c15.png new file mode 100644 index 0000000..126c043 Binary files /dev/null and b/assets/verified-tiles/t_r14_c15.png differ diff --git a/assets/verified-tiles/t_r14_c2.png b/assets/verified-tiles/t_r14_c2.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r14_c2.png differ diff --git a/assets/verified-tiles/t_r14_c3.png b/assets/verified-tiles/t_r14_c3.png new file mode 100644 index 0000000..9d0a058 Binary files /dev/null and b/assets/verified-tiles/t_r14_c3.png differ diff --git a/assets/verified-tiles/t_r14_c4.png b/assets/verified-tiles/t_r14_c4.png new file mode 100644 index 0000000..41848ff Binary files /dev/null and b/assets/verified-tiles/t_r14_c4.png differ diff --git a/assets/verified-tiles/t_r14_c5.png b/assets/verified-tiles/t_r14_c5.png new file mode 100644 index 0000000..ab3742e Binary files /dev/null and b/assets/verified-tiles/t_r14_c5.png differ diff --git a/assets/verified-tiles/t_r14_c6.png b/assets/verified-tiles/t_r14_c6.png new file mode 100644 index 0000000..992163f Binary files /dev/null and b/assets/verified-tiles/t_r14_c6.png differ diff --git a/assets/verified-tiles/t_r14_c7.png b/assets/verified-tiles/t_r14_c7.png new file mode 100644 index 0000000..2f1d2ff Binary files /dev/null and b/assets/verified-tiles/t_r14_c7.png differ diff --git a/assets/verified-tiles/t_r14_c8.png b/assets/verified-tiles/t_r14_c8.png new file mode 100644 index 0000000..3b3c456 Binary files /dev/null and b/assets/verified-tiles/t_r14_c8.png differ diff --git a/assets/verified-tiles/t_r14_c9.png b/assets/verified-tiles/t_r14_c9.png new file mode 100644 index 0000000..14ff6d1 Binary files /dev/null and b/assets/verified-tiles/t_r14_c9.png differ diff --git a/assets/verified-tiles/t_r1_c0.png b/assets/verified-tiles/t_r1_c0.png new file mode 100644 index 0000000..b759a0d Binary files /dev/null and b/assets/verified-tiles/t_r1_c0.png differ diff --git a/assets/verified-tiles/t_r1_c1.png b/assets/verified-tiles/t_r1_c1.png new file mode 100644 index 0000000..f218ad7 Binary files /dev/null and b/assets/verified-tiles/t_r1_c1.png differ diff --git a/assets/verified-tiles/t_r1_c10.png b/assets/verified-tiles/t_r1_c10.png new file mode 100644 index 0000000..f811d45 Binary files /dev/null and b/assets/verified-tiles/t_r1_c10.png differ diff --git a/assets/verified-tiles/t_r1_c11.png b/assets/verified-tiles/t_r1_c11.png new file mode 100644 index 0000000..16ac758 Binary files /dev/null and b/assets/verified-tiles/t_r1_c11.png differ diff --git a/assets/verified-tiles/t_r1_c12.png b/assets/verified-tiles/t_r1_c12.png new file mode 100644 index 0000000..917ebb3 Binary files /dev/null and b/assets/verified-tiles/t_r1_c12.png differ diff --git a/assets/verified-tiles/t_r1_c13.png b/assets/verified-tiles/t_r1_c13.png new file mode 100644 index 0000000..1a4fd1c Binary files /dev/null and b/assets/verified-tiles/t_r1_c13.png differ diff --git a/assets/verified-tiles/t_r1_c14.png b/assets/verified-tiles/t_r1_c14.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r1_c14.png differ diff --git a/assets/verified-tiles/t_r1_c15.png b/assets/verified-tiles/t_r1_c15.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r1_c15.png differ diff --git a/assets/verified-tiles/t_r1_c2.png b/assets/verified-tiles/t_r1_c2.png new file mode 100644 index 0000000..32f2a4b Binary files /dev/null and b/assets/verified-tiles/t_r1_c2.png differ diff --git a/assets/verified-tiles/t_r1_c3.png b/assets/verified-tiles/t_r1_c3.png new file mode 100644 index 0000000..913633b Binary files /dev/null and b/assets/verified-tiles/t_r1_c3.png differ diff --git a/assets/verified-tiles/t_r1_c4.png b/assets/verified-tiles/t_r1_c4.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r1_c4.png differ diff --git a/assets/verified-tiles/t_r1_c5.png b/assets/verified-tiles/t_r1_c5.png new file mode 100644 index 0000000..87a4e84 Binary files /dev/null and b/assets/verified-tiles/t_r1_c5.png differ diff --git a/assets/verified-tiles/t_r1_c6.png b/assets/verified-tiles/t_r1_c6.png new file mode 100644 index 0000000..4210948 Binary files /dev/null and b/assets/verified-tiles/t_r1_c6.png differ diff --git a/assets/verified-tiles/t_r1_c7.png b/assets/verified-tiles/t_r1_c7.png new file mode 100644 index 0000000..8920a07 Binary files /dev/null and b/assets/verified-tiles/t_r1_c7.png differ diff --git a/assets/verified-tiles/t_r1_c8.png b/assets/verified-tiles/t_r1_c8.png new file mode 100644 index 0000000..faa9beb Binary files /dev/null and b/assets/verified-tiles/t_r1_c8.png differ diff --git a/assets/verified-tiles/t_r1_c9.png b/assets/verified-tiles/t_r1_c9.png new file mode 100644 index 0000000..62ecaaa Binary files /dev/null and b/assets/verified-tiles/t_r1_c9.png differ diff --git a/assets/verified-tiles/t_r2_c0.png b/assets/verified-tiles/t_r2_c0.png new file mode 100644 index 0000000..6df96e7 Binary files /dev/null and b/assets/verified-tiles/t_r2_c0.png differ diff --git a/assets/verified-tiles/t_r2_c1.png b/assets/verified-tiles/t_r2_c1.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r2_c1.png differ diff --git a/assets/verified-tiles/t_r2_c10.png b/assets/verified-tiles/t_r2_c10.png new file mode 100644 index 0000000..4f2cffa Binary files /dev/null and b/assets/verified-tiles/t_r2_c10.png differ diff --git a/assets/verified-tiles/t_r2_c11.png b/assets/verified-tiles/t_r2_c11.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r2_c11.png differ diff --git a/assets/verified-tiles/t_r2_c12.png b/assets/verified-tiles/t_r2_c12.png new file mode 100644 index 0000000..4e71007 Binary files /dev/null and b/assets/verified-tiles/t_r2_c12.png differ diff --git a/assets/verified-tiles/t_r2_c13.png b/assets/verified-tiles/t_r2_c13.png new file mode 100644 index 0000000..4f2cffa Binary files /dev/null and b/assets/verified-tiles/t_r2_c13.png differ diff --git a/assets/verified-tiles/t_r2_c14.png b/assets/verified-tiles/t_r2_c14.png new file mode 100644 index 0000000..5522e3a Binary files /dev/null and b/assets/verified-tiles/t_r2_c14.png differ diff --git a/assets/verified-tiles/t_r2_c15.png b/assets/verified-tiles/t_r2_c15.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r2_c15.png differ diff --git a/assets/verified-tiles/t_r2_c2.png b/assets/verified-tiles/t_r2_c2.png new file mode 100644 index 0000000..fc14a0e Binary files /dev/null and b/assets/verified-tiles/t_r2_c2.png differ diff --git a/assets/verified-tiles/t_r2_c3.png b/assets/verified-tiles/t_r2_c3.png new file mode 100644 index 0000000..6df96e7 Binary files /dev/null and b/assets/verified-tiles/t_r2_c3.png differ diff --git a/assets/verified-tiles/t_r2_c4.png b/assets/verified-tiles/t_r2_c4.png new file mode 100644 index 0000000..33d776d Binary files /dev/null and b/assets/verified-tiles/t_r2_c4.png differ diff --git a/assets/verified-tiles/t_r2_c5.png b/assets/verified-tiles/t_r2_c5.png new file mode 100644 index 0000000..d14fa35 Binary files /dev/null and b/assets/verified-tiles/t_r2_c5.png differ diff --git a/assets/verified-tiles/t_r2_c6.png b/assets/verified-tiles/t_r2_c6.png new file mode 100644 index 0000000..075ce61 Binary files /dev/null and b/assets/verified-tiles/t_r2_c6.png differ diff --git a/assets/verified-tiles/t_r2_c7.png b/assets/verified-tiles/t_r2_c7.png new file mode 100644 index 0000000..1885340 Binary files /dev/null and b/assets/verified-tiles/t_r2_c7.png differ diff --git a/assets/verified-tiles/t_r2_c8.png b/assets/verified-tiles/t_r2_c8.png new file mode 100644 index 0000000..3883203 Binary files /dev/null and b/assets/verified-tiles/t_r2_c8.png differ diff --git a/assets/verified-tiles/t_r2_c9.png b/assets/verified-tiles/t_r2_c9.png new file mode 100644 index 0000000..cf822e3 Binary files /dev/null and b/assets/verified-tiles/t_r2_c9.png differ diff --git a/assets/verified-tiles/t_r3_c0.png b/assets/verified-tiles/t_r3_c0.png new file mode 100644 index 0000000..71692a0 Binary files /dev/null and b/assets/verified-tiles/t_r3_c0.png differ diff --git a/assets/verified-tiles/t_r3_c1.png b/assets/verified-tiles/t_r3_c1.png new file mode 100644 index 0000000..0c9dc69 Binary files /dev/null and b/assets/verified-tiles/t_r3_c1.png differ diff --git a/assets/verified-tiles/t_r3_c10.png b/assets/verified-tiles/t_r3_c10.png new file mode 100644 index 0000000..81bdc4b Binary files /dev/null and b/assets/verified-tiles/t_r3_c10.png differ diff --git a/assets/verified-tiles/t_r3_c11.png b/assets/verified-tiles/t_r3_c11.png new file mode 100644 index 0000000..05383a5 Binary files /dev/null and b/assets/verified-tiles/t_r3_c11.png differ diff --git a/assets/verified-tiles/t_r3_c12.png b/assets/verified-tiles/t_r3_c12.png new file mode 100644 index 0000000..032de6f Binary files /dev/null and b/assets/verified-tiles/t_r3_c12.png differ diff --git a/assets/verified-tiles/t_r3_c13.png b/assets/verified-tiles/t_r3_c13.png new file mode 100644 index 0000000..afb4d3a Binary files /dev/null and b/assets/verified-tiles/t_r3_c13.png differ diff --git a/assets/verified-tiles/t_r3_c14.png b/assets/verified-tiles/t_r3_c14.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r3_c14.png differ diff --git a/assets/verified-tiles/t_r3_c15.png b/assets/verified-tiles/t_r3_c15.png new file mode 100644 index 0000000..4d63966 Binary files /dev/null and b/assets/verified-tiles/t_r3_c15.png differ diff --git a/assets/verified-tiles/t_r3_c2.png b/assets/verified-tiles/t_r3_c2.png new file mode 100644 index 0000000..0e1268c Binary files /dev/null and b/assets/verified-tiles/t_r3_c2.png differ diff --git a/assets/verified-tiles/t_r3_c3.png b/assets/verified-tiles/t_r3_c3.png new file mode 100644 index 0000000..afb4d3a Binary files /dev/null and b/assets/verified-tiles/t_r3_c3.png differ diff --git a/assets/verified-tiles/t_r3_c4.png b/assets/verified-tiles/t_r3_c4.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r3_c4.png differ diff --git a/assets/verified-tiles/t_r3_c5.png b/assets/verified-tiles/t_r3_c5.png new file mode 100644 index 0000000..87a4e84 Binary files /dev/null and b/assets/verified-tiles/t_r3_c5.png differ diff --git a/assets/verified-tiles/t_r3_c6.png b/assets/verified-tiles/t_r3_c6.png new file mode 100644 index 0000000..e60fdbf Binary files /dev/null and b/assets/verified-tiles/t_r3_c6.png differ diff --git a/assets/verified-tiles/t_r3_c7.png b/assets/verified-tiles/t_r3_c7.png new file mode 100644 index 0000000..988a564 Binary files /dev/null and b/assets/verified-tiles/t_r3_c7.png differ diff --git a/assets/verified-tiles/t_r3_c8.png b/assets/verified-tiles/t_r3_c8.png new file mode 100644 index 0000000..faa9beb Binary files /dev/null and b/assets/verified-tiles/t_r3_c8.png differ diff --git a/assets/verified-tiles/t_r3_c9.png b/assets/verified-tiles/t_r3_c9.png new file mode 100644 index 0000000..1b9ff8e Binary files /dev/null and b/assets/verified-tiles/t_r3_c9.png differ diff --git a/assets/verified-tiles/t_r4_c0.png b/assets/verified-tiles/t_r4_c0.png new file mode 100644 index 0000000..82228a9 Binary files /dev/null and b/assets/verified-tiles/t_r4_c0.png differ diff --git a/assets/verified-tiles/t_r4_c1.png b/assets/verified-tiles/t_r4_c1.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r4_c1.png differ diff --git a/assets/verified-tiles/t_r4_c10.png b/assets/verified-tiles/t_r4_c10.png new file mode 100644 index 0000000..82228a9 Binary files /dev/null and b/assets/verified-tiles/t_r4_c10.png differ diff --git a/assets/verified-tiles/t_r4_c11.png b/assets/verified-tiles/t_r4_c11.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r4_c11.png differ diff --git a/assets/verified-tiles/t_r4_c12.png b/assets/verified-tiles/t_r4_c12.png new file mode 100644 index 0000000..1f2b0da Binary files /dev/null and b/assets/verified-tiles/t_r4_c12.png differ diff --git a/assets/verified-tiles/t_r4_c13.png b/assets/verified-tiles/t_r4_c13.png new file mode 100644 index 0000000..0a33435 Binary files /dev/null and b/assets/verified-tiles/t_r4_c13.png differ diff --git a/assets/verified-tiles/t_r4_c14.png b/assets/verified-tiles/t_r4_c14.png new file mode 100644 index 0000000..ca16f28 Binary files /dev/null and b/assets/verified-tiles/t_r4_c14.png differ diff --git a/assets/verified-tiles/t_r4_c15.png b/assets/verified-tiles/t_r4_c15.png new file mode 100644 index 0000000..79a02c5 Binary files /dev/null and b/assets/verified-tiles/t_r4_c15.png differ diff --git a/assets/verified-tiles/t_r4_c2.png b/assets/verified-tiles/t_r4_c2.png new file mode 100644 index 0000000..1f2b0da Binary files /dev/null and b/assets/verified-tiles/t_r4_c2.png differ diff --git a/assets/verified-tiles/t_r4_c3.png b/assets/verified-tiles/t_r4_c3.png new file mode 100644 index 0000000..0993625 Binary files /dev/null and b/assets/verified-tiles/t_r4_c3.png differ diff --git a/assets/verified-tiles/t_r4_c4.png b/assets/verified-tiles/t_r4_c4.png new file mode 100644 index 0000000..d1122a4 Binary files /dev/null and b/assets/verified-tiles/t_r4_c4.png differ diff --git a/assets/verified-tiles/t_r4_c5.png b/assets/verified-tiles/t_r4_c5.png new file mode 100644 index 0000000..d14fa35 Binary files /dev/null and b/assets/verified-tiles/t_r4_c5.png differ diff --git a/assets/verified-tiles/t_r4_c6.png b/assets/verified-tiles/t_r4_c6.png new file mode 100644 index 0000000..d396513 Binary files /dev/null and b/assets/verified-tiles/t_r4_c6.png differ diff --git a/assets/verified-tiles/t_r4_c7.png b/assets/verified-tiles/t_r4_c7.png new file mode 100644 index 0000000..a36f749 Binary files /dev/null and b/assets/verified-tiles/t_r4_c7.png differ diff --git a/assets/verified-tiles/t_r4_c8.png b/assets/verified-tiles/t_r4_c8.png new file mode 100644 index 0000000..3883203 Binary files /dev/null and b/assets/verified-tiles/t_r4_c8.png differ diff --git a/assets/verified-tiles/t_r4_c9.png b/assets/verified-tiles/t_r4_c9.png new file mode 100644 index 0000000..09c2331 Binary files /dev/null and b/assets/verified-tiles/t_r4_c9.png differ diff --git a/assets/verified-tiles/t_r5_c0.png b/assets/verified-tiles/t_r5_c0.png new file mode 100644 index 0000000..45e7d14 Binary files /dev/null and b/assets/verified-tiles/t_r5_c0.png differ diff --git a/assets/verified-tiles/t_r5_c1.png b/assets/verified-tiles/t_r5_c1.png new file mode 100644 index 0000000..118ea6f Binary files /dev/null and b/assets/verified-tiles/t_r5_c1.png differ diff --git a/assets/verified-tiles/t_r5_c10.png b/assets/verified-tiles/t_r5_c10.png new file mode 100644 index 0000000..b3aa3dc Binary files /dev/null and b/assets/verified-tiles/t_r5_c10.png differ diff --git a/assets/verified-tiles/t_r5_c11.png b/assets/verified-tiles/t_r5_c11.png new file mode 100644 index 0000000..18fc4e6 Binary files /dev/null and b/assets/verified-tiles/t_r5_c11.png differ diff --git a/assets/verified-tiles/t_r5_c12.png b/assets/verified-tiles/t_r5_c12.png new file mode 100644 index 0000000..73fd9ee Binary files /dev/null and b/assets/verified-tiles/t_r5_c12.png differ diff --git a/assets/verified-tiles/t_r5_c13.png b/assets/verified-tiles/t_r5_c13.png new file mode 100644 index 0000000..b411df3 Binary files /dev/null and b/assets/verified-tiles/t_r5_c13.png differ diff --git a/assets/verified-tiles/t_r5_c14.png b/assets/verified-tiles/t_r5_c14.png new file mode 100644 index 0000000..f0f1235 Binary files /dev/null and b/assets/verified-tiles/t_r5_c14.png differ diff --git a/assets/verified-tiles/t_r5_c15.png b/assets/verified-tiles/t_r5_c15.png new file mode 100644 index 0000000..23d7b44 Binary files /dev/null and b/assets/verified-tiles/t_r5_c15.png differ diff --git a/assets/verified-tiles/t_r5_c2.png b/assets/verified-tiles/t_r5_c2.png new file mode 100644 index 0000000..a5625b8 Binary files /dev/null and b/assets/verified-tiles/t_r5_c2.png differ diff --git a/assets/verified-tiles/t_r5_c3.png b/assets/verified-tiles/t_r5_c3.png new file mode 100644 index 0000000..750a3e2 Binary files /dev/null and b/assets/verified-tiles/t_r5_c3.png differ diff --git a/assets/verified-tiles/t_r5_c4.png b/assets/verified-tiles/t_r5_c4.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r5_c4.png differ diff --git a/assets/verified-tiles/t_r5_c5.png b/assets/verified-tiles/t_r5_c5.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r5_c5.png differ diff --git a/assets/verified-tiles/t_r5_c6.png b/assets/verified-tiles/t_r5_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r5_c6.png differ diff --git a/assets/verified-tiles/t_r5_c7.png b/assets/verified-tiles/t_r5_c7.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r5_c7.png differ diff --git a/assets/verified-tiles/t_r5_c8.png b/assets/verified-tiles/t_r5_c8.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r5_c8.png differ diff --git a/assets/verified-tiles/t_r5_c9.png b/assets/verified-tiles/t_r5_c9.png new file mode 100644 index 0000000..7e391a3 Binary files /dev/null and b/assets/verified-tiles/t_r5_c9.png differ diff --git a/assets/verified-tiles/t_r6_c0.png b/assets/verified-tiles/t_r6_c0.png new file mode 100644 index 0000000..a4bbb06 Binary files /dev/null and b/assets/verified-tiles/t_r6_c0.png differ diff --git a/assets/verified-tiles/t_r6_c1.png b/assets/verified-tiles/t_r6_c1.png new file mode 100644 index 0000000..89fe965 Binary files /dev/null and b/assets/verified-tiles/t_r6_c1.png differ diff --git a/assets/verified-tiles/t_r6_c10.png b/assets/verified-tiles/t_r6_c10.png new file mode 100644 index 0000000..4c86eca Binary files /dev/null and b/assets/verified-tiles/t_r6_c10.png differ diff --git a/assets/verified-tiles/t_r6_c11.png b/assets/verified-tiles/t_r6_c11.png new file mode 100644 index 0000000..5c1ddcb Binary files /dev/null and b/assets/verified-tiles/t_r6_c11.png differ diff --git a/assets/verified-tiles/t_r6_c12.png b/assets/verified-tiles/t_r6_c12.png new file mode 100644 index 0000000..a25d44b Binary files /dev/null and b/assets/verified-tiles/t_r6_c12.png differ diff --git a/assets/verified-tiles/t_r6_c13.png b/assets/verified-tiles/t_r6_c13.png new file mode 100644 index 0000000..b26457b Binary files /dev/null and b/assets/verified-tiles/t_r6_c13.png differ diff --git a/assets/verified-tiles/t_r6_c14.png b/assets/verified-tiles/t_r6_c14.png new file mode 100644 index 0000000..c17d0cd Binary files /dev/null and b/assets/verified-tiles/t_r6_c14.png differ diff --git a/assets/verified-tiles/t_r6_c15.png b/assets/verified-tiles/t_r6_c15.png new file mode 100644 index 0000000..9a40363 Binary files /dev/null and b/assets/verified-tiles/t_r6_c15.png differ diff --git a/assets/verified-tiles/t_r6_c2.png b/assets/verified-tiles/t_r6_c2.png new file mode 100644 index 0000000..06e87e1 Binary files /dev/null and b/assets/verified-tiles/t_r6_c2.png differ diff --git a/assets/verified-tiles/t_r6_c3.png b/assets/verified-tiles/t_r6_c3.png new file mode 100644 index 0000000..b80d8b1 Binary files /dev/null and b/assets/verified-tiles/t_r6_c3.png differ diff --git a/assets/verified-tiles/t_r6_c4.png b/assets/verified-tiles/t_r6_c4.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r6_c4.png differ diff --git a/assets/verified-tiles/t_r6_c5.png b/assets/verified-tiles/t_r6_c5.png new file mode 100644 index 0000000..ed17b77 Binary files /dev/null and b/assets/verified-tiles/t_r6_c5.png differ diff --git a/assets/verified-tiles/t_r6_c6.png b/assets/verified-tiles/t_r6_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r6_c6.png differ diff --git a/assets/verified-tiles/t_r6_c7.png b/assets/verified-tiles/t_r6_c7.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r6_c7.png differ diff --git a/assets/verified-tiles/t_r6_c8.png b/assets/verified-tiles/t_r6_c8.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r6_c8.png differ diff --git a/assets/verified-tiles/t_r6_c9.png b/assets/verified-tiles/t_r6_c9.png new file mode 100644 index 0000000..aedd46f Binary files /dev/null and b/assets/verified-tiles/t_r6_c9.png differ diff --git a/assets/verified-tiles/t_r7_c0.png b/assets/verified-tiles/t_r7_c0.png new file mode 100644 index 0000000..82619ec Binary files /dev/null and b/assets/verified-tiles/t_r7_c0.png differ diff --git a/assets/verified-tiles/t_r7_c1.png b/assets/verified-tiles/t_r7_c1.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r7_c1.png differ diff --git a/assets/verified-tiles/t_r7_c10.png b/assets/verified-tiles/t_r7_c10.png new file mode 100644 index 0000000..a26ec5c Binary files /dev/null and b/assets/verified-tiles/t_r7_c10.png differ diff --git a/assets/verified-tiles/t_r7_c11.png b/assets/verified-tiles/t_r7_c11.png new file mode 100644 index 0000000..5dbcd52 Binary files /dev/null and b/assets/verified-tiles/t_r7_c11.png differ diff --git a/assets/verified-tiles/t_r7_c12.png b/assets/verified-tiles/t_r7_c12.png new file mode 100644 index 0000000..f80081d Binary files /dev/null and b/assets/verified-tiles/t_r7_c12.png differ diff --git a/assets/verified-tiles/t_r7_c13.png b/assets/verified-tiles/t_r7_c13.png new file mode 100644 index 0000000..2628dd6 Binary files /dev/null and b/assets/verified-tiles/t_r7_c13.png differ diff --git a/assets/verified-tiles/t_r7_c14.png b/assets/verified-tiles/t_r7_c14.png new file mode 100644 index 0000000..757a7b5 Binary files /dev/null and b/assets/verified-tiles/t_r7_c14.png differ diff --git a/assets/verified-tiles/t_r7_c15.png b/assets/verified-tiles/t_r7_c15.png new file mode 100644 index 0000000..61b241f Binary files /dev/null and b/assets/verified-tiles/t_r7_c15.png differ diff --git a/assets/verified-tiles/t_r7_c2.png b/assets/verified-tiles/t_r7_c2.png new file mode 100644 index 0000000..716ede1 Binary files /dev/null and b/assets/verified-tiles/t_r7_c2.png differ diff --git a/assets/verified-tiles/t_r7_c3.png b/assets/verified-tiles/t_r7_c3.png new file mode 100644 index 0000000..82619ec Binary files /dev/null and b/assets/verified-tiles/t_r7_c3.png differ diff --git a/assets/verified-tiles/t_r7_c4.png b/assets/verified-tiles/t_r7_c4.png new file mode 100644 index 0000000..f109037 Binary files /dev/null and b/assets/verified-tiles/t_r7_c4.png differ diff --git a/assets/verified-tiles/t_r7_c5.png b/assets/verified-tiles/t_r7_c5.png new file mode 100644 index 0000000..b2f6d78 Binary files /dev/null and b/assets/verified-tiles/t_r7_c5.png differ diff --git a/assets/verified-tiles/t_r7_c6.png b/assets/verified-tiles/t_r7_c6.png new file mode 100644 index 0000000..4cf0717 Binary files /dev/null and b/assets/verified-tiles/t_r7_c6.png differ diff --git a/assets/verified-tiles/t_r7_c7.png b/assets/verified-tiles/t_r7_c7.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r7_c7.png differ diff --git a/assets/verified-tiles/t_r7_c8.png b/assets/verified-tiles/t_r7_c8.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r7_c8.png differ diff --git a/assets/verified-tiles/t_r7_c9.png b/assets/verified-tiles/t_r7_c9.png new file mode 100644 index 0000000..08b649f Binary files /dev/null and b/assets/verified-tiles/t_r7_c9.png differ diff --git a/assets/verified-tiles/t_r8_c0.png b/assets/verified-tiles/t_r8_c0.png new file mode 100644 index 0000000..6d3f88a Binary files /dev/null and b/assets/verified-tiles/t_r8_c0.png differ diff --git a/assets/verified-tiles/t_r8_c1.png b/assets/verified-tiles/t_r8_c1.png new file mode 100644 index 0000000..9dbe5da Binary files /dev/null and b/assets/verified-tiles/t_r8_c1.png differ diff --git a/assets/verified-tiles/t_r8_c10.png b/assets/verified-tiles/t_r8_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r8_c10.png differ diff --git a/assets/verified-tiles/t_r8_c11.png b/assets/verified-tiles/t_r8_c11.png new file mode 100644 index 0000000..980aae5 Binary files /dev/null and b/assets/verified-tiles/t_r8_c11.png differ diff --git a/assets/verified-tiles/t_r8_c12.png b/assets/verified-tiles/t_r8_c12.png new file mode 100644 index 0000000..5bb6fb3 Binary files /dev/null and b/assets/verified-tiles/t_r8_c12.png differ diff --git a/assets/verified-tiles/t_r8_c13.png b/assets/verified-tiles/t_r8_c13.png new file mode 100644 index 0000000..ed16131 Binary files /dev/null and b/assets/verified-tiles/t_r8_c13.png differ diff --git a/assets/verified-tiles/t_r8_c14.png b/assets/verified-tiles/t_r8_c14.png new file mode 100644 index 0000000..640d47a Binary files /dev/null and b/assets/verified-tiles/t_r8_c14.png differ diff --git a/assets/verified-tiles/t_r8_c15.png b/assets/verified-tiles/t_r8_c15.png new file mode 100644 index 0000000..2b59799 Binary files /dev/null and b/assets/verified-tiles/t_r8_c15.png differ diff --git a/assets/verified-tiles/t_r8_c2.png b/assets/verified-tiles/t_r8_c2.png new file mode 100644 index 0000000..0d7b43b Binary files /dev/null and b/assets/verified-tiles/t_r8_c2.png differ diff --git a/assets/verified-tiles/t_r8_c3.png b/assets/verified-tiles/t_r8_c3.png new file mode 100644 index 0000000..afb4d3a Binary files /dev/null and b/assets/verified-tiles/t_r8_c3.png differ diff --git a/assets/verified-tiles/t_r8_c4.png b/assets/verified-tiles/t_r8_c4.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r8_c4.png differ diff --git a/assets/verified-tiles/t_r8_c5.png b/assets/verified-tiles/t_r8_c5.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r8_c5.png differ diff --git a/assets/verified-tiles/t_r8_c6.png b/assets/verified-tiles/t_r8_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r8_c6.png differ diff --git a/assets/verified-tiles/t_r8_c7.png b/assets/verified-tiles/t_r8_c7.png new file mode 100644 index 0000000..0f9e474 Binary files /dev/null and b/assets/verified-tiles/t_r8_c7.png differ diff --git a/assets/verified-tiles/t_r8_c8.png b/assets/verified-tiles/t_r8_c8.png new file mode 100644 index 0000000..5731c47 Binary files /dev/null and b/assets/verified-tiles/t_r8_c8.png differ diff --git a/assets/verified-tiles/t_r8_c9.png b/assets/verified-tiles/t_r8_c9.png new file mode 100644 index 0000000..da6cc80 Binary files /dev/null and b/assets/verified-tiles/t_r8_c9.png differ diff --git a/assets/verified-tiles/t_r9_c0.png b/assets/verified-tiles/t_r9_c0.png new file mode 100644 index 0000000..82228a9 Binary files /dev/null and b/assets/verified-tiles/t_r9_c0.png differ diff --git a/assets/verified-tiles/t_r9_c1.png b/assets/verified-tiles/t_r9_c1.png new file mode 100644 index 0000000..6979036 Binary files /dev/null and b/assets/verified-tiles/t_r9_c1.png differ diff --git a/assets/verified-tiles/t_r9_c10.png b/assets/verified-tiles/t_r9_c10.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c10.png differ diff --git a/assets/verified-tiles/t_r9_c11.png b/assets/verified-tiles/t_r9_c11.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c11.png differ diff --git a/assets/verified-tiles/t_r9_c12.png b/assets/verified-tiles/t_r9_c12.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c12.png differ diff --git a/assets/verified-tiles/t_r9_c13.png b/assets/verified-tiles/t_r9_c13.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c13.png differ diff --git a/assets/verified-tiles/t_r9_c14.png b/assets/verified-tiles/t_r9_c14.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c14.png differ diff --git a/assets/verified-tiles/t_r9_c15.png b/assets/verified-tiles/t_r9_c15.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c15.png differ diff --git a/assets/verified-tiles/t_r9_c2.png b/assets/verified-tiles/t_r9_c2.png new file mode 100644 index 0000000..1f2b0da Binary files /dev/null and b/assets/verified-tiles/t_r9_c2.png differ diff --git a/assets/verified-tiles/t_r9_c3.png b/assets/verified-tiles/t_r9_c3.png new file mode 100644 index 0000000..40e30b1 Binary files /dev/null and b/assets/verified-tiles/t_r9_c3.png differ diff --git a/assets/verified-tiles/t_r9_c4.png b/assets/verified-tiles/t_r9_c4.png new file mode 100644 index 0000000..765c9c9 Binary files /dev/null and b/assets/verified-tiles/t_r9_c4.png differ diff --git a/assets/verified-tiles/t_r9_c5.png b/assets/verified-tiles/t_r9_c5.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c5.png differ diff --git a/assets/verified-tiles/t_r9_c6.png b/assets/verified-tiles/t_r9_c6.png new file mode 100644 index 0000000..9d79540 Binary files /dev/null and b/assets/verified-tiles/t_r9_c6.png differ diff --git a/assets/verified-tiles/t_r9_c7.png b/assets/verified-tiles/t_r9_c7.png new file mode 100644 index 0000000..8db3381 Binary files /dev/null and b/assets/verified-tiles/t_r9_c7.png differ diff --git a/assets/verified-tiles/t_r9_c8.png b/assets/verified-tiles/t_r9_c8.png new file mode 100644 index 0000000..dfcf112 Binary files /dev/null and b/assets/verified-tiles/t_r9_c8.png differ diff --git a/assets/verified-tiles/t_r9_c9.png b/assets/verified-tiles/t_r9_c9.png new file mode 100644 index 0000000..98250aa Binary files /dev/null and b/assets/verified-tiles/t_r9_c9.png differ diff --git a/src/frontend/FarmCanvas.jsx b/src/frontend/FarmCanvas.jsx index 9b69670..9ff644b 100644 --- a/src/frontend/FarmCanvas.jsx +++ b/src/frontend/FarmCanvas.jsx @@ -1,543 +1,346 @@ -import React, { useRef, useEffect, useState, useCallback } from 'react'; -import useStore from './store.js'; -import { OFFICE_MAP, WALLS, DOORWAYS, FURNITURE, TILE_SIZE, MAP_COLS, MAP_ROWS } from './officeMap.js'; +// FarmCanvas.jsx — Clean Canvas 2D renderer for the Virtual Office +// Draws rooms with colored floors/walls, simple furniture, and agent sprites. +// No tile-sheet dependencies. Pure Canvas drawing. -const CANVAS_W = MAP_COLS * TILE_SIZE; // 640 -const CANVAS_H = MAP_ROWS * TILE_SIZE; // 480 +import { useEffect, useRef, useCallback } from 'react'; +import { useStore } from './store'; +import { TILE, COLS, ROWS, rooms, agentDesks, hallwayTiles, furniture } from './officeMap'; -const LERP_SPEED = 0.15; +const SCALE = 2.5; // render pixels per tile pixel +const SPRITE_SCALE = 2.5; -// ── Sprite loader ──────────────────────────────────────────────── -function loadSprite(id) { - const img = new Image(); - img.src = `/office/sprites/agent-${id}.png`; - return img; -} +// Agent sprite image cache +const spriteImages = {}; +let spritesLoaded = 0; +let spritesTotal = 0; -const AGENT_IDS = ['cos', 'engineering', 'senior-eng', 'trust', 'market', 'health', 'content', 'presentations', 'vault']; - -// Preload all sprites -const sprites = {}; -AGENT_IDS.forEach(id => { sprites[id] = loadSprite(id); }); - -// ── Tileset loader ──────────────────────────────────────────────── -let tilesetImg = null; -function loadTileset() { - if (!tilesetImg) { - tilesetImg = new Image(); - tilesetImg.src = '/office/tiles/tileset.png'; - } - return tilesetImg; -} - -let roomBuilderImg = null; -function loadRoomBuilder() { - if (!roomBuilderImg) { - roomBuilderImg = new Image(); - roomBuilderImg.src = '/office/tiles/room-builder.png'; - } - return roomBuilderImg; -} - -// ── Particle system for sparkles ───────────────────────────────── -let sparkles = []; - -function spawnSparkle(x, y) { - sparkles.push({ - x, y, - vx: (Math.random() - 0.5) * 2, - vy: -Math.random() * 3 - 1, - life: 1, - decay: 0.02 + Math.random() * 0.03, - color: ['#F0C040', '#FFD700', '#FFEAA7', '#FFFFFF'][Math.floor(Math.random() * 4)], +function loadSprites() { + const agents = ['cos','engineering','senior-eng','trust','market','health','content','presentations','vault']; + spritesTotal = agents.length; + spritesLoaded = 0; + agents.forEach(id => { + const img = new Image(); + img.src = `/office/sprites/agent-${id}.png`; + img.onload = () => { spritesLoaded++; }; + img.onerror = () => { console.warn('Failed to load sprite:', id); spritesLoaded++; }; + spriteImages[id] = img; }); - if (sparkles.length > 60) sparkles.shift(); } -// ── Tile drawing helpers ────────────────────────────────────────── +loadSprites(); -// Draw a single tile from tileset.png (16-wide grid) -function drawTileFromTileset(ctx, tileId, dx, dy) { - if (tileId < 0 || tileId === undefined) return; - const img = loadTileset(); - if (!img || !img.complete) return; - const sx = (tileId % 16) * TILE_SIZE; - const sy = Math.floor(tileId / 16) * TILE_SIZE; - ctx.drawImage(img, sx, sy, TILE_SIZE, TILE_SIZE, dx, dy, TILE_SIZE, TILE_SIZE); -} +// Draw a rounded rect room +function drawRoom(ctx, room, ox, oy) { + const x = room.x * TILE * SCALE + ox; + const y = room.y * TILE * SCALE + oy; + const w = room.w * TILE * SCALE; + const h = room.h * TILE * SCALE; + const r = 6; -// Draw a single tile from room-builder.png (17-wide grid) -function drawTileFromRoomBuilder(ctx, tileId, dx, dy) { - if (tileId < 0 || tileId === undefined) return; - const img = loadRoomBuilder(); - if (!img || !img.complete) return; - const RB_COLS = 17; - const sx = (tileId % RB_COLS) * TILE_SIZE; - const sy = Math.floor(tileId / RB_COLS) * TILE_SIZE; - ctx.drawImage(img, sx, sy, TILE_SIZE, TILE_SIZE, dx, dy, TILE_SIZE, TILE_SIZE); -} - -// ── Layer 1: Background / outdoors ──────────────────────────────── -function drawBackground(ctx) { - // Dark exterior (outside the office) - ctx.fillStyle = '#1a1a2e'; - ctx.fillRect(0, 0, CANVAS_W, CANVAS_H); - - // Grass/texture around building (top strip) - ctx.fillStyle = '#2D5A27'; - ctx.fillRect(0, 0, CANVAS_W, 3 * TILE_SIZE); - - // Add some texture to the grass - for (let i = 0; i < 300; i++) { - const x = Math.random() * CANVAS_W; - const y = Math.random() * 3 * TILE_SIZE; - ctx.fillStyle = `rgb(${40 + Math.random() * 30},${70 + Math.random() * 40},${30 + Math.random() * 20})`; - ctx.fillRect(x, y, 2, 2); - } -} - -// ── Layer 2: Floor tiles ────────────────────────────────────────── -function drawFloorLayer(ctx) { - const img = loadTileset(); - if (!img || !img.complete) { - // Fallback: draw solid colors - const colors = { - 16: '#C4A882', 22: '#8BA87E', 83: '#9B9B9B', 67: '#B8956E', - 38: '#4A5070', 54: '#7A7A85', 70: '#A89B8A', - }; - for (let row = 0; row < MAP_ROWS; row++) { - for (let col = 0; col < MAP_COLS; col++) { - const tileId = OFFICE_MAP[row]?.[col]; - if (tileId && tileId > 0) { - ctx.fillStyle = colors[tileId] || '#555'; - ctx.fillRect(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); - } - } - } - return; - } - - for (let row = 0; row < MAP_ROWS; row++) { - for (let col = 0; col < MAP_COLS; col++) { - const tileId = OFFICE_MAP[row]?.[col]; - if (tileId && tileId > 0) { - drawTileFromTileset(ctx, tileId, col * TILE_SIZE, row * TILE_SIZE); - } - } - } -} - -// ── Layer 3: Walls ──────────────────────────────────────────────── -function drawWallLayer(ctx) { - const img = loadTileset(); - const drawn = new Set(); - - for (const wall of WALLS) { - const key = `${wall.row},${wall.col}`; - if (drawn.has(key)) continue; - drawn.add(key); - - const dx = wall.col * TILE_SIZE; - const dy = wall.row * TILE_SIZE; - - if (img && img.complete) { - drawTileFromTileset(ctx, wall.tile, dx, dy); - } else { - // Fallback wall rendering - ctx.fillStyle = '#6B5B4F'; - ctx.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); - ctx.strokeStyle = '#5A4A3E'; - ctx.lineWidth = 1; - ctx.strokeRect(dx + 1, dy + 1, TILE_SIZE - 2, TILE_SIZE - 2); - } - } -} - -// ── Layer 3.5: Doorways ─────────────────────────────────────────── -function drawDoorways(ctx) { - const img = loadTileset(); - for (const door of DOORWAYS) { - const dx = door.col * TILE_SIZE; - const dy = door.row * TILE_SIZE; - if (img && img.complete) { - drawTileFromTileset(ctx, door.tile, dx, dy); - } else { - // Fallback doorway - ctx.fillStyle = '#4A3520'; - ctx.fillRect(dx, dy, TILE_SIZE, TILE_SIZE); - ctx.fillStyle = '#DAA520'; - ctx.fillRect(dx + TILE_SIZE - 5, dy + TILE_SIZE / 2 - 1, 4, 4); - } - } -} - -// ── Layer 4: Furniture ──────────────────────────────────────────── -function drawFurniture(ctx) { - const img = loadTileset(); - for (const furn of FURNITURE) { - const dx = furn.col * TILE_SIZE; - const dy = furn.row * TILE_SIZE; - if (img && img.complete) { - drawTileFromTileset(ctx, furn.tile, dx, dy); - } else { - // Fallback colored furniture - const fColors = { - 528: '#8B6914', 936: '#4A3728', 736: '#6B4226', 584: '#2D8B2D', - 674: '#DAA520', 1012: '#555', 672: '#8B7355', 996: '#222', - 1010: '#444', 889: '#FFD700', 709: '#EEE', - }; - ctx.fillStyle = fColors[furn.tile] || '#666'; - ctx.fillRect(dx + 2, dy + 2, TILE_SIZE - 4, TILE_SIZE - 4); - } - } -} - -// ── Room labels ─────────────────────────────────────────────────── -function drawRoomLabels(ctx) { - const rooms = [ - { label: 'Briefing Room', col: 0, row: 3, w: 6 }, - { label: 'Commons', col: 6, row: 3, w: 8 }, - { label: 'War Room', col: 14, row: 3, w: 6 }, - { label: 'Engineering Bay', col: 0, row: 9, w: 6 }, - { label: 'Quiet Zone', col: 6, row: 9, w: 8 }, - { label: 'Ops Center', col: 14, row: 9, w: 6 }, - ]; - - for (const room of rooms) { - const cx = room.col * TILE_SIZE + (room.w * TILE_SIZE) / 2; - const topY = room.row * TILE_SIZE; - const labelW = ctx.measureText(room.label).width + 10; - const labelH = 12; - - // Semi-transparent pill behind text - ctx.fillStyle = 'rgba(0,0,0,0.5)'; - ctx.beginPath(); - ctx.roundRect(cx - labelW / 2, topY + 2, labelW, labelH, 3); - ctx.fill(); - - ctx.font = 'bold 8px "Courier New", monospace'; - ctx.textAlign = 'center'; - ctx.fillStyle = '#DDD'; - ctx.fillText(room.label, cx, topY + 11); - } - ctx.textAlign = 'start'; - - // Hallway label - const hx = MAP_COLS * TILE_SIZE / 2; - ctx.fillStyle = 'rgba(0,0,0,0.4)'; - const hlW = ctx.measureText('Hallway').width + 10; + // Floor + ctx.fillStyle = room.floor; ctx.beginPath(); - ctx.roundRect(hx - hlW / 2, 7 * TILE_SIZE + 6, hlW, 12, 3); + ctx.roundRect(x, y, w, h, r); ctx.fill(); - ctx.font = 'bold 8px "Courier New", monospace'; - ctx.textAlign = 'center'; - ctx.fillStyle = '#CCC'; - ctx.fillText('Hallway', hx, 7 * TILE_SIZE + 15); - ctx.textAlign = 'start'; -} - -// ── Layer 5: Agents ─────────────────────────────────────────────── -function drawAgent(ctx, agent, time) { - if (!agent || !agent.position) return; - - const img = sprites[agent.id]; - if (!img) return; - - const target = agent.targetPosition || agent.position; - const current = agent._smoothPos || { row: target.row, col: target.col }; - - // Lerp toward target - current.row += (target.row - current.row) * LERP_SPEED; - current.col += (target.col - current.col) * LERP_SPEED; - - // If very close, snap - if (Math.abs(target.row - current.row) < 0.01) current.row = target.row; - if (Math.abs(target.col - current.col) < 0.01) current.col = target.col; - - agent._smoothPos = current; - - const activity = agent.activity || 'idle'; - const px = current.col * TILE_SIZE + TILE_SIZE / 2; - const py = current.row * TILE_SIZE + TILE_SIZE / 2; - - // Vertical bob for idle - let yOffset = 0; - if (activity === 'idle') { - yOffset = Math.sin(time * 0.003 + (agent.id?.charCodeAt(0) || 0)) * 2; - } + // Floor grain pattern (subtle diagonal lines for warmth) ctx.save(); - ctx.globalAlpha = 0.95; - ctx.translate(px, py + yOffset); - - // Activity states - if (activity === 'offline') { - ctx.globalAlpha = 0.5; - ctx.filter = 'grayscale(100%)'; + ctx.beginPath(); + ctx.roundRect(x, y, w, h, r); + ctx.clip(); + ctx.strokeStyle = room.accent + '30'; // 30 = ~19% opacity + ctx.lineWidth = 1; + for (let i = -h; i < w + h; i += 12) { + ctx.beginPath(); + ctx.moveTo(x + i, y); + ctx.lineTo(x + i + h, y + h); + ctx.stroke(); } - - // Draw sprite centered - const sx = img.width > 32 ? 0 : 0; - const spriteW = img.width > 32 ? Math.min(32, img.width) : img.width; - const spriteH = img.height; - ctx.drawImage(img, sx, 0, spriteW, spriteH, -16, -16, 32, 32); - ctx.restore(); - // Blocked: red tint overlay - if (activity === 'blocked') { - ctx.fillStyle = 'rgba(255,50,50,0.3)'; - ctx.fillRect(px - 16, py + yOffset - 16, 32, 32); - ctx.font = 'bold 12px "Courier New", monospace'; - ctx.fillStyle = '#FF4444'; - ctx.textAlign = 'center'; - ctx.fillText('!', px, py + yOffset - 24); + // Wall border + ctx.strokeStyle = room.wall; + ctx.lineWidth = 3; + ctx.beginPath(); + ctx.roundRect(x, y, w, h, r); + ctx.stroke(); + + // Doorways — gaps in the bottom wall + const doorWidth = TILE * SCALE; + ctx.fillStyle = '#8a7a6a'; // doorframe color + // Left door + ctx.fillRect(x + 1 * TILE * SCALE - doorWidth/2, y + h - 3, doorWidth, 6); + // Right door + if (room.w >= 5) { + ctx.fillRect(x + (room.w - 2) * TILE * SCALE - doorWidth/2, y + h - 3, doorWidth, 6); } - // Agent name below (centered with shadow) - ctx.font = '9px "Courier New", monospace'; + // Room name label — small, above room + ctx.fillStyle = room.wall; + ctx.font = `bold ${Math.round(11 * SCALE / 2.5)}px 'EB Garamond', serif`; ctx.textAlign = 'center'; - ctx.fillStyle = '#000'; - ctx.fillText(agent.name || agent.id, px + 1, py + yOffset + 27); - ctx.fillStyle = '#FFF'; - ctx.fillText(agent.name || agent.id, px, py + yOffset + 26); + ctx.textBaseline = 'bottom'; + ctx.fillText(room.name, x + w / 2, y - 4); +} - // Thinking bubble - if (activity === 'thinking') { - ctx.font = 'bold 10px "Courier New", monospace'; - ctx.textAlign = 'center'; - const bubbleW = 24; - const bubbleH = 14; - const bx = px - bubbleW / 2; - const by = py + yOffset - 44; +// Draw simple furniture shapes +function drawFurniture(ctx, room, ox, oy) { + const items = furniture[room.id] || []; + items.forEach(item => { + const x = (room.x + item.rx) * TILE * SCALE + ox; + const y = (room.y + item.ry) * TILE * SCALE + oy; + const w = (item.w || 1) * TILE * SCALE; + const h = (item.h || 1) * TILE * SCALE; - ctx.fillStyle = '#FFF'; - ctx.beginPath(); - ctx.roundRect(bx, by, bubbleW, bubbleH, 3); - ctx.fill(); - ctx.strokeStyle = '#CCC'; - ctx.lineWidth = 1; - ctx.stroke(); - ctx.fillStyle = '#333'; - ctx.fillText('...', px, py + yOffset - 33); - } - - // Sparkles for working - if (activity === 'working') { - if (Math.random() < 0.3) { - spawnSparkle(px + (Math.random() - 0.5) * 24, py + yOffset - 12); + ctx.save(); + switch (item.type) { + case 'table': + ctx.fillStyle = room.accent; + ctx.beginPath(); + ctx.roundRect(x + 2, y + 2, w - 4, h - 4, 3); + ctx.fill(); + ctx.strokeStyle = room.wall + '60'; + ctx.lineWidth = 1; + ctx.stroke(); + break; + case 'desk': + ctx.fillStyle = room.accent; + ctx.fillRect(x + 2, y + 4, w - 4, h - 8); + ctx.strokeStyle = room.wall + '80'; + ctx.lineWidth = 1; + ctx.strokeRect(x + 2, y + 4, w - 4, h - 8); + break; + case 'chair': + ctx.fillStyle = room.wall; + ctx.fillRect(x + 8, y + 8, TILE * SCALE - 16, TILE * SCALE - 16); + break; + case 'monitor': + ctx.fillStyle = '#1a1a2e'; + ctx.fillRect(x + 10, y + 6, TILE * SCALE - 20, TILE * SCALE * 0.5); + ctx.fillStyle = '#4a9eff'; + ctx.fillRect(x + 12, y + 8, TILE * SCALE - 24, TILE * SCALE * 0.5 - 6); + break; + case 'sofa': + ctx.fillStyle = room.accent + 'cc'; + ctx.beginPath(); + ctx.roundRect(x + 2, y + 2, w - 4, h - 4, 4); + ctx.fill(); + ctx.strokeStyle = room.wall; + ctx.lineWidth = 1; + ctx.stroke(); + break; + case 'shelf': + case 'bookcase': + ctx.fillStyle = room.wall; + ctx.fillRect(x + 2, y + 2, w - 4, h - 4); + // Book spines + for (let b = 0; b < Math.min(w / 6, 8); b++) { + ctx.fillStyle = ['#c44','#4a4','#44a','#a4a','#ca4'][b % 5]; + ctx.fillRect(x + 4 + b * 6, y + 4, 4, h - 8); + } + break; + case 'plant': + ctx.fillStyle = '#2a6a2a'; + ctx.beginPath(); + ctx.arc(x + TILE * SCALE / 2, y + TILE * SCALE / 2, TILE * SCALE / 3, 0, Math.PI * 2); + ctx.fill(); + ctx.fillStyle = '#5a3a1a'; + ctx.fillRect(x + TILE * SCALE / 2 - 4, y + TILE * SCALE / 2 + 4, 8, 8); + break; + case 'lamp': + ctx.fillStyle = '#ffd700'; + ctx.beginPath(); + ctx.arc(x + TILE * SCALE / 2, y + TILE * SCALE / 2, 6, 0, Math.PI * 2); + ctx.fill(); + // Glow + const grad = ctx.createRadialGradient( + x + TILE * SCALE / 2, y + TILE * SCALE / 2, 2, + x + TILE * SCALE / 2, y + TILE * SCALE / 2, 20 + ); + grad.addColorStop(0, 'rgba(255,215,0,0.3)'); + grad.addColorStop(1, 'rgba(255,215,0,0)'); + ctx.fillStyle = grad; + ctx.beginPath(); + ctx.arc(x + TILE * SCALE / 2, y + TILE * SCALE / 2, 20, 0, Math.PI * 2); + ctx.fill(); + break; + case 'screen': + ctx.fillStyle = '#2a2a3e'; + ctx.fillRect(x + 2, y + 2, w - 4, h - 4); + ctx.fillStyle = '#3a5aff'; + ctx.fillRect(x + 4, y + 4, w - 8, h - 8); + break; } - } - - ctx.textAlign = 'start'; + ctx.restore(); + }); } -function drawParticles(ctx) { - sparkles = sparkles.filter(s => s.life > 0); - for (const s of sparkles) { - s.x += s.vx; - s.y += s.vy; - s.life -= s.decay; - const alpha = Math.max(0, s.life); - ctx.fillStyle = s.color; - ctx.globalAlpha = alpha; - ctx.fillRect(s.x, s.y, 2, 2); - } - ctx.globalAlpha = 1; +// Draw hallway +function drawHallway(ctx, ox, oy) { + const hw = COLS * TILE * SCALE; + const hh = ROWS * TILE * SCALE; + + // Background + ctx.fillStyle = '#1a1a28'; + ctx.fillRect(ox, oy, hw, hh); + + // Hallway tiles + hallwayTiles.forEach(({ x, y }) => { + const px = x * TILE * SCALE + ox; + const py = y * TILE * SCALE + oy; + ctx.fillStyle = '#2a2a3e'; + ctx.fillRect(px, py, TILE * SCALE, TILE * SCALE); + // Subtle grid + ctx.strokeStyle = '#3a3a4e'; + ctx.lineWidth = 0.5; + ctx.strokeRect(px, py, TILE * SCALE, TILE * SCALE); + }); } -// ── Component ───────────────────────────────────────────────────── -export default function FarmCanvas({ onAgentClick, onAgentHover }) { +// Draw an agent +function drawAgent(ctx, agent, ox, oy) { + const img = spriteImages[agent.id]; + if (!img || !img.complete || img.naturalWidth === 0) return; + + const sx = agent.x * TILE * SCALE + ox; + const sy = agent.y * TILE * SCALE + oy; + const spriteSize = 32 * SPRITE_SCALE; + + // Center sprite on tile + const dx = sx + (TILE * SCALE - spriteSize) / 2; + const dy = sy + (TILE * SCALE - spriteSize) / 2 - 4; // slight lift + + // Shadow + ctx.fillStyle = 'rgba(0,0,0,0.2)'; + ctx.beginPath(); + ctx.ellipse(dx + spriteSize / 2, dy + spriteSize + 2, spriteSize / 3, 4, 0, 0, Math.PI * 2); + ctx.fill(); + + // Sprite + ctx.imageSmoothingEnabled = false; + ctx.drawImage(img, dx, dy, spriteSize, spriteSize); + + // Activity indicator dot + const statusColors = { + active: '#4aff4a', + idle: '#888', + error: '#ff4444', + offline: '#555', + }; + const color = statusColors[agent.status] || statusColors.idle; + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(dx + spriteSize - 4, dy + 4, 4, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = '#000'; + ctx.lineWidth = 1; + ctx.stroke(); +} + +export default function FarmCanvas() { const canvasRef = useRef(null); - const animRef = useRef(null); const agents = useStore(s => s.agents); - const agentList = React.useMemo(() => Object.values(agents), [agents]); + const hoveredAgent = useStore(s => s.hoveredAgent); + const setHoveredAgent = useStore(s => s.setHoveredAgent); + const selectAgent = useStore(s => s.selectAgent); + const containerRef = useRef(null); - // Hover state - const [hoveredAgent, setHoveredAgent] = useState(null); - const hoveredRef = useRef(null); + const canvasWidth = COLS * TILE * SCALE; + const canvasHeight = ROWS * TILE * SCALE; - // Detect agent under mouse - const getAgentAtPoint = useCallback((mx, my) => { - for (const agent of [...agentList].reverse()) { - const pos = agent._smoothPos || agent.position; - if (!pos) continue; - const px = pos.col * TILE_SIZE + TILE_SIZE / 2; - const py = pos.row * TILE_SIZE + TILE_SIZE / 2; - if (Math.abs(mx - px) < 20 && Math.abs(my - py) < 20) { - return agent; + const render = useCallback(() => { + const canvas = canvasRef.current; + if (!canvas) return; + const ctx = canvas.getContext('2d'); + + // Clear + ctx.clearRect(0, 0, canvasWidth, canvasHeight); + + // Background + ctx.fillStyle = '#1a1a28'; + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + + // Draw hallways + drawHallway(ctx, 0, 0); + + // Draw rooms + rooms.forEach(room => { + drawRoom(ctx, room, 0, 0); + drawFurniture(ctx, room, 0, 0); + }); + + // Draw agents (sorted so hovered agent renders on top) + const sortedAgents = [...agents].sort((a, b) => { + if (a.id === hoveredAgent) return 1; + if (b.id === hoveredAgent) return -1; + return 0; + }); + sortedAgents.forEach(agent => drawAgent(ctx, agent, 0, 0)); + + // Hover highlight + if (hoveredAgent) { + const agent = agents.find(a => a.id === hoveredAgent); + if (agent) { + const hx = agent.x * TILE * SCALE; + const hy = agent.y * TILE * SCALE; + ctx.strokeStyle = '#ffd700'; + ctx.lineWidth = 2; + ctx.beginPath(); + ctx.roundRect(hx + 2, hy + 2, TILE * SCALE - 4, TILE * SCALE - 4, 4); + ctx.stroke(); } } - return null; - }, [agentList]); + }, [agents, hoveredAgent]); - // Mouse move → hover detection + useEffect(() => { + render(); + }, [render]); + + // Handle mouse for hover detection const handleMouseMove = useCallback((e) => { const canvas = canvasRef.current; if (!canvas) return; const rect = canvas.getBoundingClientRect(); - const scaleX = CANVAS_W / rect.width; - const scaleY = CANVAS_H / rect.height; + const scaleX = canvasWidth / rect.width; + const scaleY = canvasHeight / rect.height; const mx = (e.clientX - rect.left) * scaleX; const my = (e.clientY - rect.top) * scaleY; - const agent = getAgentAtPoint(mx, my); - hoveredRef.current = agent; - setHoveredAgent(agent); - if (onAgentHover) onAgentHover(agent); - }, [getAgentAtPoint, onAgentHover]); - // Mouse leave → clear hover - const handleMouseLeave = useCallback(() => { - hoveredRef.current = null; - setHoveredAgent(null); - if (onAgentHover) onAgentHover(null); - }, [onAgentHover]); + const tx = Math.floor(mx / (TILE * SCALE)); + const ty = Math.floor(my / (TILE * SCALE)); - // Canvas click → open detail card for hovered agent - const handleCanvasClick = useCallback((e) => { - const agent = hoveredRef.current; - if (agent) { - onAgentClick(agent); + // Find agent at this tile + const found = agents.find(a => { + const ax = Math.floor(a.x); + const ay = Math.floor(a.y); + return (tx === ax && ty === ay) || (tx === ax && ty === ay - 1); + }); + + setHoveredAgent(found ? found.id : null); + }, [agents, setHoveredAgent]); + + const handleClick = useCallback((e) => { + if (hoveredAgent) { + selectAgent(hoveredAgent); } - }, [onAgentClick]); - - // Animation loop - useEffect(() => { - const canvas = canvasRef.current; - if (!canvas) return; - const ctx = canvas.getContext('2d'); - ctx.imageSmoothingEnabled = false; // pixel-art crisp - - // Pre-load tileset - loadTileset(); - let startTime = Date.now(); - - function loop() { - const time = Date.now() - startTime; - ctx.clearRect(0, 0, CANVAS_W, CANVAS_H); - - // Layer 1: Background (outdoor area around building) - drawBackground(ctx); - - // Layer 2: Floor tiles (from tileset) - drawFloorLayer(ctx); - - // Layer 3: Walls (from tileset, drawn on top of floors) - drawWallLayer(ctx); - - // Layer 3.5: Doorways (openings in walls) - drawDoorways(ctx); - - // Layer 4: Furniture - drawFurniture(ctx); - - // Room labels - drawRoomLabels(ctx); - - // Layer 5: Agents - const currentAgents = useStore.getState().agents; - for (const agent of Object.values(currentAgents)) { - drawAgent(ctx, agent, time); - } - - // Hover tooltip - const hAgent = hoveredRef.current; - if (hAgent) { - const pos = hAgent._smoothPos || hAgent.position; - if (pos) { - const hpx = pos.col * TILE_SIZE + TILE_SIZE / 2; - const hpy = pos.row * TILE_SIZE + TILE_SIZE / 2; - const activity = hAgent.activity || 'idle'; - const name = hAgent.name || hAgent.id; - const task = hAgent.currentTask || hAgent.task || ''; - - const statusColors = { - idle: '#44cc44', working: '#ffcc00', thinking: '#44aaff', - offline: '#888', blocked: '#ff4444', - }; - const statusColor = statusColors[activity] || '#888'; - - ctx.font = '10px "Courier New", monospace'; - const nameW = ctx.measureText(name).width; - ctx.font = '9px "Courier New", monospace'; - const statusW = ctx.measureText(activity).width; - const taskW = task ? Math.min(ctx.measureText(task).width, 180) : 0; - const tooltipW = Math.max(nameW + 28, statusW + taskW + 8) + 16; - const tooltipH = task ? 48 : 36; - - const tx = Math.min(hpx + 10, CANVAS_W - tooltipW - 4); - const ty = Math.max(hpy - tooltipH - 24, 4); - - // Tooltip background - ctx.fillStyle = 'rgba(0,0,0,0.82)'; - ctx.beginPath(); - ctx.roundRect(tx, ty, tooltipW, tooltipH, 6); - ctx.fill(); - ctx.strokeStyle = 'rgba(255,255,255,0.2)'; - ctx.lineWidth = 1; - ctx.stroke(); - - // Name - ctx.font = 'bold 10px "Courier New", monospace'; - ctx.textAlign = 'left'; - ctx.fillStyle = '#FFF'; - ctx.fillText(name, tx + 8, ty + 14); - - // Status badge - ctx.font = '9px "Courier New", monospace'; - ctx.fillStyle = 'rgba(0,0,0,0.5)'; - ctx.beginPath(); - ctx.roundRect(tx + nameW + 12, ty + 5, statusW + 8, 14, 3); - ctx.fill(); - ctx.fillStyle = statusColor; - ctx.fillText(activity, tx + nameW + 16, ty + 15); - - // Task line - if (task) { - ctx.font = '8px "Courier New", monospace'; - ctx.fillStyle = '#aaa'; - const taskText = task.length > 35 ? task.slice(0, 32) + '...' : task; - ctx.fillText(taskText, tx + 8, ty + 34); - } - } - } - - drawParticles(ctx); - - animRef.current = requestAnimationFrame(loop); - } - - loop(); - return () => { - if (animRef.current) cancelAnimationFrame(animRef.current); - }; - }, []); + }, [hoveredAgent, selectAgent]); return ( -
+
); -} +} \ No newline at end of file diff --git a/src/frontend/WebSocketClient.js b/src/frontend/WebSocketClient.js index ad5cd0a..fa4427a 100644 --- a/src/frontend/WebSocketClient.js +++ b/src/frontend/WebSocketClient.js @@ -153,15 +153,30 @@ class WebSocketClient { ); } - // Occasionally move agents - if (cycle % 10 === 0) { + // Occasionally move agents (with collision avoidance) + if (cycle % 8 === 0) { const agentId = agentIds[Math.floor(Math.random() * agentIds.length)]; - const pos = store.agents[agentId]?.position; + const pos = store.agents[agentId]?.targetPosition || store.agents[agentId]?.position; if (pos) { - store.updateAgentPosition(agentId, { - row: Math.max(1, Math.min(18, pos.row + (Math.random() - 0.5) * 4)), - col: Math.max(1, Math.min(26, pos.col + (Math.random() - 0.5) * 6)), - }); + // Check ALL other agents' current AND target positions + const occupied = new Set( + Object.entries(store.agents) + .filter(([id]) => id !== agentId) + .flatMap(([, a]) => { + const pts = []; + if (a.position) pts.push(`${a.position.row},${a.position.col}`); + if (a.targetPosition) pts.push(`${a.targetPosition.row},${a.targetPosition.col}`); + if (a._smoothPos) pts.push(`${Math.round(a._smoothPos.row)},${Math.round(a._smoothPos.col)}`); + return pts; + }) + ); + let newRow, newCol, attempts = 0; + do { + newRow = Math.max(1, Math.min(18, pos.row + Math.floor((Math.random() - 0.5) * 10))); + newCol = Math.max(1, Math.min(26, pos.col + Math.floor((Math.random() - 0.5) * 14))); + attempts++; + } while (occupied.has(`${newRow},${newCol}`) && attempts < 20); + store.updateAgentPosition(agentId, { row: newRow, col: newCol }); } } }, 1000); diff --git a/src/frontend/officeMap.js b/src/frontend/officeMap.js index cec373b..9ac3430 100644 --- a/src/frontend/officeMap.js +++ b/src/frontend/officeMap.js @@ -1,421 +1,134 @@ -// Tile map for spatial office using LimeZu Modern Interiors tileset -// Tileset: 16 tiles wide × 89 tiles tall, each tile 32×32px -// Room-builder: 17 tiles wide × 23 tiles tall, floor textures and wall variants +// officeMap.js — Clean room definitions for the Scobleclaw Virtual Office +// No tile IDs, no guessing. Just rooms with colors and furniture. -// Map dimensions: 20 cols × 15 rows = 640×480 internal px (scaled via canvas CSS) -export const MAP_COLS = 20; -export const MAP_ROWS = 15; -export const TILE_SIZE = 32; +const TILE = 32; // pixels per tile +const COLS = 25; +const ROWS = 20; -// ── Tile IDs from tileset.png (16-wide grid) ──────────────────── -// Tile grid position: tileId = row * 16 + col -export const TILES = { - EMPTY: -1, - - // ── Ground / outdoor tiles ────────────────────────────── - // We'll use the room-builder for grass/outdoor if needed - GRASS: -2, // drawn procedurally - - // ── Floor tiles from tileset.png ──────────────────────── - // Wood floor variants (row 1, cols 0-3): tile IDs 16-19 - FLOOR_WOOD_LIGHT: 16, // (r1,c0) - light wood planks - FLOOR_WOOD_LIGHT2: 18, // (r1,c2) - light wood variant - FLOOR_WOOD_LIGHT3: 19, // (r1,c3) - light wood variant - - // Stone/checkered floor (row 5-6): tile IDs ~83-99 - FLOOR_STONE: 83, // (r5,c3) - stone floor - FLOOR_STONE2: 99, // (r6,c3) - stone floor variant - - // Carpet tiles (row 1, cols 6-13): tile IDs 22-29 - FLOOR_CARPET_GREEN: 22, // (r1,c6) - greenish carpet - FLOOR_CARPET_GREEN2: 23, // (r1,c7) - green variant - FLOOR_CARPET_BROWN: 25, // (r1,c9) - brown carpet - FLOOR_CARPET_BROWN2: 26, // (r1,c10) - brown variant - - // Dark blue/study floor (row 2, cols 6-14): tile IDs 38-46 - FLOOR_STUDY: 38, // (r2,c6) - dark blue study carpet - FLOOR_STUDY2: 39, // (r2,c7) - variant - - // Gray tile floor (row 3, cols 6-11): tile IDs 54-59 - FLOOR_GRAY_TILE: 54, // (r3,c6) - gray tile - FLOOR_GRAY_TILE2: 55, // (r3,c7) - variant - - // Warm wood floor (row 4): tile IDs 67-68 - FLOOR_WARM_WOOD: 67, // (r4,c3) - warm wood planks - FLOOR_WARM_WOOD2: 68, // (r4,c4) - variant - - // Plush carpet (row 4, cols 6-9): tile IDs 70-73 - FLOOR_PLUSH: 70, // (r4,c6) - plush pink/tan carpet - FLOOR_PLUSH2: 71, // (r4,c7) - variant - - // ── Wall tiles from tileset.png ───────────────────────── - // Wall sections (row 16+): stone/brick walls - // Interior wall (row 16-17): tile IDs ~257-287 - WALL_BRICK: 258, // (r16,c2) - brick wall body - WALL_BRICK2: 259, // (r16,c3) - brick variant - WALL_BRICK_TOP: 257, // (r16,c1) - brick wall top edge - WALL_BRICK_BOTTOM: 274, // (r17,c2) - brick wall bottom - - // Dark wall (row 26-28): tile IDs ~416-461 - WALL_DARK: 433, // (r27,c1) - dark wall body - WALL_DARK2: 434, // (r27,c2) - variant - - // Light plaster wall (row 28-29): tile IDs ~448-477 - WALL_PLASTER: 464, // (r29,c0) - plaster wall body - WALL_PLASTER_TOP: 466, // (r29,c2) - top with shadow - - // Interior wood wall (room-builder, row 5 col 2-3): room-builder tiles - // We reference room-builder walls separately - - // ── Door tiles from tileset.png ───────────────────────── - // Doors are typically in the wall sections - DOOR_WOOD: 296, // (r18,c8) - red/wood door, closed - DOOR_WOOD2: 297, // (r18,c9) - variant - - // ── Window tiles ──────────────────────────────────────── - WINDOW: 305, // (r19,c1) - window hint - WINDOW_GLASS: 300, // (r18,c12) - glass pane - - // ── Furniture tiles (approximate from analysis) ──────── - // These are in the tileset rows 33-65 - TABLE_WOOD: 580, // (r36,c4) - table top - CHAIR_WOOD: 528, // (r33,c0) - wooden chair - DESK: 583, // (r36,c7) - desk surface - BOOKSHELF: 736, // (r46,c0) - bookshelf - BOOKSHELF2: 737, // (r46,c1) - bookshelf variant - PLANT: 584, // (r36,c8) - potted plant - PLANT2: 587, // (r36,c11) - plant variant - LAMP: 674, // (r42,c2) - lamp/light - SOFA_LEFT: 736, // Using bookshelf area as sofa placeholder - SOFA_RIGHT: 737, - FILING_CABINET: 744, // (r46,c8) - cabinet/locker - RUG: 652, // (r40,c12) - decorative rug - COFFEE_TABLE: 672, // (r42,c0) - low table - PLANT_BIG: 632, // (r39,c8) - large plant - MONITOR: 744, // Monitor-like object - WHITEBOARD: 709, // (r44,c5) - whiteboard/wall decor -}; -// ── Room builder tiles (separate PNG) ────────────────────────── -// These are for floor/wall variants from room-builder.png -// Room-builder is 17 tiles wide -export const RB_TILES = { - // Wall textures (rows 5-15 in room-builder) - WALL_RED_BRICK: 80, // (r5,c0) - red brick wall - WALL_RED_BRICK2: 81, // (r5,c1) - variant - WALL_DARK_WOOD: 84, // (r5,c4) - dark wood panel - WALL_CREAM: 112, // (r7,c0) - cream/yellow wall - WALL_CREAM2: 113, // (r7,c1) - variant - WALL_BROWN_WOOD: 128, // (r8,c0) - brown wood panel - WALL_TEAL: 144, // (r9,c0) - teal wall - WALL_GREEN: 160, // (r10,c0) - green wall - WALL_STONE_WARM: 176, // (r11,c0) - warm stone - WALL_BEIGE: 192, // (r12,c0) - beige wall - WALL_GRAY_STONE: 208, // (r13,c0) - gray stone - WALL_RED_STONE: 240, // (r15,c0) - red stone - - // Floor tiles (scattered in room-builder) - FLOOR_STONE_BEIGE: 48, // (r3,c0) area - beige stone - FLOOR_STONE_BEIGE2: 49, -}; - -// ── Room definitions ────────────────────────────────────────── -export const ROOMS = { - 'briefing': { name: 'Briefing Room', col: 0, row: 3, w: 6, h: 3, floor: 'FLOOR_WOOD_LIGHT' }, - 'commons': { name: 'Commons', col: 6, row: 3, w: 8, h: 3, floor: 'FLOOR_CARPET_GREEN' }, - 'war-room': { name: 'War Room', col: 14, row: 3, w: 6, h: 3, floor: 'FLOOR_STONE' }, - 'eng-bay': { name: 'Engineering Bay', col: 0, row: 9, w: 6, h: 6, floor: 'FLOOR_WARM_WOOD' }, - 'quiet': { name: 'Quiet Zone', col: 6, row: 9, w: 8, h: 4, floor: 'FLOOR_STUDY' }, - 'ops': { name: 'Ops Center', col: 14, row: 9, w: 6, h: 6, floor: 'FLOOR_GRAY_TILE' }, -}; - -// ── Hallway tile markers ────────────────────────────────────── -const HALL = 999; // hallway marker (rendered with hallway floor) -const EMPTY = -1; // outside/void - -// ── Tile type constants for multi-tile rendering ────────────── -// We'll use these as references for the 2D map grid -const F = { - // Floors - WL: 16, // wood light - WL2: 18, // wood light variant - CG: 22, // carpet green - CG2: 23, // carpet green variant - ST: 83, // stone tile - ST2: 99, // stone variant - WW: 67, // warm wood - WW2: 68, // warm wood variant - SD: 38, // study carpet (dark blue) - SD2: 39, // study variant - GT: 54, // gray tile - GT2: 55, // gray tile variant - HL: 70, // hallway (plush carpet) - - // Walls (from tileset) - WB: 258, // wall brick - WB2: 259, // wall brick variant - WT: 257, // wall top - WWD: 464, // wood wall dark - WWD2: 465,// wood wall dark variant - - // Furniture - TB: 528, // table/chair base - DK: 936, // desk - BS: 736, // bookshelf - PL: 584, // plant - LP: 889, // lamp - SF: 674, // sofa - FC: 1012, // filing cabinet - RG: 672, // rug/coffee table - MB: 996, // monitor - CB: 1010, // cabinet - DO: 296, // door -}; - -// ── Office Map: 20 columns × 15 rows ───────────────────────── -// Each cell is a base tile ID. Walls are drawn on top as border tiles. -// Row 0-2: exterior wall / roof area -// Row 3-5: upper rooms (Briefing, Commons, War Room) -// Row 6-8: hallway -// Row 9-14: lower rooms (Engineering Bay, Quiet Zone, Ops Center) - -export const OFFICE_MAP = [ - // Row 0: Exterior top wall - [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY], - // Row 1: Exterior wall top edge - [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY], - // Row 2: Exterior wall (north wall) - [EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY], - - // Row 3: Upper rooms - floor with wall separators - // BR = Briefing Room (col 0-5), Commons (col 6-13), War Room (col 14-19) - [F.WL, F.WL, F.WL, F.WL, F.WL, F.WL, F.CG, F.CG, F.CG, F.CG, - F.CG, F.CG, F.CG, F.CG, F.ST, F.ST, F.ST, F.ST, F.ST, F.ST], - - // Row 4: Upper rooms continue - [F.WL, F.WL, F.WL2, F.WL, F.WL2, F.WL, F.CG, F.CG2, F.CG, F.CG2, - F.CG, F.CG2, F.CG, F.CG, F.ST, F.ST2, F.ST, F.ST2, F.ST, F.ST], - - // Row 5: Upper rooms bottom row - [F.WL2, F.WL2, F.WL, F.WL2, F.WL, F.WL2, F.CG2, F.CG, F.CG2, F.CG, - F.CG2, F.CG, F.CG2, F.CG, F.ST2, F.ST, F.ST2, F.ST, F.ST2, F.ST], - - // Row 6: HALLWAY (connects all rooms) - [F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, - F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL], - - // Row 7: HALLWAY center - [F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, - F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL], - - // Row 8: HALLWAY bottom - [F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, - F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL, F.HL], - - // Row 9: Lower rooms - // Engineering Bay (col 0-5), Quiet Zone (col 6-13), Ops Center (col 14-19) - [F.WW, F.WW, F.WW, F.WW, F.WW, F.WW, F.SD, F.SD, F.SD, F.SD, - F.SD, F.SD, F.SD, F.SD, F.GT, F.GT, F.GT, F.GT, F.GT, F.GT], - - // Row 10: Lower rooms - [F.WW2, F.WW, F.WW2, F.WW, F.WW2, F.WW, F.SD2, F.SD, F.SD2, F.SD, - F.SD2, F.SD, F.SD2, F.SD, F.GT2, F.GT, F.GT2, F.GT, F.GT2, F.GT], - - // Row 11: Lower rooms - [F.WW, F.WW2, F.WW, F.WW2, F.WW, F.WW2, F.SD, F.SD2, F.SD, F.SD2, - F.SD, F.SD2, F.SD, F.SD2, F.GT, F.GT2, F.GT, F.GT2, F.GT, F.GT2], - - // Row 12: Lower rooms / quiet zone ends - [F.WW2, F.WW, F.WW2, F.WW, F.WW2, F.WW, F.SD2, F.SD, F.SD2, F.SD, - F.SD2, F.SD, F.SD2, F.SD, F.GT2, F.GT, F.GT2, F.GT, F.GT2, F.GT], - - // Row 13: Lower rooms - [F.WW, F.WW2, F.WW, F.WW2, F.WW, F.WW2, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, F.GT, F.GT2, F.GT, F.GT2, F.GT, F.GT2], - - // Row 14: Bottom row - lower rooms + exterior bottom wall - [F.WW2, F.WW, F.WW2, F.WW, F.WW2, F.WW, EMPTY, EMPTY, EMPTY, EMPTY, - EMPTY, EMPTY, EMPTY, EMPTY, F.GT2, F.GT, F.GT2, F.GT, F.GT2, F.GT], +// Room layout: rooms are defined by their bounding box + visual style +// Each agent gets a "desk" position in their department room +const rooms = [ + { + id: 'briefing', + name: 'Briefing Room', + x: 1, y: 1, w: 7, h: 5, + floor: '#c9a86c', // warm wood + wall: '#5a4a3a', + accent: '#8b7355', + }, + { + id: 'commons', + name: 'Commons', + x: 9, y: 1, w: 7, h: 5, + floor: '#b8c9a0', // sage green + wall: '#4a5a3a', + accent: '#6b8a50', + }, + { + id: 'warroom', + name: 'War Room', + x: 17, y: 1, w: 7, h: 5, + floor: '#d4c4a8', // light stone + wall: '#6a5a4a', + accent: '#8a7a60', + }, + { + id: 'engineering', + name: 'Engineering Bay', + x: 1, y: 8, w: 7, h: 5, + floor: '#a8c4d4', // cool blue-grey + wall: '#3a5a6a', + accent: '#5080a0', + }, + { + id: 'quiet', + name: 'Quiet Zone', + x: 9, y: 8, w: 7, h: 5, + floor: '#d4d0e8', // soft lavender + wall: '#5a5070', + accent: '#8070a0', + }, + { + id: 'ops', + name: 'Ops Center', + x: 17, y: 8, w: 7, h: 5, + floor: '#c8d8d0', // mint + wall: '#4a6a5a', + accent: '#608a70', + }, ]; -// ── Wall definitions (drawn on top of floors) ──────────────── -// Each wall entry: { row, col, tileId } -// Walls between rooms at column boundaries and row boundaries -export const WALLS = [ - // Exterior walls (row 0-2) - // North wall row - ...Array.from({ length: 20 }, (_, c) => ({ row: 2, col: c, tile: F.WB2 })), +// Agent desk positions — where each agent "sits" in their room +// Positioned at center-ish of each room +const agentDesks = { + cos: { room: 'briefing', tx: 4, ty: 3 }, + content: { room: 'commons', tx: 12, ty: 3 }, + market: { room: 'warroom', tx: 20, ty: 3 }, + engineering: { room: 'engineering', tx: 4, ty: 10 }, + 'senior-eng': { room: 'quiet', tx: 12, ty: 10 }, + trust: { room: 'ops', tx: 20, ty: 10 }, + health: { room: 'briefing', tx: 2, ty: 3 }, // shares briefing + vault: { room: 'commons', tx: 10, ty: 3 }, // shares commons + presentations:{ room: 'ops', tx: 22, ty: 10 }, // shares ops +}; - // Vertical walls between rooms (wall at column 5 between Briefing/Commons) - { row: 3, col: 5, tile: F.WB }, - { row: 4, col: 5, tile: F.WB }, - // Doorway at row 5, col 5 (hallway level) - { row: 3, col: 13, tile: F.WB }, - { row: 4, col: 13, tile: F.WB }, - // Doorway at row 5, col 13 +// Hallway tiles connecting rooms +// Top hallway: y=6-7, bottom hallway: y=14-15 +// Left hallway: x=8, right hallway: x=16 +const hallwayTiles = []; +// Top row hallway +for (let x = 1; x < 24; x++) { + hallwayTiles.push({ x, y: 6 }); + hallwayTiles.push({ x, y: 7 }); +} +// Bottom row hallway +for (let x = 1; x < 24; x++) { + hallwayTiles.push({ x, y: 14 }); + hallwayTiles.push({ x, y: 15 }); +} +// Left vertical connector +for (let y = 6; y <= 15; y++) { + hallwayTiles.push({ x: 8, y }); + hallwayTiles.push({ x: 16, y }); +} - // Vertical walls below hallway - { row: 9, col: 5, tile: F.WB }, - { row: 10, col: 5, tile: F.WB }, - { row: 11, col: 5, tile: F.WB }, - { row: 12, col: 5, tile: F.WB }, - { row: 13, col: 5, tile: F.WB }, - { row: 14, col: 5, tile: F.WB }, +// Furniture definitions: type + tile position relative to room origin +const furniture = { + briefing: [ + { type: 'table', rx: 3, ry: 2, w: 3, h: 2 }, // conference table + { type: 'chair', rx: 2, ry: 2 }, + { type: 'chair', rx: 6, ry: 2 }, + { type: 'plant', rx: 6, ry: 0 }, + ], + commons: [ + { type: 'sofa', rx: 2, ry: 1, w: 3, h: 1 }, + { type: 'table', rx: 3, ry: 2, w: 2, h: 1 }, + { type: 'shelf', rx: 0, ry: 0, w: 1, h: 2 }, + { type: 'plant', rx: 6, ry: 0 }, + ], + warroom: [ + { type: 'table', rx: 3, ry: 2, w: 3, h: 2 }, + { type: 'screen', rx: 0, ry: 1, w: 1, h: 2 }, + { type: 'chair', rx: 2, ry: 2 }, + { type: 'chair', rx: 6, ry: 2 }, + ], + engineering: [ + { type: 'desk', rx: 3, ry: 2, w: 2, h: 1 }, + { type: 'monitor',rx: 3, ry: 2 }, + { type: 'desk', rx: 1, ry: 3, w: 2, h: 1 }, + { type: 'shelf', rx: 5, ry: 0, w: 1, h: 2 }, + ], + quiet: [ + { type: 'desk', rx: 3, ry: 2, w: 2, h: 1 }, + { type: 'lamp', rx: 2, ry: 1 }, + { type: 'bookcase',rx: 5, ry: 0, w: 1, h: 3 }, + ], + ops: [ + { type: 'table', rx: 3, ry: 2, w: 3, h: 2 }, + { type: 'monitor',rx: 1, ry: 2 }, + { type: 'monitor',rx: 6, ry: 2 }, + { type: 'screen', rx: 0, ry: 1, w: 1, h: 2 }, + ], +}; - { row: 9, col: 13, tile: F.WB }, - { row: 10, col: 13, tile: F.WB }, - { row: 11, col: 13, tile: F.WB }, - { row: 12, col: 13, tile: F.WB }, - { row: 13, col: 13, tile: F.WB }, - { row: 14, col: 13, tile: F.WB }, - - // Horizontal wall between upper rooms and hallway (row 5 bottom edge) - ...Array.from({ length: 6 }, (_, c) => ({ row: 5, col: c, tile: F.WB2 })), - ...Array.from({ length: 8 }, (_, c) => ({ row: 5, col: c + 6, tile: F.WB2 })), - ...Array.from({ length: 6 }, (_, c) => ({ row: 5, col: c + 14, tile: F.WB2 })), - - // Horizontal wall between hallway and lower rooms (row 8 bottom edge) - ...Array.from({ length: 6 }, (_, c) => ({ row: 8, col: c, tile: F.WB2 })), - ...Array.from({ length: 8 }, (_, c) => ({ row: 8, col: c + 6, tile: F.WB2 })), - ...Array.from({ length: 6 }, (_, c) => ({ row: 8, col: c + 14, tile: F.WB2 })), - - // Exterior walls (left edge) - { row: 3, col: 0, tile: F.WB }, - { row: 4, col: 0, tile: F.WB }, - { row: 9, col: 0, tile: F.WB }, - { row: 10, col: 0, tile: F.WB }, - { row: 11, col: 0, tile: F.WB }, - { row: 12, col: 0, tile: F.WB }, - { row: 13, col: 0, tile: F.WB }, - { row: 14, col: 0, tile: F.WB }, - - // Exterior walls (right edge) - { row: 3, col: 19, tile: F.WB }, - { row: 4, col: 19, tile: F.WB }, - { row: 9, col: 19, tile: F.WB }, - { row: 10, col: 19, tile: F.WB }, - { row: 11, col: 19, tile: F.WB }, - { row: 12, col: 19, tile: F.WB }, - { row: 13, col: 19, tile: F.WB }, - { row: 14, col: 19, tile: F.WB }, - - // Bottom wall (row 14 bottom edge) - ...Array.from({ length: 6 }, (_, c) => ({ row: 14, col: c, tile: F.WB2 })), - ...Array.from({ length: 6 }, (_, c) => ({ row: 14, col: c + 14, tile: F.WB2 })), - - // Wall separators at hallway left/right (row 6-8, col 0/19 already exterior) -]; - -// ── Doorways (openings in walls) ────────────────────────────── -// These overwrite wall tiles at specific positions -export const DOORWAYS = [ - // Briefing Room → Hallway (col 2, row 5) - { row: 5, col: 2, tile: F.DO }, - // Commons → Hallway (col 9, row 5 and row 8) - { row: 5, col: 9, tile: F.DO }, - { row: 8, col: 9, tile: F.DO }, - // War Room → Hallway (col 16, row 5) - { row: 5, col: 16, tile: F.DO }, - // Engineering Bay → Hallway (col 2, row 8) - { row: 8, col: 2, tile: F.DO }, - // Quiet Zone → Hallway (col 9, row 8) same as Commons lower - // Ops Center → Hallway (col 16, row 8) - { row: 8, col: 16, tile: F.DO }, -]; - -// ── Furniture placements ────────────────────────────────────── -// { row, col, tileId } -export const FURNITURE = [ - // === Briefing Room (col 0-5, row 3-5) === - // Round table center - { row: 4, col: 2, tile: F.RG }, - // Chairs around table - { row: 3, col: 1, tile: F.TB }, - { row: 3, col: 3, tile: F.TB }, - { row: 5, col: 1, tile: F.TB }, - { row: 5, col: 3, tile: F.TB }, - // Plant in corner - { row: 4, col: 4, tile: F.PL }, - - // === Commons (col 6-13, row 3-5) === - // Sofa area - { row: 3, col: 7, tile: F.SF }, - { row: 3, col: 8, tile: F.SF }, - // Coffee table - { row: 4, col: 7, tile: F.RG }, - { row: 4, col: 8, tile: F.RG }, - // Plant - { row: 3, col: 10, tile: F.PL }, - { row: 5, col: 7, tile: F.PL }, - // Lamp - { row: 4, col: 11, tile: F.LP }, - - // === War Room (col 14-19, row 3-5) === - // Large table - { row: 4, col: 15, tile: F.RG }, - { row: 4, col: 16, tile: F.RG }, - { row: 4, col: 17, tile: F.RG }, - // Chairs around - { row: 3, col: 15, tile: F.TB }, - { row: 3, col: 16, tile: F.TB }, - { row: 3, col: 17, tile: F.TB }, - { row: 5, col: 15, tile: F.TB }, - { row: 5, col: 16, tile: F.TB }, - { row: 5, col: 17, tile: F.TB }, - // Whiteboard - { row: 3, col: 18, tile: F.MB }, - - // === Engineering Bay (col 0-5, row 9-14) === - // Desks with monitors - { row: 10, col: 1, tile: F.DK }, - { row: 10, col: 2, tile: F.MB }, - { row: 12, col: 1, tile: F.DK }, - { row: 12, col: 2, tile: F.MB }, - { row: 10, col: 4, tile: F.DK }, - { row: 12, col: 4, tile: F.DK }, - // Bookshelf - { row: 9, col: 4, tile: F.BS }, - // Filing cabinet - { row: 9, col: 1, tile: F.FC }, - // Plant - { row: 13, col: 4, tile: F.PL }, - - // === Quiet Zone (col 6-13, row 9-12) === - // Individual desks - { row: 9, col: 7, tile: F.DK }, - { row: 9, col: 9, tile: F.DK }, - { row: 11, col: 7, tile: F.DK }, - { row: 11, col: 9, tile: F.DK }, - // Bookshelf - { row: 10, col: 12, tile: F.BS }, - // Lamp - { row: 9, col: 12, tile: F.LP }, - { row: 11, col: 12, tile: F.LP }, - // Plant - { row: 10, col: 6, tile: F.PL }, - - // === Ops Center (col 14-19, row 9-14) === - // Desks with monitors - { row: 10, col: 15, tile: F.DK }, - { row: 10, col: 16, tile: F.MB }, - { row: 12, col: 15, tile: F.DK }, - { row: 12, col: 16, tile: F.MB }, - { row: 10, col: 18, tile: F.DK }, - { row: 12, col: 18, tile: F.DK }, - // Filing cabinets - { row: 9, col: 15, tile: F.FC }, - { row: 9, col: 16, tile: F.FC }, - // Server rack / cabinet - { row: 9, col: 18, tile: F.CB }, - { row: 14, col: 18, tile: F.CB }, - // Plant - { row: 14, col: 15, tile: F.PL }, - - // === Hallway decorations === - { row: 6, col: 2, tile: F.PL }, - { row: 6, col: 10, tile: F.PL }, - { row: 7, col: 17, tile: F.PL }, - { row: 8, col: 11, tile: F.PL }, -]; +module.exports = { TILE, COLS, ROWS, rooms, agentDesks, hallwayTiles, furniture }; \ No newline at end of file diff --git a/src/frontend/store.js b/src/frontend/store.js index faf70d8..fa82da3 100644 --- a/src/frontend/store.js +++ b/src/frontend/store.js @@ -1,216 +1,95 @@ import { create } from 'zustand'; +import { agentDesks, rooms } from './officeMap'; -// ── Stardew-inspired Zone definitions ─────────────────────────────── -const ZONES = { - 'pod-a': { - id: 'pod-a', - name: 'Workshop', - type: 'collaboration', - color: '#A0522D', - bounds: { row: 2, col: 8, rows: 5, cols: 5 }, - }, - 'pod-b': { - id: 'pod-b', - name: 'Studio', - type: 'collaboration', - color: '#DEB887', - bounds: { row: 2, col: 14, rows: 5, cols: 5 }, - }, - 'solo-1': { - id: 'solo-1', - name: 'Cabins', - type: 'solo', - color: '#8B4513', - bounds: { row: 2, col: 0, rows: 10, cols: 6 }, - }, - 'solo-2': { - id: 'solo-2', - name: 'Library', - type: 'solo', - color: '#5B8FA8', - bounds: { row: 2, col: 22, rows: 10, cols: 6 }, - }, - 'coaching': { - id: 'coaching', - name: 'Shrine', - type: 'self-improvement', - color: '#DAA520', - bounds: { row: 13, col: 8, rows: 4, cols: 12 }, - }, - 'coffee': { - id: 'coffee', - name: 'Campfire', - type: 'social', - color: '#FF8C42', - bounds: { row: 0, col: 10, rows: 2, cols: 8 }, - }, -}; +// Agent definitions with personality +const AGENT_DEFS = [ + { id: 'cos', name: 'Marcus', dept: 'Chief of Staff', color: '#e8833a', status: 'active' }, + { id: 'engineering', name: 'Engineering', dept: 'Engineering Bay', color: '#4ac4c4', status: 'active' }, + { id: 'senior-eng', name: 'Senior Eng', dept: 'Quiet Zone', color: '#9a6adc', status: 'active' }, + { id: 'trust', name: 'Trust', dept: 'Ops Center', color: '#4a7aff', status: 'idle' }, + { id: 'market', name: 'Market', dept: 'War Room', color: '#4aaa4a', status: 'active' }, + { id: 'health', name: 'Health', dept: 'Briefing Room', color: '#eacc4a', status: 'idle' }, + { id: 'content', name: 'Content', dept: 'Commons', color: '#aa7adc', status: 'active' }, + { id: 'presentations', name: 'Presentations', dept: 'Ops Center', color: '#ea6a6a', status: 'active' }, + { id: 'vault', name: 'Vault', dept: 'Commons', color: '#7adcaa', status: 'idle' }, +]; -// ── Agent definitions ────────────────────────────────────────────── -const AGENT_DEFS = { - cos: { id: 'cos', name: 'COS', department: 'cos', color: '#FF6B35' }, - engineering: { id: 'engineering', name: 'Engineering', department: 'engineering', color: '#4ECDC4' }, - 'senior-eng': { id: 'senior-eng', name: 'Senior Eng', department: 'senior-eng', color: '#7B2D8E' }, - trust: { id: 'trust', name: 'Trust', department: 'trust', color: '#45B7D1' }, - market: { id: 'market', name: 'Market', department: 'market', color: '#96CEB4' }, - health: { id: 'health', name: 'Health', department: 'health', color: '#FFEAA7' }, - content: { id: 'content', name: 'Content', department: 'content', color: '#DDA0DD' }, - presentations: { id: 'presentations', name: 'Presentations', department: 'presentations', color: '#FF8A80' }, - vault: { id: 'vault', name: 'Vault', department: 'vault', color: '#A5D6A7' }, -}; - -// ── Default agent positions (row, col in tile coords) ─────────── -// Office layout: 20 cols × 15 rows -// Briefing Room: col 0-5, row 3-5 -// Commons: col 6-13, row 3-5 -// War Room: col 14-19, row 3-5 -// Hallway: row 6-8 -// Engineering Bay: col 0-5, row 9-14 -// Quiet Zone: col 6-13, row 9-12 -// Ops Center: col 14-19, row 9-14 -const DEFAULT_POSITIONS = { - cos: { row: 10, col: 3 }, // Engineering Bay - engineering: { row: 11, col: 2 }, // Engineering Bay - 'senior-eng': { row: 12, col: 3 }, // Engineering Bay - trust: { row: 10, col: 17 }, // Ops Center - market: { row: 4, col: 9 }, // Commons - health: { row: 9, col: 8 }, // Quiet Zone - content: { row: 10, col: 8 }, // Quiet Zone - presentations: { row: 4, col: 16 }, // War Room - vault: { row: 9, col: 17 }, // Ops Center -}; - -// ── Helpers ──────────────────────────────────────────────────────── -function generateTileMap(gridRows, gridCols) { - const tiles = []; - for (let row = 0; row < gridRows; row++) { - tiles[row] = []; - for (let col = 0; col < gridCols; col++) { - tiles[row][col] = { type: 'floor', zoneId: findZoneForTile(row, col) }; - } - } - return { rows: gridRows, cols: gridCols, tiles }; +// Calculate initial positions from desk assignments +function initialAgents() { + return AGENT_DEFS.map(def => { + const desk = agentDesks[def.id]; + return { + ...def, + x: desk ? desk.tx : 12, + y: desk ? desk.ty : 10, + targetX: desk ? desk.tx : 12, + targetY: desk ? desk.ty : 10, + deskX: desk ? desk.tx : 12, + deskY: desk ? desk.ty : 10, + }; + }); } -function findZoneForTile(row, col) { - for (const zone of Object.values(ZONES)) { - const { row: zr, col: zc, rows, cols } = zone.bounds; - if (row >= zr && row < zr + rows && col >= zc && col < zc + cols) { - return zone.id; - } - } - return null; +// Get room bounds for wandering +function getRoomForAgent(agentId) { + const desk = agentDesks[agentId]; + if (!desk) return null; + return rooms.find(r => r.id === desk.room) || null; } -// ── Store ────────────────────────────────────────────────────────── -const useStore = create((set, get) => ({ - // Connection state - wsConnected: false, - wsReconnecting: false, +export const useStore = create((set, get) => ({ + agents: initialAgents(), + hoveredAgent: null, + selectedAgent: null, - // World state - grid: generateTileMap(15, 20), - zones: ZONES, - agents: {}, + setHoveredAgent: (id) => set({ hoveredAgent: id }), + selectAgent: (id) => set({ selectedAgent: id }), + clearSelection: () => set({ selectedAgent: null }), - // Initialize from full state snapshot - initFromSnapshot(snapshot) { - const agents = {}; - for (const agentId of Object.keys(AGENT_DEFS)) { - const def = AGENT_DEFS[agentId]; - const pos = DEFAULT_POSITIONS[agentId]; - agents[agentId] = { - ...def, - position: { row: pos.row, col: pos.col }, - targetPosition: { row: pos.row, col: pos.col }, - activity: 'idle', - currentTask: null, - lastHeartbeat: Date.now(), - pulse: 0, - }; - } - // Apply snapshot overrides if provided - if (snapshot && snapshot.agents) { - for (const [id, data] of Object.entries(snapshot.agents)) { - if (agents[id]) { - Object.assign(agents[id], data); - if (data.position) { - agents[id].targetPosition = { ...data.position }; + // Update agent positions from WS state + updateAgentState: (agentStates) => { + set(s => ({ + agents: s.agents.map(a => { + const ws = agentStates[a.id]; + if (ws) { + return { ...a, status: ws.status || a.status, name: ws.name || a.name }; + } + return a; + }), + })); + }, + + // Wander agents within their room bounds + tick: () => { + set(s => ({ + agents: s.agents.map(a => { + // Move toward target + const dx = a.targetX - a.x; + const dy = a.targetY - a.y; + const speed = 0.08; + + let newX = a.x + dx * speed; + let newY = a.y + dy * speed; + + // Snap if close enough + if (Math.abs(dx) < 0.1 && Math.abs(dy) < 0.1) { + newX = a.targetX; + newY = a.targetY; + + // Pick new random target within room (occasionally) + if (Math.random() < 0.01) { + const room = getRoomForAgent(a.id); + if (room) { + const margin = 1.5; + const tx = room.x + margin + Math.random() * (room.w - margin * 2); + const ty = room.y + margin + Math.random() * (room.h - margin * 2); + return { ...a, x: newX, y: newY, targetX: tx, targetY: ty }; + } } } - } - } - set({ agents, wsConnected: true, wsReconnecting: false }); + + return { ...a, x: newX, y: newY }; + }), + })); }, - - // Apply a diff update - applyDiff(diffs) { - const state = get(); - const updated = { ...state.agents }; - - for (const diff of diffs) { - if (diff.op === 'agent.move' || diff.op === 'agent.update') { - const agentId = diff.path.split('.')[1]; - if (updated[agentId]) { - const delta = diff.value || {}; - if (delta.position) { - delta.targetPosition = { ...delta.position }; - } - Object.assign(updated[agentId], delta); - } - } else if (diff.op === 'agent.position') { - const agentId = diff.path.split('.')[1]; - if (updated[agentId]) { - updated[agentId].targetPosition = { ...diff.value }; - } - } else if (diff.op === 'agent.activity') { - const agentId = diff.path.split('.')[1]; - if (updated[agentId]) { - updated[agentId] = { ...updated[agentId], ...diff.value }; - } - } - } - - set({ agents: updated }); - }, - - // WS connection status - setWsConnected(connected) { - set({ wsConnected: connected, wsReconnecting: !connected }); - }, - - setWsReconnecting(reconnecting) { - set({ wsReconnecting: reconnecting }); - }, - - // Update agent positions directly (used by mock mode) - updateAgentPosition(agentId, position) { - set(state => { - const agents = { ...state.agents }; - if (agents[agentId]) { - agents[agentId] = { - ...agents[agentId], - targetPosition: { ...position }, - }; - } - return { agents }; - }); - }, - - updateAgentActivity(agentId, activity, task) { - set(state => { - const agents = { ...state.agents }; - if (agents[agentId]) { - agents[agentId] = { - ...agents[agentId], - activity, - currentTask: task || agents[agentId].currentTask, - }; - } - return { agents }; - }); - }, -})); - -export { ZONES, AGENT_DEFS, DEFAULT_POSITIONS }; -export default useStore; +})); \ No newline at end of file