diff --git a/.vscode/settings.json b/.vscode/settings.json
index ae78692d..a0b13e03 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -9,6 +9,7 @@
"adsbygoogle",
"Adsense",
"alwaysshow",
+ "animationcomplete",
"appstore",
"awardable",
"Baldur's",
@@ -74,6 +75,7 @@
"nanomachines",
"NARUTO",
"Navi",
+ "Netherzapdos",
"NEXTAUTH",
"nextjs",
"noarchive",
@@ -108,11 +110,16 @@
"skibidi",
"Skwatta",
"snackbars",
+ "spritesheets",
"stackable",
"steamid",
"taki",
"tetris",
"tiktok",
+ "tilemap",
+ "Tilemaps",
+ "Tileset",
+ "tilesets",
"Triforce",
"trpc",
"turny",
diff --git a/apps/games/hide-and-seek/.babelrc b/apps/games/hide-and-seek/.babelrc
new file mode 100644
index 00000000..f2f38067
--- /dev/null
+++ b/apps/games/hide-and-seek/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["@nx/js/babel"]
+}
diff --git a/apps/games/hide-and-seek/.eslintrc.json b/apps/games/hide-and-seek/.eslintrc.json
new file mode 100644
index 00000000..3456be9b
--- /dev/null
+++ b/apps/games/hide-and-seek/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "extends": ["../../../.eslintrc.json"],
+ "ignorePatterns": ["!**/*"],
+ "overrides": [
+ {
+ "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.ts", "*.tsx"],
+ "rules": {}
+ },
+ {
+ "files": ["*.js", "*.jsx"],
+ "rules": {}
+ }
+ ]
+}
diff --git a/apps/games/hide-and-seek/.swcrc b/apps/games/hide-and-seek/.swcrc
new file mode 100644
index 00000000..a2d5b04f
--- /dev/null
+++ b/apps/games/hide-and-seek/.swcrc
@@ -0,0 +1,8 @@
+{
+ "jsc": {
+ "parser": {
+ "syntax": "typescript"
+ },
+ "target": "es2016"
+ }
+}
diff --git a/apps/games/hide-and-seek/index.html b/apps/games/hide-and-seek/index.html
new file mode 100644
index 00000000..4d828e75
--- /dev/null
+++ b/apps/games/hide-and-seek/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+ Hide & Seek
+
+
+
+
+
+
+
+ .
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/project.json b/apps/games/hide-and-seek/project.json
new file mode 100644
index 00000000..c844b771
--- /dev/null
+++ b/apps/games/hide-and-seek/project.json
@@ -0,0 +1,9 @@
+{
+ "name": "games-hide-and-seek",
+ "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+ "projectType": "application",
+ "sourceRoot": "apps/games/hide-and-seek/src",
+ "tags": [],
+ "// targets": "to see all targets run: nx show project games-hide-and-seek --web",
+ "targets": {}
+}
diff --git a/apps/games/hide-and-seek/public/assets/achievements/found-one.png b/apps/games/hide-and-seek/public/assets/achievements/found-one.png
new file mode 100644
index 00000000..d790658e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/achievements/found-one.png differ
diff --git a/apps/games/hide-and-seek/public/assets/achievements/found-three.png b/apps/games/hide-and-seek/public/assets/achievements/found-three.png
new file mode 100644
index 00000000..0d10fe67
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/achievements/found-three.png differ
diff --git a/apps/games/hide-and-seek/public/assets/achievements/found-two.png b/apps/games/hide-and-seek/public/assets/achievements/found-two.png
new file mode 100644
index 00000000..cbb541e0
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/achievements/found-two.png differ
diff --git a/apps/games/hide-and-seek/public/assets/achievements/perfect.png b/apps/games/hide-and-seek/public/assets/achievements/perfect.png
new file mode 100644
index 00000000..b7e1221c
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/achievements/perfect.png differ
diff --git a/apps/games/hide-and-seek/public/assets/banner.png b/apps/games/hide-and-seek/public/assets/banner.png
new file mode 100644
index 00000000..e28081fe
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/banner.png differ
diff --git a/apps/games/hide-and-seek/public/assets/buildings/1.json b/apps/games/hide-and-seek/public/assets/buildings/1.json
new file mode 100644
index 00000000..b5acd629
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/buildings/1.json
@@ -0,0 +1,2275 @@
+{ "compressionlevel":-1,
+ "height":36,
+ "infinite":false,
+ "layers":[
+ {
+ "data":[1223, 1223, 1223, 1223, 1223, 1223, 1969, 1969, 1969, 1969, 1969, 1969, 1527, 1527, 1527, 1527, 1527, 1527, 1120, 1120, 1120, 1120, 1120, 1120, 4825, 4825, 4825, 4825, 4825, 4825,
+ 1259, 1259, 1259, 1259, 1259, 1259, 2005, 2005, 2005, 2005, 2005, 2005, 1563, 1563, 1563, 1563, 1563, 1563, 1156, 1156, 1156, 1156, 1156, 1156, 4825, 4825, 4825, 4825, 4825, 4825,
+ 1295, 1295, 1295, 1295, 1295, 1295, 2041, 2041, 2041, 2041, 2041, 2041, 1599, 1599, 1599, 1599, 1599, 1599, 1192, 1192, 1192, 1192, 1192, 1192, 4825, 4825, 4825, 4825, 4825, 4825,
+ 1090, 1090, 1090, 1090, 1090, 1090, 1640, 1640, 1640, 1640, 1640, 1640, 1306, 1306, 1306, 1306, 1306, 1306, 1439, 1439, 1439, 1439, 1439, 1439, 2062, 2062, 2062, 2062, 2062, 2062,
+ 1126, 1126, 1126, 1126, 1126, 1126, 1676, 1676, 1676, 1676, 1676, 1676, 1342, 1342, 1342, 1342, 1342, 1342, 1475, 1475, 1475, 1475, 1475, 1475, 2098, 2098, 2098, 2098, 2098, 2098,
+ 1162, 1162, 1162, 1162, 1162, 1162, 1712, 1712, 1712, 1712, 1712, 1712, 1378, 1378, 1378, 1378, 1378, 1378, 1511, 1511, 1511, 1511, 1511, 1511, 2134, 2134, 2134, 2134, 2134, 2134,
+ 2170, 2170, 2170, 2170, 2170, 2170, 1542, 1542, 1542, 1542, 1542, 1542, 5390, 5390, 5390, 5390, 5390, 5390, 1861, 1861, 1861, 1861, 1861, 1861, 1331, 1331, 1331, 1331, 1331, 1331,
+ 2170, 2170, 2170, 2170, 2170, 2170, 1578, 1578, 1578, 1578, 1578, 1578, 5423, 5423, 5423, 5423, 5423, 5423, 1897, 1897, 1897, 1897, 1897, 1897, 1367, 1367, 1367, 1367, 1367, 1367,
+ 2170, 2170, 2170, 2170, 2170, 2170, 1614, 1614, 1614, 1614, 1614, 1614, 5456, 5456, 5456, 5456, 5456, 5456, 1933, 1933, 1933, 1933, 1933, 1933, 1403, 1403, 1403, 1403, 1403, 1403,
+ 1630, 1630, 1630, 1630, 1630, 1630, 1306, 1306, 1306, 1306, 1306, 1306, 1748, 1748, 1748, 1748, 1748, 1748, 1095, 1095, 1095, 1095, 1095, 1095, 1964, 1964, 1964, 1964, 1964, 1964,
+ 1666, 1666, 1666, 1666, 1666, 1666, 1342, 1342, 1342, 1342, 1342, 1342, 1784, 1784, 1784, 1784, 1784, 1784, 1131, 1131, 1131, 1131, 1131, 1131, 2000, 2000, 2000, 2000, 2000, 2000,
+ 1702, 1702, 1702, 1702, 1702, 1702, 1378, 1378, 1378, 1378, 1378, 1378, 1820, 1820, 1820, 1820, 1820, 1820, 1167, 1167, 1167, 1167, 1167, 1167, 2036, 2036, 2036, 2036, 2036, 2036,
+ 1444, 1444, 1444, 1444, 1444, 1444, 5757, 5757, 5757, 5758, 5758, 5758, 1866, 1866, 1866, 1866, 1866, 1866, 1954, 1954, 1954, 1954, 1954, 1954, 1522, 1522, 1522, 1522, 1522, 1522,
+ 1480, 1480, 1480, 1480, 1480, 1480, 5778, 5778, 5778, 5778, 5778, 5778, 1902, 1902, 1902, 1902, 1902, 1902, 1990, 1990, 1990, 1990, 1990, 1990, 1558, 1558, 1558, 1558, 1558, 1558,
+ 1516, 1516, 1516, 1516, 1516, 1516, 5778, 5778, 5778, 5778, 5778, 5778, 1938, 1938, 1938, 1938, 1938, 1938, 2026, 2026, 2026, 2026, 2026, 2026, 1594, 1594, 1594, 1594, 1594, 1594,
+ 4825, 4825, 4825, 4825, 4825, 4825, 1954, 1954, 1954, 1954, 1954, 1954, 1203, 1203, 1203, 1203, 1203, 1203, 1650, 1650, 1650, 1650, 1650, 1650, 1429, 1429, 1429, 1429, 1429, 1429,
+ 4825, 4825, 4825, 4825, 4825, 4825, 1990, 1990, 1990, 1990, 1990, 1990, 1239, 1239, 1239, 1239, 1239, 1239, 1686, 1686, 1686, 1686, 1686, 1686, 1465, 1465, 1465, 1465, 1465, 1465,
+ 4861, 4861, 4861, 4861, 4861, 4861, 2026, 2026, 2026, 2026, 2026, 2026, 1275, 1275, 1275, 1275, 1275, 1275, 1722, 1722, 1722, 1722, 1722, 1722, 1501, 1501, 1501, 1501, 1501, 1501,
+ 1316, 1316, 1316, 1316, 1316, 1316, 1552, 1552, 1552, 1552, 1552, 1552, 1105, 1105, 1105, 1105, 1105, 1105, 1228, 1228, 1228, 1228, 1228, 1228, 1306, 1306, 1306, 1306, 1306, 1306,
+ 1352, 1352, 1352, 1352, 1352, 1352, 1588, 1588, 1588, 1588, 1588, 1588, 1141, 1141, 1141, 1141, 1141, 1141, 1264, 1264, 1264, 1264, 1264, 1264, 1342, 1342, 1342, 1342, 1342, 1342,
+ 1388, 1388, 1388, 1388, 1388, 1388, 1624, 1624, 1624, 1624, 1624, 1624, 1177, 1177, 1177, 1177, 1177, 1177, 1300, 1300, 1300, 1300, 1300, 1300, 1378, 1378, 1378, 1378, 1378, 1378,
+ 1424, 1424, 1424, 1424, 1424, 1424, 1203, 1203, 1203, 1203, 1203, 1203, 2082, 2082, 2082, 2082, 2082, 2082, 1964, 1964, 1964, 1964, 1964, 1964, 1547, 1547, 1547, 1547, 1547, 1547,
+ 1460, 1460, 1460, 1460, 1460, 1460, 1239, 1239, 1239, 1239, 1239, 1239, 2118, 2118, 2118, 2118, 2118, 2118, 2000, 2000, 2000, 2000, 2000, 2000, 1583, 1583, 1583, 1583, 1583, 1583,
+ 1496, 1496, 1496, 1496, 1496, 1496, 1275, 1275, 1275, 1275, 1275, 1275, 2154, 2154, 2154, 2154, 2154, 2154, 2036, 2036, 2036, 2036, 2036, 2036, 1619, 1619, 1619, 1619, 1619, 1619,
+ 6220, 6220, 6220, 6220, 6220, 6220, 1969, 1969, 1969, 1969, 1969, 1969, 1645, 1645, 1645, 1645, 1645, 1645, 1331, 1331, 1331, 1331, 1331, 1331, 1429, 1429, 1429, 1429, 1429, 1429,
+ 6241, 6241, 6241, 6241, 6241, 6241, 2005, 2005, 2005, 2005, 2005, 2005, 1681, 1681, 1681, 1681, 1681, 1681, 1367, 1367, 1367, 1367, 1367, 1367, 1465, 1465, 1465, 1465, 1465, 1465,
+ 6262, 6262, 6262, 6262, 6262, 6262, 2041, 2041, 2041, 2041, 2041, 2041, 1717, 1717, 1717, 1717, 1717, 1717, 1403, 1403, 1403, 1403, 1403, 1403, 1501, 1501, 1501, 1501, 1501, 1501,
+ 1120, 1120, 1120, 1120, 1120, 1120, 1846, 1846, 1846, 1846, 1846, 1846, 1434, 1434, 1434, 1434, 1434, 1434, 1748, 1748, 1748, 1748, 1748, 1748, 1537, 1537, 1537, 1537, 1537, 1537,
+ 1156, 1156, 1156, 1156, 1156, 1156, 1882, 1882, 1882, 1882, 1882, 1882, 1470, 1470, 1470, 1470, 1470, 1470, 1784, 1784, 1784, 1784, 1784, 1784, 1573, 1573, 1573, 1573, 1573, 1573,
+ 1192, 1192, 1192, 1192, 1192, 1192, 1918, 1918, 1918, 1918, 1918, 1918, 1506, 1506, 1506, 1506, 1506, 1506, 1820, 1820, 1820, 1820, 1820, 1820, 1609, 1609, 1609, 1609, 1609, 1609,
+ 2072, 2072, 2072, 2072, 2072, 2072, 1311, 1311, 1311, 1311, 1311, 1311, 1660, 1660, 1660, 1660, 1660, 1660, 1090, 1090, 1090, 1090, 1090, 1090, 5291, 5291, 5291, 5291, 5291, 5291,
+ 2108, 2108, 2108, 2108, 2108, 2108, 1347, 1347, 1347, 1347, 1347, 1347, 1696, 1696, 1696, 1696, 1696, 1696, 1126, 1126, 1126, 1126, 1126, 1126, 5324, 5324, 5324, 5324, 5324, 5324,
+ 2144, 2144, 2144, 2144, 2144, 2144, 1383, 1383, 1383, 1383, 1383, 1383, 1732, 1732, 1732, 1732, 1732, 1732, 1162, 1162, 1162, 1162, 1162, 1162, 5357, 5357, 5357, 5357, 5357, 5357,
+ 1856, 1856, 1856, 1856, 1856, 1856, 1223, 1223, 1223, 1223, 1223, 1223, 1414, 1414, 1414, 1414, 1414, 1414, 2170, 2170, 2170, 2170, 2170, 2170, 1110, 1110, 1110, 1110, 1110, 1110,
+ 1892, 1892, 1892, 1892, 1892, 1892, 1259, 1259, 1259, 1259, 1259, 1259, 1450, 1450, 1450, 1450, 1450, 1450, 2170, 2170, 2170, 2170, 2170, 2170, 1146, 1146, 1146, 1146, 1146, 1146,
+ 1928, 1928, 1928, 1928, 1928, 1928, 1295, 1295, 1295, 1295, 1295, 1295, 1486, 1486, 1486, 1486, 1486, 1486, 2170, 2170, 2170, 2170, 2170, 2170, 1182, 1182, 1182, 1182, 1182, 1182],
+ "height":36,
+ "id":3,
+ "name":"wallpaper",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5009,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5029,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":36,
+ "id":5,
+ "name":"furniture1",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":36,
+ "id":9,
+ "name":"furniture2",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+ "height":36,
+ "id":6,
+ "name":"furniture3",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[761, 763, 763, 763, 763, 765, 563, 565, 565, 565, 565, 567, 761, 763, 763, 763, 763, 765, 167, 169, 169, 169, 169, 171, 266, 268, 268, 268, 268, 270,
+ 794, 0, 0, 0, 0, 797, 597, 0, 0, 0, 0, 599, 795, 0, 0, 0, 0, 797, 201, 0, 0, 0, 0, 203, 300, 0, 0, 0, 0, 303,
+ 827, 828, 828, 828, 828, 828, 630, 630, 630, 630, 630, 630, 828, 828, 828, 828, 828, 828, 234, 234, 234, 234, 234, 234, 333, 333, 333, 333, 333, 336,
+ 167, 169, 169, 169, 169, 171, 365, 367, 367, 367, 367, 369, 266, 268, 268, 268, 268, 270, 365, 367, 367, 367, 367, 369, 167, 169, 169, 169, 169, 171,
+ 200, 0, 0, 0, 0, 204, 398, 0, 0, 0, 0, 401, 300, 0, 0, 0, 0, 302, 399, 0, 0, 0, 0, 401, 201, 0, 0, 0, 0, 204,
+ 233, 234, 234, 234, 234, 237, 431, 432, 432, 432, 432, 432, 333, 333, 333, 333, 333, 333, 432, 432, 432, 432, 432, 432, 234, 234, 234, 234, 234, 237,
+ 365, 367, 367, 367, 367, 369, 662, 664, 664, 664, 664, 666, 563, 565, 565, 565, 565, 567, 761, 763, 763, 763, 763, 765, 563, 565, 565, 565, 565, 567,
+ 398, 0, 0, 0, 0, 401, 696, 0, 0, 0, 0, 699, 596, 0, 0, 0, 0, 599, 795, 0, 0, 0, 0, 798, 596, 0, 0, 0, 0, 600,
+ 431, 432, 432, 432, 432, 432, 729, 729, 729, 729, 729, 732, 629, 630, 630, 630, 630, 630, 828, 828, 828, 828, 828, 831, 629, 630, 630, 630, 630, 633,
+ 563, 565, 565, 565, 565, 567, 266, 268, 268, 268, 268, 270, 167, 169, 169, 169, 169, 171, 662, 664, 664, 664, 664, 666, 464, 466, 466, 466, 466, 468,
+ 596, 0, 0, 0, 0, 599, 300, 0, 0, 0, 0, 303, 200, 0, 0, 0, 0, 203, 696, 0, 0, 0, 0, 698, 498, 0, 0, 0, 0, 501,
+ 629, 630, 630, 630, 630, 630, 333, 333, 333, 333, 333, 336, 233, 234, 234, 234, 234, 234, 729, 729, 729, 729, 729, 729, 531, 531, 531, 531, 531, 534,
+ 464, 466, 466, 466, 466, 468, 563, 565, 565, 565, 565, 567, 662, 664, 664, 664, 664, 666, 761, 763, 763, 763, 763, 765, 365, 367, 367, 367, 367, 369,
+ 497, 0, 0, 0, 0, 500, 597, 0, 0, 0, 0, 599, 696, 0, 0, 0, 0, 698, 795, 0, 0, 0, 0, 798, 398, 0, 0, 0, 0, 402,
+ 530, 531, 531, 531, 531, 531, 630, 630, 630, 630, 630, 630, 729, 729, 729, 729, 729, 729, 828, 828, 828, 828, 828, 831, 431, 432, 432, 432, 432, 435,
+ 662, 664, 664, 664, 664, 666, 365, 367, 367, 367, 367, 369, 266, 268, 268, 268, 268, 270, 563, 565, 565, 565, 565, 567, 761, 763, 763, 763, 763, 765,
+ 695, 0, 0, 0, 0, 698, 399, 0, 0, 0, 0, 402, 299, 0, 0, 0, 0, 302, 597, 0, 0, 0, 0, 599, 795, 0, 0, 0, 0, 798,
+ 728, 729, 729, 729, 729, 729, 432, 432, 432, 432, 432, 435, 332, 333, 333, 333, 333, 333, 630, 630, 630, 630, 630, 630, 828, 828, 828, 828, 828, 831,
+ 563, 565, 565, 565, 565, 567, 464, 466, 466, 466, 466, 468, 662, 664, 664, 664, 664, 666, 761, 763, 763, 763, 763, 765, 266, 268, 268, 268, 268, 270,
+ 596, 0, 0, 0, 0, 599, 498, 0, 0, 0, 0, 500, 696, 0, 0, 0, 0, 698, 795, 0, 0, 0, 0, 798, 299, 0, 0, 0, 0, 303,
+ 629, 630, 630, 630, 630, 630, 531, 531, 531, 531, 531, 531, 729, 729, 729, 729, 729, 729, 828, 828, 828, 828, 828, 831, 332, 333, 333, 333, 333, 336,
+ 761, 763, 763, 763, 763, 765, 266, 268, 268, 268, 268, 270, 365, 367, 367, 367, 367, 369, 464, 466, 466, 466, 466, 468, 167, 169, 169, 169, 169, 171,
+ 794, 0, 0, 0, 0, 797, 300, 0, 0, 0, 0, 303, 398, 0, 0, 0, 0, 402, 497, 0, 0, 0, 0, 500, 201, 0, 0, 0, 0, 204,
+ 827, 828, 828, 828, 828, 828, 333, 333, 333, 333, 333, 336, 431, 432, 432, 432, 432, 435, 530, 531, 531, 531, 531, 531, 234, 234, 234, 234, 234, 237,
+ 266, 268, 268, 268, 268, 270, 464, 466, 466, 466, 466, 468, 563, 565, 565, 565, 565, 567, 662, 664, 664, 664, 664, 666, 365, 367, 367, 367, 367, 369,
+ 299, 0, 0, 0, 0, 302, 498, 0, 0, 0, 0, 500, 597, 0, 0, 0, 0, 600, 695, 0, 0, 0, 0, 699, 398, 0, 0, 0, 0, 402,
+ 332, 333, 333, 333, 333, 333, 531, 531, 531, 531, 531, 531, 630, 630, 630, 630, 630, 633, 728, 729, 729, 729, 729, 732, 431, 432, 432, 432, 432, 435,
+ 563, 565, 565, 565, 565, 567, 662, 664, 664, 664, 664, 666, 266, 268, 268, 268, 268, 270, 167, 169, 169, 169, 169, 171, 761, 763, 763, 763, 763, 765,
+ 596, 0, 0, 0, 0, 599, 696, 0, 0, 0, 0, 698, 300, 0, 0, 0, 0, 302, 201, 0, 0, 0, 0, 203, 795, 0, 0, 0, 0, 798,
+ 629, 630, 630, 630, 630, 630, 729, 729, 729, 729, 729, 729, 333, 333, 333, 333, 333, 333, 234, 234, 234, 234, 234, 234, 828, 828, 828, 828, 828, 831,
+ 365, 367, 367, 367, 367, 369, 563, 565, 565, 565, 565, 567, 761, 763, 763, 763, 763, 765, 266, 268, 268, 268, 268, 270, 167, 169, 169, 169, 169, 171,
+ 398, 0, 0, 0, 0, 401, 597, 0, 0, 0, 0, 599, 795, 0, 0, 0, 0, 798, 299, 0, 0, 0, 0, 302, 201, 0, 0, 0, 0, 204,
+ 431, 432, 432, 432, 432, 432, 630, 630, 630, 630, 630, 630, 828, 828, 828, 828, 828, 831, 332, 333, 333, 333, 333, 333, 234, 234, 234, 234, 234, 237,
+ 464, 466, 466, 466, 466, 468, 167, 169, 169, 169, 169, 171, 365, 367, 367, 367, 367, 369, 761, 763, 763, 763, 763, 765, 662, 664, 664, 664, 664, 666,
+ 497, 0, 0, 0, 0, 501, 200, 0, 0, 0, 0, 203, 399, 0, 0, 0, 0, 401, 795, 0, 0, 0, 0, 798, 695, 0, 0, 0, 0, 699,
+ 530, 531, 531, 531, 531, 534, 233, 234, 234, 234, 234, 234, 432, 432, 432, 432, 432, 432, 828, 828, 828, 828, 828, 831, 728, 729, 729, 729, 729, 732],
+ "height":36,
+ "id":1,
+ "name":"frame",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2350, 2351, 0, 0, 0, 0, 0, 0, 2422, 2423, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147483987, 2147483986, 0, 0, 0, 0, 0, 0, 0, 2386, 2387, 0, 0, 2147483987, 2147483986, 0, 0, 2458, 2459, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2147484021, 2147484020, 0, 0, 0, 371, 0, 0, 0, 0, 0, 0, 0, 2147484021, 2147484020, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2350, 2351, 0, 2147484055, 2147484054, 2147484053, 0, 0, 0, 0, 0, 0, 2422, 2423, 0, 0, 2147484021, 2147484054, 2147484053, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2386, 2387, 2147484089, 2147484088, 2147484053, 0, 0, 0, 0, 338, 339, 0, 2458, 2459, 0, 2147484089, 2147484088, 2147484053, 0, 0, 0, 0, 0, 2147483987, 2147483986, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484021, 2147484020, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2350, 2351, 0, 0, 405, 406, 407, 0, 0, 0, 2638, 2639, 0, 0, 0, 2147484055, 2147484054, 2147484053, 2422, 2423,
+ 0, 338, 339, 0, 0, 0, 0, 0, 0, 0, 2386, 2387, 0, 0, 0, 439, 440, 441, 338, 339, 2674, 2675, 0, 0, 2147484089, 2147484088, 2147484087, 0, 2458, 2459,
+ 0, 0, 372, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2638, 2639, 406, 407, 0, 0, 0, 0, 0, 2422, 2423, 0, 0, 0, 0, 0, 0, 2350, 2351, 406, 407, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 2674, 2675, 439, 440, 441, 0, 0, 0, 0, 2458, 2459, 0, 0, 0, 2147483987, 2147483986, 0, 2386, 2387, 439, 440, 441, 0, 0, 338, 339, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484021, 2147484020, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372, 373, 0, 0,
+ 2494, 2495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484055, 2147484054, 2147484053, 0, 0, 0, 0, 0, 0, 2350, 2351, 0, 0, 405, 406, 407, 0,
+ 2530, 2531, 0, 0, 0, 0, 0, 338, 339, 0, 0, 0, 2147484089, 2147484088, 2147484087, 0, 0, 0, 0, 0, 0, 0, 2386, 2387, 0, 0, 0, 439, 440, 441,
+ 0, 0, 0, 0, 0, 0, 0, 0, 372, 373, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 405, 406, 407, 0, 2422, 2423, 0, 0, 0, 0, 0, 0, 0, 0, 2638, 2639, 0, 0, 0, 0, 0, 0,
+ 0, 2147483990, 2147483989, 2147483988, 2147483987, 2147483986, 0, 0, 0, 439, 440, 441, 2458, 2459, 0, 0, 0, 0, 0, 0, 0, 0, 2674, 2675, 2147483990, 2147483989, 2147483988, 2147483987, 2147483986, 0,
+ 0, 2147484023, 2147484022, 2147484021, 2147484020, 2147484019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484023, 2147484022, 2147484021, 2147484020, 2147484019, 0,
+ 0, 2147484056, 2147484055, 2147484054, 2147484053, 2147484052, 0, 0, 2566, 2567, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2422, 2423, 2147484056, 2147484055, 2147484054, 2147484053, 2147484052, 0,
+ 0, 2147484089, 2147484088, 2147484087, 2147484086, 2147484085, 0, 0, 2602, 2603, 0, 0, 2147483990, 2147483989, 2147483988, 2147483987, 2147483986, 0, 0, 0, 0, 0, 2458, 2459, 2147484089, 2147484088, 2147484087, 2147484086, 2147484085, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484023, 2147484022, 2147484021, 2147484020, 2147484019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2494, 2495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484056, 2147484055, 2147484054, 2147484053, 2147484052, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2566, 2567, 0, 0,
+ 2530, 2531, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484089, 2147484088, 2147484087, 2147484086, 2147484085, 0, 0, 338, 339, 340, 341, 342, 0, 2147483990, 2602, 2603, 2147483987, 2147483986,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 371, 372, 373, 374, 375, 0, 2147484023, 2147484022, 2147484021, 2147484020, 2147484019,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2638, 2639, 2422, 2423, 405, 406, 407, 408, 0, 2147484056, 2147484055, 2147484054, 2147484053, 2147484052,
+ 0, 0, 0, 0, 0, 0, 0, 338, 339, 340, 341, 342, 0, 0, 0, 0, 2674, 2675, 2458, 2459, 438, 439, 440, 441, 0, 2147484089, 2147484088, 2147484087, 2147484086, 2147484085,
+ 0, 0, 0, 0, 0, 0, 0, 371, 372, 373, 374, 375, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2350, 2351, 0, 0, 0, 0, 0, 404, 405, 406, 407, 408, 0, 0, 0, 0, 2494, 2495, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2386, 2387, 2147483988, 2147483987, 2147483986, 0, 0, 437, 438, 439, 440, 441, 0, 0, 0, 0, 2530, 2531, 338, 339, 340, 341, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2147484023, 2147484022, 2147484021, 2147484020, 2147484019, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 371, 372, 373, 374, 375, 0, 0, 0, 0, 0, 0, 0,
+ 2147484056, 2147484055, 2147484054, 2147484053, 2147484052, 0, 0, 0, 0, 0, 2422, 2423, 0, 0, 0, 0, 0, 0, 404, 405, 406, 407, 408, 0, 0, 0, 0, 0, 2350, 2351,
+ 2147484089, 2147484088, 2147484087, 2147484086, 2147484085, 0, 0, 0, 0, 0, 2458, 2459, 0, 2147483990, 2147483989, 2147483988, 2147483987, 2147483986, 437, 438, 439, 440, 441, 0, 0, 338, 339, 340, 2386, 2387,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484023, 2147484022, 2147484021, 2147484020, 2147484019, 0, 0, 0, 0, 0, 0, 0, 371, 372, 373, 374, 375,
+ 2638, 2639, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484056, 2147484055, 2147484054, 2147484053, 2147484052, 0, 0, 0, 0, 0, 0, 0, 404, 405, 406, 407, 408,
+ 2674, 2675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2147484089, 2147484088, 2147484087, 2147484086, 2147484085, 0, 0, 0, 0, 0, 0, 0, 437, 438, 439, 440, 441],
+ "height":36,
+ "id":7,
+ "name":"transport",
+ "opacity":1,
+ "type":"tilelayer",
+ "visible":true,
+ "width":30,
+ "x":0,
+ "y":0
+ },
+ {
+ "draworder":"topdown",
+ "id":12,
+ "name":"points",
+ "objects":[
+ {
+ "height":48,
+ "id":19,
+ "name":"1b",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":48
+ },
+ {
+ "height":48,
+ "id":20,
+ "name":"2b",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":48
+ },
+ {
+ "height":48,
+ "id":21,
+ "name":"3b",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":48
+ },
+ {
+ "height":48,
+ "id":22,
+ "name":"3a",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":0
+ },
+ {
+ "height":48,
+ "id":29,
+ "name":"1a",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":0
+ },
+ {
+ "height":48,
+ "id":30,
+ "name":"2a",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":0
+ },
+ {
+ "height":48,
+ "id":39,
+ "name":"1c",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":96
+ },
+ {
+ "height":48,
+ "id":40,
+ "name":"2c",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":96
+ },
+ {
+ "height":48,
+ "id":41,
+ "name":"3c",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":96
+ },
+ {
+ "height":48,
+ "id":42,
+ "name":"1d",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":144
+ },
+ {
+ "height":48,
+ "id":44,
+ "name":"2d",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":144
+ },
+ {
+ "height":48,
+ "id":45,
+ "name":"3d",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":144
+ },
+ {
+ "height":48,
+ "id":46,
+ "name":"4d",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":144
+ },
+ {
+ "height":48,
+ "id":47,
+ "name":"4c",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":96
+ },
+ {
+ "height":48,
+ "id":48,
+ "name":"4b",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":48
+ },
+ {
+ "height":48,
+ "id":49,
+ "name":"4a",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":0
+ },
+ {
+ "height":48,
+ "id":51,
+ "name":"1e",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":192
+ },
+ {
+ "height":48,
+ "id":52,
+ "name":"2e",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":192
+ },
+ {
+ "height":48,
+ "id":53,
+ "name":"3e",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":192
+ },
+ {
+ "height":48,
+ "id":54,
+ "name":"4e",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":192
+ },
+ {
+ "height":48,
+ "id":55,
+ "name":"5b",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":48
+ },
+ {
+ "height":48,
+ "id":56,
+ "name":"5c",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":96
+ },
+ {
+ "height":48,
+ "id":58,
+ "name":"5a",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":0
+ },
+ {
+ "height":48,
+ "id":59,
+ "name":"5d",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":144
+ },
+ {
+ "height":48,
+ "id":60,
+ "name":"5e",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":192
+ },
+ {
+ "height":48,
+ "id":61,
+ "name":"1f",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":240
+ },
+ {
+ "height":48,
+ "id":62,
+ "name":"1g",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":288
+ },
+ {
+ "height":48,
+ "id":63,
+ "name":"1h",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":336
+ },
+ {
+ "height":48,
+ "id":64,
+ "name":"1i",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":384
+ },
+ {
+ "height":48,
+ "id":65,
+ "name":"1j",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":432
+ },
+
+ {
+ "height":48,
+ "id":66,
+ "name":"1k",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":480
+ },
+ {
+ "height":48,
+ "id":67,
+ "name":"1l",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":0,
+ "y":528
+ },
+ {
+ "height":48,
+ "id":68,
+ "name":"2f",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":240
+ },
+ {
+ "height":48,
+ "id":69,
+ "name":"3f",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":240
+ },
+ {
+ "height":48,
+ "id":70,
+ "name":"4f",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":240
+ },
+ {
+ "height":48,
+ "id":71,
+ "name":"5f",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":240
+ },
+ {
+ "height":48,
+ "id":72,
+ "name":"2g",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":288
+ },
+ {
+ "height":48,
+ "id":73,
+ "name":"3g",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":288
+ },
+ {
+ "height":48,
+ "id":74,
+ "name":"4g",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":288
+ },
+ {
+ "height":48,
+ "id":75,
+ "name":"5g",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":288
+ },
+ {
+ "height":48,
+ "id":76,
+ "name":"2h",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":336
+ },
+ {
+ "height":48,
+ "id":77,
+ "name":"3h",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":336
+ },
+ {
+ "height":48,
+ "id":78,
+ "name":"4h",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":336
+ },
+ {
+ "height":48,
+ "id":79,
+ "name":"5h",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":336
+ },
+ {
+ "height":48,
+ "id":80,
+ "name":"2i",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":384
+ },
+ {
+ "height":48,
+ "id":81,
+ "name":"3i",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":384
+ },
+ {
+ "height":48,
+ "id":82,
+ "name":"4i",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":384
+ },
+ {
+ "height":48,
+ "id":83,
+ "name":"5i",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":384
+ },
+ {
+ "height":48,
+ "id":84,
+ "name":"2j",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":432
+ },
+ {
+ "height":48,
+ "id":85,
+ "name":"3j",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":432
+ },
+ {
+ "height":48,
+ "id":86,
+ "name":"4j",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":432
+ },
+ {
+ "height":48,
+ "id":87,
+ "name":"5j",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":432
+ },
+ {
+ "height":48,
+ "id":88,
+ "name":"2k",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":480
+ },
+ {
+ "height":48,
+ "id":89,
+ "name":"3k",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":480
+ },
+ {
+ "height":48,
+ "id":90,
+ "name":"4k",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":480
+ },
+ {
+ "height":48,
+ "id":91,
+ "name":"5k",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":480
+ },
+ {
+ "height":48,
+ "id":92,
+ "name":"2l",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":96,
+ "y":528
+ },
+ {
+ "height":48,
+ "id":93,
+ "name":"3l",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":192,
+ "y":528
+ },
+ {
+ "height":48,
+ "id":94,
+ "name":"4l",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":288,
+ "y":528
+ },
+ {
+ "height":48,
+ "id":95,
+ "name":"5l",
+ "rotation":0,
+ "type":"",
+ "visible":true,
+ "width":96,
+ "x":384,
+ "y":528
+ }],
+ "opacity":1,
+ "type":"objectgroup",
+ "visible":true,
+ "x":0,
+ "y":0
+ }],
+ "nextlayerid":13,
+ "nextobjectid":96,
+ "orientation":"orthogonal",
+ "renderorder":"right-down",
+ "tiledversion":"1.11.0",
+ "tileheight":16,
+ "tilesets":[
+ {
+ "columns":33,
+ "firstgid":1,
+ "image":"..\/tilesets\/infrastructure.png",
+ "imageheight":528,
+ "imagewidth":528,
+ "margin":0,
+ "name":"infrastructure",
+ "spacing":0,
+ "tilecount":1089,
+ "tileheight":16,
+ "tiles":[
+ {
+ "id":200,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":202,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":299,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":301,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":337,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"top"
+ }]
+ },
+ {
+ "id":342,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"top"
+ }]
+ },
+ {
+ "id":347,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"top"
+ }]
+ },
+ {
+ "id":398,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":400,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":440,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"bottom"
+ }]
+ },
+ {
+ "id":445,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"bottom"
+ }]
+ },
+ {
+ "id":450,
+ "properties":[
+ {
+ "name":"staircase",
+ "type":"string",
+ "value":"bottom"
+ }]
+ },
+ {
+ "id":497,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":499,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":596,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":598,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":695,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":697,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ },
+ {
+ "id":794,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"left"
+ }]
+ },
+ {
+ "id":796,
+ "properties":[
+ {
+ "name":"door",
+ "type":"string",
+ "value":"right"
+ }]
+ }],
+ "tilewidth":16
+ },
+ {
+ "columns":36,
+ "firstgid":1090,
+ "image":"..\/tilesets\/wallpaper.png",
+ "imageheight":752,
+ "imagewidth":576,
+ "margin":0,
+ "name":"wallpaper",
+ "spacing":0,
+ "tilecount":1692,
+ "tileheight":16,
+ "tiles":[
+ {
+ "id":0,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":1,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":2,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":3,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":4,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":5,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":6,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":7,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":8,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":9,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":10,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":11,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":12,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":13,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":14,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":15,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":16,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":17,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":18,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":19,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":20,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":21,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":22,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":23,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":24,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":25,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":26,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":27,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":28,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":29,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+
+ {
+ "id":30,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":31,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":32,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":33,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":34,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":36,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":37,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":38,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":39,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":40,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":41,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":42,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":43,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":44,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":45,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":46,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":47,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":48,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":49,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":50,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":51,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":52,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":53,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":54,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":55,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":56,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":57,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":58,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":59,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":60,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+
+ {
+ "id":61,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":62,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":63,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":64,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":65,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":66,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":67,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":68,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":69,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":70,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":72,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":73,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":74,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":75,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":76,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":77,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":78,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":79,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":80,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":81,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":82,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":83,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":84,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":85,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":86,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":87,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":88,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":89,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":90,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":91,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+
+ {
+ "id":92,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":93,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":94,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":95,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":96,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":97,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":98,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":99,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":100,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":101,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":102,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":103,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":104,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":105,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":106,
+ "properties":[
+ {
+ "name":"color",
+ "type":"string",
+ "value":"red"
+ }]
+ },
+ {
+ "id":1260,
+ "properties":[
+ {
+ "name":"elevator",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":1332,
+ "properties":[
+ {
+ "name":"elevator",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":1404,
+ "properties":[
+ {
+ "name":"elevator",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":1476,
+ "properties":[
+ {
+ "name":"elevator",
+ "type":"bool",
+ "value":true
+ }]
+ },
+ {
+ "id":1548,
+ "properties":[
+ {
+ "name":"elevator",
+ "type":"bool",
+ "value":true
+ }]
+ }],
+ "tilewidth":16
+ },
+ {
+ "columns":42,
+ "firstgid":2782,
+ "image":"..\/tilesets\/furniture.png",
+ "imageheight":512,
+ "imagewidth":672,
+ "margin":0,
+ "name":"furniture",
+ "spacing":0,
+ "tilecount":1344,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":19,
+ "firstgid":4126,
+ "image":"..\/tilesets\/objects.png",
+ "imageheight":512,
+ "imagewidth":304,
+ "margin":0,
+ "name":"objects",
+ "spacing":0,
+ "tilecount":608,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":18,
+ "firstgid":4734,
+ "image":"..\/tilesets\/fire.png",
+ "imageheight":208,
+ "imagewidth":288,
+ "margin":0,
+ "name":"fire",
+ "spacing":0,
+ "tilecount":234,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":20,
+ "firstgid":4968,
+ "image":"..\/tilesets\/gamer.png",
+ "imageheight":192,
+ "imagewidth":320,
+ "margin":0,
+ "name":"gamer",
+ "spacing":0,
+ "tilecount":240,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":33,
+ "firstgid":5208,
+ "image":"..\/tilesets\/halloween.png",
+ "imageheight":256,
+ "imagewidth":528,
+ "margin":0,
+ "name":"halloween",
+ "spacing":0,
+ "tilecount":528,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":20,
+ "firstgid":5736,
+ "image":"..\/tilesets\/museum.png",
+ "imageheight":176,
+ "imagewidth":320,
+ "margin":0,
+ "name":"museum",
+ "spacing":0,
+ "tilecount":220,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":20,
+ "firstgid":5956,
+ "image":"..\/tilesets\/winter.png",
+ "imageheight":160,
+ "imagewidth":320,
+ "margin":0,
+ "name":"winter",
+ "spacing":0,
+ "tilecount":200,
+ "tileheight":16,
+ "tilewidth":16
+ },
+ {
+ "columns":21,
+ "firstgid":6156,
+ "image":"..\/tilesets\/police.png",
+ "imageheight":176,
+ "imagewidth":336,
+ "margin":0,
+ "name":"police",
+ "spacing":0,
+ "tilecount":231,
+ "tileheight":16,
+ "tilewidth":16
+ }],
+ "tilewidth":16,
+ "type":"map",
+ "version":"1.10",
+ "width":30
+}
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/buildings/1.tmx b/apps/games/hide-and-seek/public/assets/buildings/1.tmx
new file mode 100644
index 00000000..6492864a
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/buildings/1.tmx
@@ -0,0 +1,988 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1223,1223,1223,1223,1223,1223,1969,1969,1969,1969,1969,1969,1527,1527,1527,1527,1527,1527,1120,1120,1120,1120,1120,1120,4825,4825,4825,4825,4825,4825,
+1259,1259,1259,1259,1259,1259,2005,2005,2005,2005,2005,2005,1563,1563,1563,1563,1563,1563,1156,1156,1156,1156,1156,1156,4825,4825,4825,4825,4825,4825,
+1295,1295,1295,1295,1295,1295,2041,2041,2041,2041,2041,2041,1599,1599,1599,1599,1599,1599,1192,1192,1192,1192,1192,1192,4825,4825,4825,4825,4825,4825,
+1090,1090,1090,1090,1090,1090,1640,1640,1640,1640,1640,1640,1306,1306,1306,1306,1306,1306,1439,1439,1439,1439,1439,1439,2062,2062,2062,2062,2062,2062,
+1126,1126,1126,1126,1126,1126,1676,1676,1676,1676,1676,1676,1342,1342,1342,1342,1342,1342,1475,1475,1475,1475,1475,1475,2098,2098,2098,2098,2098,2098,
+1162,1162,1162,1162,1162,1162,1712,1712,1712,1712,1712,1712,1378,1378,1378,1378,1378,1378,1511,1511,1511,1511,1511,1511,2134,2134,2134,2134,2134,2134,
+2170,2170,2170,2170,2170,2170,1542,1542,1542,1542,1542,1542,5390,5390,5390,5390,5390,5390,1861,1861,1861,1861,1861,1861,1331,1331,1331,1331,1331,1331,
+2170,2170,2170,2170,2170,2170,1578,1578,1578,1578,1578,1578,5423,5423,5423,5423,5423,5423,1897,1897,1897,1897,1897,1897,1367,1367,1367,1367,1367,1367,
+2170,2170,2170,2170,2170,2170,1614,1614,1614,1614,1614,1614,5456,5456,5456,5456,5456,5456,1933,1933,1933,1933,1933,1933,1403,1403,1403,1403,1403,1403,
+1630,1630,1630,1630,1630,1630,1306,1306,1306,1306,1306,1306,1748,1748,1748,1748,1748,1748,1095,1095,1095,1095,1095,1095,1964,1964,1964,1964,1964,1964,
+1666,1666,1666,1666,1666,1666,1342,1342,1342,1342,1342,1342,1784,1784,1784,1784,1784,1784,1131,1131,1131,1131,1131,1131,2000,2000,2000,2000,2000,2000,
+1702,1702,1702,1702,1702,1702,1378,1378,1378,1378,1378,1378,1820,1820,1820,1820,1820,1820,1167,1167,1167,1167,1167,1167,2036,2036,2036,2036,2036,2036,
+1444,1444,1444,1444,1444,1444,5757,5757,5757,5758,5758,5758,1866,1866,1866,1866,1866,1866,1954,1954,1954,1954,1954,1954,1522,1522,1522,1522,1522,1522,
+1480,1480,1480,1480,1480,1480,5778,5778,5778,5778,5778,5778,1902,1902,1902,1902,1902,1902,1990,1990,1990,1990,1990,1990,1558,1558,1558,1558,1558,1558,
+1516,1516,1516,1516,1516,1516,5778,5778,5778,5778,5778,5778,1938,1938,1938,1938,1938,1938,2026,2026,2026,2026,2026,2026,1594,1594,1594,1594,1594,1594,
+4825,4825,4825,4825,4825,4825,1954,1954,1954,1954,1954,1954,1203,1203,1203,1203,1203,1203,1650,1650,1650,1650,1650,1650,1429,1429,1429,1429,1429,1429,
+4825,4825,4825,4825,4825,4825,1990,1990,1990,1990,1990,1990,1239,1239,1239,1239,1239,1239,1686,1686,1686,1686,1686,1686,1465,1465,1465,1465,1465,1465,
+4861,4861,4861,4861,4861,4861,2026,2026,2026,2026,2026,2026,1275,1275,1275,1275,1275,1275,1722,1722,1722,1722,1722,1722,1501,1501,1501,1501,1501,1501,
+1316,1316,1316,1316,1316,1316,1552,1552,1552,1552,1552,1552,1105,1105,1105,1105,1105,1105,1228,1228,1228,1228,1228,1228,1306,1306,1306,1306,1306,1306,
+1352,1352,1352,1352,1352,1352,1588,1588,1588,1588,1588,1588,1141,1141,1141,1141,1141,1141,1264,1264,1264,1264,1264,1264,1342,1342,1342,1342,1342,1342,
+1388,1388,1388,1388,1388,1388,1624,1624,1624,1624,1624,1624,1177,1177,1177,1177,1177,1177,1300,1300,1300,1300,1300,1300,1378,1378,1378,1378,1378,1378,
+1424,1424,1424,1424,1424,1424,1203,1203,1203,1203,1203,1203,2082,2082,2082,2082,2082,2082,1964,1964,1964,1964,1964,1964,1547,1547,1547,1547,1547,1547,
+1460,1460,1460,1460,1460,1460,1239,1239,1239,1239,1239,1239,2118,2118,2118,2118,2118,2118,2000,2000,2000,2000,2000,2000,1583,1583,1583,1583,1583,1583,
+1496,1496,1496,1496,1496,1496,1275,1275,1275,1275,1275,1275,2154,2154,2154,2154,2154,2154,2036,2036,2036,2036,2036,2036,1619,1619,1619,1619,1619,1619,
+6220,6220,6220,6220,6220,6220,1969,1969,1969,1969,1969,1969,1645,1645,1645,1645,1645,1645,1331,1331,1331,1331,1331,1331,1429,1429,1429,1429,1429,1429,
+6241,6241,6241,6241,6241,6241,2005,2005,2005,2005,2005,2005,1681,1681,1681,1681,1681,1681,1367,1367,1367,1367,1367,1367,1465,1465,1465,1465,1465,1465,
+6262,6262,6262,6262,6262,6262,2041,2041,2041,2041,2041,2041,1717,1717,1717,1717,1717,1717,1403,1403,1403,1403,1403,1403,1501,1501,1501,1501,1501,1501,
+1120,1120,1120,1120,1120,1120,1846,1846,1846,1846,1846,1846,1434,1434,1434,1434,1434,1434,1748,1748,1748,1748,1748,1748,1537,1537,1537,1537,1537,1537,
+1156,1156,1156,1156,1156,1156,1882,1882,1882,1882,1882,1882,1470,1470,1470,1470,1470,1470,1784,1784,1784,1784,1784,1784,1573,1573,1573,1573,1573,1573,
+1192,1192,1192,1192,1192,1192,1918,1918,1918,1918,1918,1918,1506,1506,1506,1506,1506,1506,1820,1820,1820,1820,1820,1820,1609,1609,1609,1609,1609,1609,
+2072,2072,2072,2072,2072,2072,1311,1311,1311,1311,1311,1311,1660,1660,1660,1660,1660,1660,1090,1090,1090,1090,1090,1090,5291,5291,5291,5291,5291,5291,
+2108,2108,2108,2108,2108,2108,1347,1347,1347,1347,1347,1347,1696,1696,1696,1696,1696,1696,1126,1126,1126,1126,1126,1126,5324,5324,5324,5324,5324,5324,
+2144,2144,2144,2144,2144,2144,1383,1383,1383,1383,1383,1383,1732,1732,1732,1732,1732,1732,1162,1162,1162,1162,1162,1162,5357,5357,5357,5357,5357,5357,
+1856,1856,1856,1856,1856,1856,1223,1223,1223,1223,1223,1223,1414,1414,1414,1414,1414,1414,2170,2170,2170,2170,2170,2170,1110,1110,1110,1110,1110,1110,
+1892,1892,1892,1892,1892,1892,1259,1259,1259,1259,1259,1259,1450,1450,1450,1450,1450,1450,2170,2170,2170,2170,2170,2170,1146,1146,1146,1146,1146,1146,
+1928,1928,1928,1928,1928,1928,1295,1295,1295,1295,1295,1295,1486,1486,1486,1486,1486,1486,2170,2170,2170,2170,2170,2170,1182,1182,1182,1182,1182,1182
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5009,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5029,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+761,763,763,763,763,765,563,565,565,565,565,567,761,763,763,763,763,765,167,169,169,169,169,171,266,268,268,268,268,270,
+794,0,0,0,0,797,597,0,0,0,0,599,795,0,0,0,0,797,201,0,0,0,0,203,300,0,0,0,0,303,
+827,828,828,828,828,828,630,630,630,630,630,630,828,828,828,828,828,828,234,234,234,234,234,234,333,333,333,333,333,336,
+167,169,169,169,169,171,365,367,367,367,367,369,266,268,268,268,268,270,365,367,367,367,367,369,167,169,169,169,169,171,
+200,0,0,0,0,204,398,0,0,0,0,401,300,0,0,0,0,302,399,0,0,0,0,401,201,0,0,0,0,204,
+233,234,234,234,234,237,431,432,432,432,432,432,333,333,333,333,333,333,432,432,432,432,432,432,234,234,234,234,234,237,
+365,367,367,367,367,369,662,664,664,664,664,666,563,565,565,565,565,567,761,763,763,763,763,765,563,565,565,565,565,567,
+398,0,0,0,0,401,696,0,0,0,0,699,596,0,0,0,0,599,795,0,0,0,0,798,596,0,0,0,0,600,
+431,432,432,432,432,432,729,729,729,729,729,732,629,630,630,630,630,630,828,828,828,828,828,831,629,630,630,630,630,633,
+563,565,565,565,565,567,266,268,268,268,268,270,167,169,169,169,169,171,662,664,664,664,664,666,464,466,466,466,466,468,
+596,0,0,0,0,599,300,0,0,0,0,303,200,0,0,0,0,203,696,0,0,0,0,698,498,0,0,0,0,501,
+629,630,630,630,630,630,333,333,333,333,333,336,233,234,234,234,234,234,729,729,729,729,729,729,531,531,531,531,531,534,
+464,466,466,466,466,468,563,565,565,565,565,567,662,664,664,664,664,666,761,763,763,763,763,765,365,367,367,367,367,369,
+497,0,0,0,0,500,597,0,0,0,0,599,696,0,0,0,0,698,795,0,0,0,0,798,398,0,0,0,0,402,
+530,531,531,531,531,531,630,630,630,630,630,630,729,729,729,729,729,729,828,828,828,828,828,831,431,432,432,432,432,435,
+662,664,664,664,664,666,365,367,367,367,367,369,266,268,268,268,268,270,563,565,565,565,565,567,761,763,763,763,763,765,
+695,0,0,0,0,698,399,0,0,0,0,402,299,0,0,0,0,302,597,0,0,0,0,599,795,0,0,0,0,798,
+728,729,729,729,729,729,432,432,432,432,432,435,332,333,333,333,333,333,630,630,630,630,630,630,828,828,828,828,828,831,
+563,565,565,565,565,567,464,466,466,466,466,468,662,664,664,664,664,666,761,763,763,763,763,765,266,268,268,268,268,270,
+596,0,0,0,0,599,498,0,0,0,0,500,696,0,0,0,0,698,795,0,0,0,0,798,299,0,0,0,0,303,
+629,630,630,630,630,630,531,531,531,531,531,531,729,729,729,729,729,729,828,828,828,828,828,831,332,333,333,333,333,336,
+761,763,763,763,763,765,266,268,268,268,268,270,365,367,367,367,367,369,464,466,466,466,466,468,167,169,169,169,169,171,
+794,0,0,0,0,797,300,0,0,0,0,303,398,0,0,0,0,402,497,0,0,0,0,500,201,0,0,0,0,204,
+827,828,828,828,828,828,333,333,333,333,333,336,431,432,432,432,432,435,530,531,531,531,531,531,234,234,234,234,234,237,
+266,268,268,268,268,270,464,466,466,466,466,468,563,565,565,565,565,567,662,664,664,664,664,666,365,367,367,367,367,369,
+299,0,0,0,0,302,498,0,0,0,0,500,597,0,0,0,0,600,695,0,0,0,0,699,398,0,0,0,0,402,
+332,333,333,333,333,333,531,531,531,531,531,531,630,630,630,630,630,633,728,729,729,729,729,732,431,432,432,432,432,435,
+563,565,565,565,565,567,662,664,664,664,664,666,266,268,268,268,268,270,167,169,169,169,169,171,761,763,763,763,763,765,
+596,0,0,0,0,599,696,0,0,0,0,698,300,0,0,0,0,302,201,0,0,0,0,203,795,0,0,0,0,798,
+629,630,630,630,630,630,729,729,729,729,729,729,333,333,333,333,333,333,234,234,234,234,234,234,828,828,828,828,828,831,
+365,367,367,367,367,369,563,565,565,565,565,567,761,763,763,763,763,765,266,268,268,268,268,270,167,169,169,169,169,171,
+398,0,0,0,0,401,597,0,0,0,0,599,795,0,0,0,0,798,299,0,0,0,0,302,201,0,0,0,0,204,
+431,432,432,432,432,432,630,630,630,630,630,630,828,828,828,828,828,831,332,333,333,333,333,333,234,234,234,234,234,237,
+464,466,466,466,466,468,167,169,169,169,169,171,365,367,367,367,367,369,761,763,763,763,763,765,662,664,664,664,664,666,
+497,0,0,0,0,501,200,0,0,0,0,203,399,0,0,0,0,401,795,0,0,0,0,798,695,0,0,0,0,699,
+530,531,531,531,531,534,233,234,234,234,234,234,432,432,432,432,432,432,828,828,828,828,828,831,728,729,729,729,729,732
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2350,2351,0,0,0,0,0,0,2422,2423,0,0,
+0,0,0,0,0,0,0,0,0,2147483987,2147483986,0,0,0,0,0,0,0,2386,2387,0,0,2147483987,2147483986,0,0,2458,2459,0,0,
+0,0,0,0,0,0,0,0,2147484021,2147484020,0,0,0,371,0,0,0,0,0,0,0,2147484021,2147484020,0,0,0,0,0,0,0,
+0,0,0,0,2350,2351,0,2147484055,2147484054,2147484053,0,0,0,0,0,0,2422,2423,0,0,2147484021,2147484054,2147484053,0,0,0,0,0,0,0,
+0,0,0,0,2386,2387,2147484089,2147484088,2147484053,0,0,0,0,338,339,0,2458,2459,0,2147484089,2147484088,2147484053,0,0,0,0,0,2147483987,2147483986,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,372,373,0,0,0,0,0,0,0,0,0,0,2147484021,2147484020,0,0,
+0,0,0,0,0,0,0,0,0,0,2350,2351,0,0,405,406,407,0,0,0,2638,2639,0,0,0,2147484055,2147484054,2147484053,2422,2423,
+0,338,339,0,0,0,0,0,0,0,2386,2387,0,0,0,439,440,441,338,339,2674,2675,0,0,2147484089,2147484088,2147484087,0,2458,2459,
+0,0,372,373,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,372,373,0,0,0,0,0,0,0,0,0,
+0,2638,2639,406,407,0,0,0,0,0,2422,2423,0,0,0,0,0,0,2350,2351,406,407,0,0,0,0,0,0,0,0,
+0,2674,2675,439,440,441,0,0,0,0,2458,2459,0,0,0,2147483987,2147483986,0,2386,2387,439,440,441,0,0,338,339,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147484021,2147484020,0,0,0,0,0,0,0,0,0,0,372,373,0,0,
+2494,2495,0,0,0,0,0,0,0,0,0,0,0,2147484055,2147484054,2147484053,0,0,0,0,0,0,2350,2351,0,0,405,406,407,0,
+2530,2531,0,0,0,0,0,338,339,0,0,0,2147484089,2147484088,2147484087,0,0,0,0,0,0,0,2386,2387,0,0,0,439,440,441,
+0,0,0,0,0,0,0,0,372,373,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,405,406,407,0,2422,2423,0,0,0,0,0,0,0,0,2638,2639,0,0,0,0,0,0,
+0,2147483990,2147483989,2147483988,2147483987,2147483986,0,0,0,439,440,441,2458,2459,0,0,0,0,0,0,0,0,2674,2675,2147483990,2147483989,2147483988,2147483987,2147483986,0,
+0,2147484023,2147484022,2147484021,2147484020,2147484019,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2147484023,2147484022,2147484021,2147484020,2147484019,0,
+0,2147484056,2147484055,2147484054,2147484053,2147484052,0,0,2566,2567,0,0,0,0,0,0,0,0,0,0,0,0,2422,2423,2147484056,2147484055,2147484054,2147484053,2147484052,0,
+0,2147484089,2147484088,2147484087,2147484086,2147484085,0,0,2602,2603,0,0,2147483990,2147483989,2147483988,2147483987,2147483986,0,0,0,0,0,2458,2459,2147484089,2147484088,2147484087,2147484086,2147484085,0,
+0,0,0,0,0,0,0,0,0,0,0,0,2147484023,2147484022,2147484021,2147484020,2147484019,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2494,2495,0,0,0,0,0,0,0,0,0,0,2147484056,2147484055,2147484054,2147484053,2147484052,0,0,0,0,0,0,0,0,0,2566,2567,0,0,
+2530,2531,0,0,0,0,0,0,0,0,0,0,2147484089,2147484088,2147484087,2147484086,2147484085,0,0,338,339,340,341,342,0,2147483990,2602,2603,2147483987,2147483986,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,371,372,373,374,375,0,2147484023,2147484022,2147484021,2147484020,2147484019,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2638,2639,2422,2423,405,406,407,408,0,2147484056,2147484055,2147484054,2147484053,2147484052,
+0,0,0,0,0,0,0,338,339,340,341,342,0,0,0,0,2674,2675,2458,2459,438,439,440,441,0,2147484089,2147484088,2147484087,2147484086,2147484085,
+0,0,0,0,0,0,0,371,372,373,374,375,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+2350,2351,0,0,0,0,0,404,405,406,407,408,0,0,0,0,2494,2495,0,0,0,0,0,0,0,0,0,0,0,0,
+2386,2387,2147483988,2147483987,2147483986,0,0,437,438,439,440,441,0,0,0,0,2530,2531,338,339,340,341,0,0,0,0,0,0,0,0,
+2147484023,2147484022,2147484021,2147484020,2147484019,0,0,0,0,0,0,0,0,0,0,0,0,0,371,372,373,374,375,0,0,0,0,0,0,0,
+2147484056,2147484055,2147484054,2147484053,2147484052,0,0,0,0,0,2422,2423,0,0,0,0,0,0,404,405,406,407,408,0,0,0,0,0,2350,2351,
+2147484089,2147484088,2147484087,2147484086,2147484085,0,0,0,0,0,2458,2459,0,2147483990,2147483989,2147483988,2147483987,2147483986,437,438,439,440,441,0,0,338,339,340,2386,2387,
+0,0,0,0,0,0,0,0,0,0,0,0,0,2147484023,2147484022,2147484021,2147484020,2147484019,0,0,0,0,0,0,0,371,372,373,374,375,
+2638,2639,0,0,0,0,0,0,0,0,0,0,0,2147484056,2147484055,2147484054,2147484053,2147484052,0,0,0,0,0,0,0,404,405,406,407,408,
+2674,2675,0,0,0,0,0,0,0,0,0,0,0,2147484089,2147484088,2147484087,2147484086,2147484085,0,0,0,0,0,0,0,437,438,439,440,441
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/games/hide-and-seek/public/assets/charity_games.png b/apps/games/hide-and-seek/public/assets/charity_games.png
new file mode 100644
index 00000000..11277cda
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/charity_games.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/9x13.ttf b/apps/games/hide-and-seek/public/assets/fonts/9x13.ttf
new file mode 100644
index 00000000..219bdaef
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/9x13.ttf differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.png b/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.png
new file mode 100644
index 00000000..2c60c5c3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.xml b/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.xml
new file mode 100644
index 00000000..0d79f7f0
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/fonts/peaberry_blue.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.png b/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.png
new file mode 100644
index 00000000..edde7ff9
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.xml b/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.xml
new file mode 100644
index 00000000..51bf179c
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/fonts/peaberry_red.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.png b/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.png
new file mode 100644
index 00000000..a13fed9b
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.xml b/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.xml
new file mode 100644
index 00000000..4938ce51
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/fonts/peaberry_yellow.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/fonts/pixel.png b/apps/games/hide-and-seek/public/assets/fonts/pixel.png
new file mode 100644
index 00000000..9c36b8a4
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/pixel.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/pixel.xml b/apps/games/hide-and-seek/public/assets/fonts/pixel.xml
new file mode 100644
index 00000000..4a73e507
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/fonts/pixel.xml
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/fonts/thick.png b/apps/games/hide-and-seek/public/assets/fonts/thick.png
new file mode 100644
index 00000000..8f5fd09f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/fonts/thick.png differ
diff --git a/apps/games/hide-and-seek/public/assets/fonts/thick.xml b/apps/games/hide-and-seek/public/assets/fonts/thick.xml
new file mode 100644
index 00000000..78f80c84
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/fonts/thick.xml
@@ -0,0 +1,276 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/public/assets/project.tiled-session b/apps/games/hide-and-seek/public/assets/project.tiled-session
new file mode 100644
index 00000000..974e83d9
--- /dev/null
+++ b/apps/games/hide-and-seek/public/assets/project.tiled-session
@@ -0,0 +1,293 @@
+{
+ "Map/SizeTest": {
+ "height": 4300,
+ "width": 2
+ },
+ "activeFile": "buildings/1.tmx",
+ "expandedProjectPaths": [
+ "."
+ ],
+ "file.lastUsedOpenFilter": "All Files (*)",
+ "fileStates": {
+ "": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "#UI_spritesheet": {
+ "scaleInDock": 1.572
+ },
+ "#furniture": {
+ "scaleInDock": 1
+ },
+ "#infrastructure": {
+ "scaleInDock": 1
+ },
+ "#objects": {
+ "scaleInDock": 1
+ },
+ "#wallpaper": {
+ "scaleInDock": 1
+ },
+ "buildings/1.tmx": {
+ "expandedObjectLayers": [
+ 12
+ ],
+ "scale": 3.2485,
+ "selectedLayer": 0,
+ "viewCenter": {
+ "x": 354.62521163613985,
+ "y": 184.08496229028785
+ }
+ },
+ "buildings/1.tmx#fire": {
+ "scaleInDock": 3,
+ "scaleInEditor": 1
+ },
+ "buildings/1.tmx#fire-station": {
+ "scaleInEditor": 1
+ },
+ "buildings/1.tmx#furniture": {
+ "scaleInDock": 3,
+ "scaleInEditor": 1
+ },
+ "buildings/1.tmx#gamer": {
+ "scaleInDock": 3,
+ "scaleInEditor": 1
+ },
+ "buildings/1.tmx#halloween": {
+ "scaleInDock": 3
+ },
+ "buildings/1.tmx#infrastructure": {
+ "scaleInDock": 3,
+ "scaleInEditor": 2.41
+ },
+ "buildings/1.tmx#museum": {
+ "scaleInDock": 3
+ },
+ "buildings/1.tmx#objects": {
+ "scaleInDock": 3
+ },
+ "buildings/1.tmx#police": {
+ "scaleInDock": 3
+ },
+ "buildings/1.tmx#wallpaper": {
+ "scaleInDock": 3,
+ "scaleInEditor": 1.44
+ },
+ "buildings/1.tmx#winter": {
+ "scaleInDock": 3
+ },
+ "infrastructure.tsj": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "infrastructure.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "room.tmx": {
+ "scale": 1.764,
+ "selectedLayer": 0,
+ "viewCenter": {
+ "x": -25.793650793650812,
+ "y": 89.56916099773241
+ }
+ },
+ "room.tmx#infrastructure": {
+ "scaleInDock": 1
+ },
+ "room1.json": {
+ "scale": 9.89,
+ "selectedLayer": 0,
+ "viewCenter": {
+ "x": 48.02831142568251,
+ "y": 23.963599595551067
+ }
+ },
+ "room1.json#infrastructure": {
+ "scaleInDock": 1
+ },
+ "room1.tmx": {
+ "expandedGroupLayers": [
+ 4
+ ],
+ "scale": 4.85,
+ "selectedLayer": 1,
+ "viewCenter": {
+ "x": 66.18556701030928,
+ "y": 56.90721649484537
+ }
+ },
+ "room1.tmx#furniture": {
+ "scaleInDock": 3
+ },
+ "room1.tmx#infrastructure": {
+ "scaleInDock": 1.3933
+ },
+ "room1.tmx#objects": {
+ "scaleInDock": 3
+ },
+ "room1.tmx#wallpaper": {
+ "scaleInDock": 3
+ },
+ "room2.tmx": {
+ "scale": 6.2918,
+ "selectedLayer": 2,
+ "viewCenter": {
+ "x": 40.21106837470994,
+ "y": 31.15165771321402
+ }
+ },
+ "room2.tmx#furniture": {
+ "scaleInDock": 1.8059
+ },
+ "room2.tmx#infrastructure": {
+ "scaleInDock": 1.5519
+ },
+ "room2.tmx#objects": {
+ "scaleInDock": 3.8963
+ },
+ "room2.tmx#wallpaper": {
+ "scaleInDock": 2.287
+ },
+ "rooms/1.tmx": {
+ "scale": 8.35,
+ "selectedLayer": 1,
+ "viewCenter": {
+ "x": 45.449101796407184,
+ "y": 51.73652694610779
+ }
+ },
+ "rooms/1.tmx#furniture": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/1.tmx#infrastructure": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/1.tmx#objects": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/1.tmx#wallpaper": {
+ "scaleInDock": 1.1721,
+ "scaleInEditor": 1
+ },
+ "rooms/2.tmx": {
+ "scale": 7.58,
+ "selectedLayer": 5,
+ "viewCenter": {
+ "x": 54.68337730870712,
+ "y": 43.53562005277045
+ }
+ },
+ "rooms/2.tmx#furniture": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/2.tmx#infrastructure": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/2.tmx#objects": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/2.tmx#wallpaper": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "rooms/3.tmx": {
+ "scale": 4.0199,
+ "selectedLayer": 4,
+ "viewCenter": {
+ "x": 29.602726435981012,
+ "y": 85.32550560959228
+ }
+ },
+ "rooms/3.tmx#furniture": {
+ "scaleInDock": 1.9199
+ },
+ "rooms/3.tmx#infrastructure": {
+ "scaleInDock": 2.3697,
+ "scaleInEditor": 4.62
+ },
+ "rooms/3.tmx#objects": {
+ "scaleInDock": 1.9297
+ },
+ "rooms/3.tmx#wallpaper": {
+ "scaleInDock": 1.3468
+ },
+ "rooms/4.tmx": {
+ "scale": 4.38,
+ "selectedLayer": 3,
+ "viewCenter": {
+ "x": 37.10045662100457,
+ "y": -8.904109589041099
+ }
+ },
+ "tilesets/furniture.tsx": {
+ "scaleInDock": 1.5513,
+ "scaleInEditor": 1.03
+ },
+ "tilesets/gamer.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ },
+ "tilesets/infrastructure.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1.03
+ },
+ "tilesets/objects.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1.03
+ },
+ "tilesets/police.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 2.8
+ },
+ "tilesets/wallpaper.tsx": {
+ "scaleInDock": 1.7543,
+ "scaleInEditor": 1.03
+ },
+ "wallpaper.tsx": {
+ "scaleInDock": 1,
+ "scaleInEditor": 1
+ }
+ },
+ "last.exportedFilePath": "/Users/miguelcampos/src/worksheets/apps/games/hide-and-seek/public/assets/buildings",
+ "last.imagePath": "/Users/miguelcampos/Downloads/PixelSpaces Full Pack/UI",
+ "map.fixedSize": true,
+ "map.height": 6,
+ "map.lastUsedExportFilter": "JSON map files (*.tmj *.json)",
+ "map.lastUsedFormat": "tmx",
+ "map.tileHeight": 16,
+ "map.tileWidth": 16,
+ "map.width": 6,
+ "openFiles": [
+ "buildings/1.tmx"
+ ],
+ "project": "project.tiled-project",
+ "property.type": "string",
+ "recentFiles": [
+ "buildings/1.tmx",
+ "tilesets/police.tsx",
+ "tilesets/gamer.tsx",
+ "rooms/3.tmx",
+ "rooms/2.tmx",
+ "tilesets/wallpaper.tsx",
+ "tilesets/furniture.tsx",
+ "tilesets/objects.tsx",
+ "tilesets/infrastructure.tsx",
+ "rooms/4.tmx",
+ "room1.tmx",
+ "room2.tmx"
+ ],
+ "tileset.embedInMap": true,
+ "tileset.lastUsedFormat": "tsx",
+ "tileset.tileSize": {
+ "height": 16,
+ "width": 16
+ }
+}
diff --git a/apps/games/hide-and-seek/public/assets/sounds/menu.mp3 b/apps/games/hide-and-seek/public/assets/sounds/menu.mp3
new file mode 100644
index 00000000..eee0f1d5
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/sounds/menu.mp3 differ
diff --git a/apps/games/hide-and-seek/public/assets/sounds/right.mp3 b/apps/games/hide-and-seek/public/assets/sounds/right.mp3
new file mode 100644
index 00000000..340d6164
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/sounds/right.mp3 differ
diff --git a/apps/games/hide-and-seek/public/assets/sounds/wrong.mp3 b/apps/games/hide-and-seek/public/assets/sounds/wrong.mp3
new file mode 100644
index 00000000..3c86353f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/sounds/wrong.mp3 differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/door.png b/apps/games/hide-and-seek/public/assets/spritesheets/door.png
new file mode 100644
index 00000000..d7cac152
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/door.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/elevator.png b/apps/games/hide-and-seek/public/assets/spritesheets/elevator.png
new file mode 100644
index 00000000..6fc15c54
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/elevator.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/emotes.png b/apps/games/hide-and-seek/public/assets/spritesheets/emotes.png
new file mode 100644
index 00000000..374e2299
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/emotes.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_1.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_1.png
new file mode 100644
index 00000000..5fb4469d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_1.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_10.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_10.png
new file mode 100644
index 00000000..da27fb0f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_10.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_11.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_11.png
new file mode 100644
index 00000000..b41e51fb
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_11.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_12.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_12.png
new file mode 100644
index 00000000..a1861a68
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_12.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_13.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_13.png
new file mode 100644
index 00000000..3b906598
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_13.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_14.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_14.png
new file mode 100644
index 00000000..b4e85b9f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_14.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_15.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_15.png
new file mode 100644
index 00000000..caa594b3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_15.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_16.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_16.png
new file mode 100644
index 00000000..5dd6ae33
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_16.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_17.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_17.png
new file mode 100644
index 00000000..f824a527
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_17.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_18.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_18.png
new file mode 100644
index 00000000..d1603599
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_18.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_19.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_19.png
new file mode 100644
index 00000000..4715afa1
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_19.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_2.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_2.png
new file mode 100644
index 00000000..952ceba5
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_2.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_20.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_20.png
new file mode 100644
index 00000000..da416267
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_20.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_21.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_21.png
new file mode 100644
index 00000000..46931383
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_21.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_22.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_22.png
new file mode 100644
index 00000000..17614a37
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_22.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_3.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_3.png
new file mode 100644
index 00000000..6f647d08
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_3.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_4.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_4.png
new file mode 100644
index 00000000..01111e34
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_4.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_5.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_5.png
new file mode 100644
index 00000000..8115b7f3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_5.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_6.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_6.png
new file mode 100644
index 00000000..feddac52
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_6.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_7.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_7.png
new file mode 100644
index 00000000..b933d314
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_7.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_8.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_8.png
new file mode 100644
index 00000000..820571ae
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_8.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_9.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_9.png
new file mode 100644
index 00000000..70637f50
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/female_9.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_1.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_1.png
new file mode 100644
index 00000000..7f2acef5
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_1.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_10.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_10.png
new file mode 100644
index 00000000..a408cf6d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_10.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_11.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_11.png
new file mode 100644
index 00000000..85487c00
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_11.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_12.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_12.png
new file mode 100644
index 00000000..f8a9e42e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_12.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_13.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_13.png
new file mode 100644
index 00000000..55842af3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_13.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_14.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_14.png
new file mode 100644
index 00000000..c86bb2ef
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_14.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_15.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_15.png
new file mode 100644
index 00000000..d4265f82
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_15.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_16.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_16.png
new file mode 100644
index 00000000..6a9fd9f2
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_16.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_17.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_17.png
new file mode 100644
index 00000000..480ded8b
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_17.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_18.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_18.png
new file mode 100644
index 00000000..c21b4b56
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_18.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_19.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_19.png
new file mode 100644
index 00000000..c252bf89
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_19.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_2.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_2.png
new file mode 100644
index 00000000..49528cda
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_2.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_20.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_20.png
new file mode 100644
index 00000000..23ade16e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_20.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_21.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_21.png
new file mode 100644
index 00000000..1bbd5870
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_21.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_22.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_22.png
new file mode 100644
index 00000000..fedac52d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_22.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_3.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_3.png
new file mode 100644
index 00000000..7cb625eb
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_3.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_4.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_4.png
new file mode 100644
index 00000000..35866918
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_4.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_5.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_5.png
new file mode 100644
index 00000000..e62c5049
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_5.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_6.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_6.png
new file mode 100644
index 00000000..2ee14128
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_6.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_7.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_7.png
new file mode 100644
index 00000000..8041bc5e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_7.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_8.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_8.png
new file mode 100644
index 00000000..5cf2f69b
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_8.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_9.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_9.png
new file mode 100644
index 00000000..697bedd2
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/male_9.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_1.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_1.png
new file mode 100644
index 00000000..fc817735
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_1.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_10.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_10.png
new file mode 100644
index 00000000..32ef9c14
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_10.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_11.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_11.png
new file mode 100644
index 00000000..afd9d1fb
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_11.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_2.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_2.png
new file mode 100644
index 00000000..40eaff2d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_2.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_3.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_3.png
new file mode 100644
index 00000000..a0186622
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_3.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_4.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_4.png
new file mode 100644
index 00000000..bca51ecc
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_4.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_5.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_5.png
new file mode 100644
index 00000000..5479cca0
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_5.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_6.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_6.png
new file mode 100644
index 00000000..854488d5
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_6.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_7.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_7.png
new file mode 100644
index 00000000..047d005d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_7.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_8.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_8.png
new file mode 100644
index 00000000..4127636e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_8.png differ
diff --git a/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_9.png b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_9.png
new file mode 100644
index 00000000..1f7fc2ba
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/spritesheets/npc/special_9.png differ
diff --git a/apps/games/hide-and-seek/public/assets/thumbnail.png b/apps/games/hide-and-seek/public/assets/thumbnail.png
new file mode 100644
index 00000000..3c1b4609
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/thumbnail.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/backgrounds.png b/apps/games/hide-and-seek/public/assets/tilesets/backgrounds.png
new file mode 100644
index 00000000..9b5f46c0
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/backgrounds.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/fire.png b/apps/games/hide-and-seek/public/assets/tilesets/fire.png
new file mode 100644
index 00000000..6eb391b9
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/fire.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/furniture.png b/apps/games/hide-and-seek/public/assets/tilesets/furniture.png
new file mode 100644
index 00000000..126b24ed
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/furniture.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/gamer.png b/apps/games/hide-and-seek/public/assets/tilesets/gamer.png
new file mode 100644
index 00000000..d5466119
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/gamer.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/halloween.png b/apps/games/hide-and-seek/public/assets/tilesets/halloween.png
new file mode 100644
index 00000000..4b924a64
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/halloween.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/infrastructure.png b/apps/games/hide-and-seek/public/assets/tilesets/infrastructure.png
new file mode 100644
index 00000000..5a375354
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/infrastructure.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/museum.png b/apps/games/hide-and-seek/public/assets/tilesets/museum.png
new file mode 100644
index 00000000..0d22cad2
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/museum.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/objects.png b/apps/games/hide-and-seek/public/assets/tilesets/objects.png
new file mode 100644
index 00000000..b73846ab
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/objects.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/police.png b/apps/games/hide-and-seek/public/assets/tilesets/police.png
new file mode 100644
index 00000000..5286804b
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/police.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/wallpaper.png b/apps/games/hide-and-seek/public/assets/tilesets/wallpaper.png
new file mode 100644
index 00000000..9fb5533d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/wallpaper.png differ
diff --git a/apps/games/hide-and-seek/public/assets/tilesets/winter.png b/apps/games/hide-and-seek/public/assets/tilesets/winter.png
new file mode 100644
index 00000000..12cc0105
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/tilesets/winter.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/arrow_down.png b/apps/games/hide-and-seek/public/assets/ui/arrow_down.png
new file mode 100644
index 00000000..525cc9fb
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/arrow_down.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/arrow_left.png b/apps/games/hide-and-seek/public/assets/ui/arrow_left.png
new file mode 100644
index 00000000..2c682ff1
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/arrow_left.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/arrow_right.png b/apps/games/hide-and-seek/public/assets/ui/arrow_right.png
new file mode 100644
index 00000000..5180e545
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/arrow_right.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/arrow_up.png b/apps/games/hide-and-seek/public/assets/ui/arrow_up.png
new file mode 100644
index 00000000..faee0067
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/arrow_up.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/back.png b/apps/games/hide-and-seek/public/assets/ui/back.png
new file mode 100644
index 00000000..e67f296d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/back.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/button_blue_long.png b/apps/games/hide-and-seek/public/assets/ui/button_blue_long.png
new file mode 100644
index 00000000..6c07b280
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/button_blue_long.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/button_grey.png b/apps/games/hide-and-seek/public/assets/ui/button_grey.png
new file mode 100644
index 00000000..53ac9b9d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/button_grey.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/button_grey_long.png b/apps/games/hide-and-seek/public/assets/ui/button_grey_long.png
new file mode 100644
index 00000000..f298b1b2
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/button_grey_long.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/button_white.png b/apps/games/hide-and-seek/public/assets/ui/button_white.png
new file mode 100644
index 00000000..b62b91b1
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/button_white.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/chat.png b/apps/games/hide-and-seek/public/assets/ui/chat.png
new file mode 100644
index 00000000..e1e31a8a
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/chat.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/check.png b/apps/games/hide-and-seek/public/assets/ui/check.png
new file mode 100644
index 00000000..058a84cd
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/check.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/close.png b/apps/games/hide-and-seek/public/assets/ui/close.png
new file mode 100644
index 00000000..0d98ecec
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/close.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/comfort.png b/apps/games/hide-and-seek/public/assets/ui/comfort.png
new file mode 100644
index 00000000..93103ded
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/comfort.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/continue.png b/apps/games/hide-and-seek/public/assets/ui/continue.png
new file mode 100644
index 00000000..347b1be3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/continue.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/cross.png b/apps/games/hide-and-seek/public/assets/ui/cross.png
new file mode 100644
index 00000000..b621f8bf
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/cross.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/exit.png b/apps/games/hide-and-seek/public/assets/ui/exit.png
new file mode 100644
index 00000000..5fe34c63
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/exit.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/frame_blue.png b/apps/games/hide-and-seek/public/assets/ui/frame_blue.png
new file mode 100644
index 00000000..5d7b03c1
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/frame_blue.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/frame_blue_transparent.png b/apps/games/hide-and-seek/public/assets/ui/frame_blue_transparent.png
new file mode 100644
index 00000000..9c27789f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/frame_blue_transparent.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/frame_white.png b/apps/games/hide-and-seek/public/assets/ui/frame_white.png
new file mode 100644
index 00000000..465a754b
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/frame_white.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/frame_white_golden.png b/apps/games/hide-and-seek/public/assets/ui/frame_white_golden.png
new file mode 100644
index 00000000..7d5843ad
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/frame_white_golden.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/gear.png b/apps/games/hide-and-seek/public/assets/ui/gear.png
new file mode 100644
index 00000000..3b5897c6
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/gear.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/gift.png b/apps/games/hide-and-seek/public/assets/ui/gift.png
new file mode 100644
index 00000000..dcf2b83d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/gift.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/minus.png b/apps/games/hide-and-seek/public/assets/ui/minus.png
new file mode 100644
index 00000000..d065d3a9
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/minus.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/package.png b/apps/games/hide-and-seek/public/assets/ui/package.png
new file mode 100644
index 00000000..5d220baa
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/package.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/panel_blue.png b/apps/games/hide-and-seek/public/assets/ui/panel_blue.png
new file mode 100644
index 00000000..ade65737
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/panel_blue.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/panel_blue_background.png b/apps/games/hide-and-seek/public/assets/ui/panel_blue_background.png
new file mode 100644
index 00000000..1c7f546f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/panel_blue_background.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/panel_blue_tab.png b/apps/games/hide-and-seek/public/assets/ui/panel_blue_tab.png
new file mode 100644
index 00000000..80eb7fa1
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/panel_blue_tab.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/panel_grey_gradient.png b/apps/games/hide-and-seek/public/assets/ui/panel_grey_gradient.png
new file mode 100644
index 00000000..735f6dfb
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/panel_grey_gradient.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/panel_white.png b/apps/games/hide-and-seek/public/assets/ui/panel_white.png
new file mode 100644
index 00000000..06e7f122
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/panel_white.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/plus.png b/apps/games/hide-and-seek/public/assets/ui/plus.png
new file mode 100644
index 00000000..f735f927
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/plus.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/pointer_blue.png b/apps/games/hide-and-seek/public/assets/ui/pointer_blue.png
new file mode 100644
index 00000000..20db44b3
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/pointer_blue.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/pointer_green.png b/apps/games/hide-and-seek/public/assets/ui/pointer_green.png
new file mode 100644
index 00000000..ebcc6be0
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/pointer_green.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/pointer_red.png b/apps/games/hide-and-seek/public/assets/ui/pointer_red.png
new file mode 100644
index 00000000..9bb34f52
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/pointer_red.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/pointer_yellow.png b/apps/games/hide-and-seek/public/assets/ui/pointer_yellow.png
new file mode 100644
index 00000000..c73ed248
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/pointer_yellow.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/population.png b/apps/games/hide-and-seek/public/assets/ui/population.png
new file mode 100644
index 00000000..ad78eff5
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/population.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_1.png b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_1.png
new file mode 100644
index 00000000..97944b95
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_1.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_2.png b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_2.png
new file mode 100644
index 00000000..10a49175
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_2.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_3.png b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_3.png
new file mode 100644
index 00000000..3c728d8e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_3.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_4.png b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_4.png
new file mode 100644
index 00000000..84746b62
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_4.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_5.png b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_5.png
new file mode 100644
index 00000000..60b80192
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/progress_bar_blue_5.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/properties.png b/apps/games/hide-and-seek/public/assets/ui/properties.png
new file mode 100644
index 00000000..f3215f3f
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/properties.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/siren.png b/apps/games/hide-and-seek/public/assets/ui/siren.png
new file mode 100644
index 00000000..4569d21e
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/siren.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/speaker_off.png b/apps/games/hide-and-seek/public/assets/ui/speaker_off.png
new file mode 100644
index 00000000..02fb3f7d
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/speaker_off.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/speaker_on.png b/apps/games/hide-and-seek/public/assets/ui/speaker_on.png
new file mode 100644
index 00000000..a3cc4289
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/speaker_on.png differ
diff --git a/apps/games/hide-and-seek/public/assets/ui/tasks.png b/apps/games/hide-and-seek/public/assets/ui/tasks.png
new file mode 100644
index 00000000..35791565
Binary files /dev/null and b/apps/games/hide-and-seek/public/assets/ui/tasks.png differ
diff --git a/apps/games/hide-and-seek/public/favicon.ico b/apps/games/hide-and-seek/public/favicon.ico
new file mode 100644
index 00000000..317ebcb2
Binary files /dev/null and b/apps/games/hide-and-seek/public/favicon.ico differ
diff --git a/apps/games/hide-and-seek/public/pixel-spaces-license.txt b/apps/games/hide-and-seek/public/pixel-spaces-license.txt
new file mode 100644
index 00000000..9a1d8a20
--- /dev/null
+++ b/apps/games/hide-and-seek/public/pixel-spaces-license.txt
@@ -0,0 +1,13 @@
+Hi! Thank you for purchasing Pixel Spaces! This is my first ever asset pack
+so I am truly grateful ♥ If you have any requests or questions,
+please leave a comment at the project page or DM/@ me on twitter!
+
+License:
+- This asset pack can be used in any commercial or non-commercial project, you may modify the assets as you wish.
+- This asset pack cannot be resold/redistributed, even if modified - this includes as NFTs.
+- This asset pack cannot be used as basis for AI-generated content.
+
+Credit is not required but very much appreciated! Let me know of any projects you have finished :)
+
+Project Page: https://netherzapdos.itch.io/pixel-spaces
+Twitter: https://twitter.com/Netherzapdoss
\ No newline at end of file
diff --git a/apps/games/hide-and-seek/src/main.ts b/apps/games/hide-and-seek/src/main.ts
new file mode 100644
index 00000000..347c64e8
--- /dev/null
+++ b/apps/games/hide-and-seek/src/main.ts
@@ -0,0 +1,50 @@
+import 'phaser';
+
+import { CharityGamesPlugin } from '@worksheets/phaser/plugins';
+
+import { Boot } from './scenes/boot';
+import { Credits } from './scenes/credits';
+import { Game } from './scenes/game';
+import { GameOver } from './scenes/game-over';
+import { Instructions } from './scenes/instructions';
+import { UserInterface } from './scenes/user-interface';
+
+const config: Phaser.Types.Core.GameConfig = {
+ type: Phaser.AUTO,
+ backgroundColor: '#000000',
+ antialias: false,
+ render: {
+ pixelArt: true,
+ },
+ scale: {
+ parent: 'game',
+ mode: Phaser.Scale.FIT,
+ autoCenter: Phaser.Scale.CENTER_BOTH,
+ width: 320,
+ height: 240,
+ },
+ scene: [Boot, Game, UserInterface, Credits, Instructions, GameOver],
+ plugins: {
+ global: [
+ {
+ key: CharityGamesPlugin.KEY,
+ plugin: CharityGamesPlugin,
+ start: true,
+ },
+ ],
+ },
+ physics: {
+ default: 'arcade',
+ arcade: {
+ gravity: { y: 0, x: 0 },
+ debug: true,
+ },
+ },
+ dom: {
+ createContainer: true,
+ },
+};
+
+window.addEventListener('load', () => {
+ new Phaser.Game(config);
+});
diff --git a/apps/games/hide-and-seek/src/objects/building.ts b/apps/games/hide-and-seek/src/objects/building.ts
new file mode 100644
index 00000000..32f2779a
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/building.ts
@@ -0,0 +1,345 @@
+import { RectangleObject } from '../types';
+import { DEBUGGING, Depths, MovementSpeed, TILE_SIZE } from '../util';
+import { Door } from './door';
+import { Elevator } from './elevator';
+import { NonPlayerCharacter } from './non-player-character';
+import { Room } from './room';
+import { Staircase } from './staircase';
+
+export class Building {
+ static MAP_KEY = 'building';
+ scene: Phaser.Scene;
+ rooms: Room[];
+ elevators: Elevator[];
+ staircases: Staircase[];
+ doors: Door[];
+
+ tilemap: Phaser.Tilemaps.Tilemap;
+
+ pointsLayer: Phaser.Tilemaps.ObjectLayer;
+ wallpaperLayer: Phaser.Tilemaps.TilemapLayer;
+ infraLayer: Phaser.Tilemaps.TilemapLayer;
+ furn1Layer: Phaser.Tilemaps.TilemapLayer;
+ furn2Layer: Phaser.Tilemaps.TilemapLayer;
+ furn3Layer: Phaser.Tilemaps.TilemapLayer;
+ transportLayer: Phaser.Tilemaps.TilemapLayer;
+
+ constructor(scene: Phaser.Scene) {
+ this.scene = scene;
+ this.rooms = [];
+ this.elevators = [];
+ this.staircases = [];
+ this.doors = [];
+ this.tilemap = scene.make.tilemap({ key: Building.MAP_KEY });
+
+ /** Tileset Images **/
+ const wallpaperTiles = this.tilemap.addTilesetImage(
+ 'wallpaper',
+ 'wallpaper'
+ );
+ if (!wallpaperTiles) throw new Error('Wallpaper tiles not found');
+
+ const infraTiles = this.tilemap.addTilesetImage(
+ 'infrastructure',
+ 'infrastructure'
+ );
+ if (!infraTiles) throw new Error('Infrastructure tiles not found');
+
+ const furnTiles = this.tilemap.addTilesetImage('furniture', 'furniture');
+ if (!furnTiles) throw new Error('Furniture tiles not found');
+
+ const objectTiles = this.tilemap.addTilesetImage('objects', 'objects');
+ if (!objectTiles) throw new Error('Object tiles not found');
+
+ const gamerTiles = this.tilemap.addTilesetImage('gamer', 'gamer');
+ if (!gamerTiles) throw new Error('Gamer tiles not found');
+
+ const fire = this.tilemap.addTilesetImage('fire', 'fire');
+ if (!fire) throw new Error('Fire tiles not found');
+
+ const halloweenTiles = this.tilemap.addTilesetImage(
+ 'halloween',
+ 'halloween'
+ );
+ if (!halloweenTiles) throw new Error('Halloween tiles not found');
+
+ const museumTiles = this.tilemap.addTilesetImage('museum', 'museum');
+ if (!museumTiles) throw new Error('Museum tiles not found');
+
+ const policeTiles = this.tilemap.addTilesetImage('police', 'police');
+ if (!policeTiles) throw new Error('Police tiles not found');
+
+ const winterTiles = this.tilemap.addTilesetImage('winter', 'winter');
+ if (!winterTiles) throw new Error('Winter tiles not found');
+
+ const tiles = [
+ wallpaperTiles,
+ infraTiles,
+ furnTiles,
+ objectTiles,
+ fire,
+ gamerTiles,
+ halloweenTiles,
+ museumTiles,
+ policeTiles,
+ winterTiles,
+ ];
+
+ /** Layers **/
+ const wallpaperLayer = this.tilemap.createLayer('wallpaper', tiles);
+ if (!wallpaperLayer) throw new Error('Wallpaper layer not found');
+ this.wallpaperLayer = wallpaperLayer;
+
+ const furn1 = this.tilemap.createLayer('furniture1', tiles);
+ if (!furn1) throw new Error('Furniture 1 layer not found');
+ this.furn1Layer = furn1;
+
+ const furn2 = this.tilemap.createLayer('furniture2', tiles);
+ if (!furn2) throw new Error('Furniture 2 layer not found');
+ this.furn2Layer = furn2;
+
+ const furn3 = this.tilemap.createLayer('furniture3', tiles);
+ if (!furn3) throw new Error('Furniture 3 layer not found');
+ this.furn3Layer = furn3;
+
+ const transport = this.tilemap.createLayer('transport', tiles);
+ if (!transport) throw new Error('Transport layer not found');
+ transport.setDepth(Depths.INTERACTING);
+ this.transportLayer = transport;
+
+ const infraLayer = this.tilemap.createLayer('frame', tiles);
+ if (!infraLayer) throw new Error('Frame layer not found');
+ this.infraLayer = infraLayer;
+
+ const pointsLayer = this.tilemap.getObjectLayer('points');
+ if (!pointsLayer) throw new Error('Paths layer not found');
+ this.pointsLayer = pointsLayer;
+
+ this.createRooms();
+ this.createElevators();
+ this.createStaircases();
+ this.createDoors();
+
+ DEBUGGING && this.debug(scene);
+ }
+
+ iterateRectangles(fn: (rectangle: RectangleObject) => void) {
+ this.pointsLayer.objects.forEach((point) => {
+ const { x, y, height, width, name, rectangle } = point;
+ if (!rectangle) return; // ignore objects that aren't rectangles
+ if (x == null || y == null || width == null || height == null)
+ throw new Error(`Point ${name} properties not found`);
+ fn({ name, x, y, height, width });
+ });
+ }
+
+ debug(scene: Phaser.Scene) {
+ this.iterateRectangles((area) => {
+ const { x, y, width, height } = area;
+ const graphics = scene.add.graphics({
+ x,
+ y,
+ });
+ graphics.setDepth(1000);
+ graphics.lineStyle(1, 0xff0000);
+ graphics.strokeRect(0, 0, width, height);
+ });
+ }
+
+ getRoom(code: string) {
+ const room = this.rooms.find((room) => room.code === code);
+ if (!room) throw new Error(`Room ${code} not found`);
+ return room;
+ }
+
+ createRooms() {
+ this.rooms = [];
+
+ this.iterateRectangles((area) => {
+ this.rooms.push(new Room(this, area));
+ });
+ }
+
+ getTilesWithin(
+ layer: Phaser.Tilemaps.TilemapLayer,
+ x: number,
+ y: number,
+ width: number,
+ height: number
+ ) {
+ return layer.getTilesWithin(
+ x / TILE_SIZE,
+ y / TILE_SIZE,
+ width / TILE_SIZE,
+ height / TILE_SIZE
+ );
+ }
+
+ createElevators() {
+ this.iterateRectangles((area) => {
+ const tiles = this.getTilesWithin(
+ this.transportLayer,
+ area.x,
+ area.y,
+ area.width,
+ area.height
+ );
+
+ const elevator = tiles.find((t) => t.properties?.elevator);
+ if (elevator) {
+ this.elevators.push(
+ new Elevator(this, area.name, elevator.pixelX, elevator.pixelY)
+ );
+ }
+ });
+ }
+
+ createStaircases() {
+ this.iterateRectangles((area) => {
+ const tiles = this.getTilesWithin(
+ this.transportLayer,
+ area.x,
+ area.y,
+ area.width,
+ area.height
+ );
+
+ const staircase = tiles.find((t) => t.properties?.staircase);
+ if (staircase) {
+ const anchor = staircase.properties?.staircase as 'top' | 'bottom';
+ this.staircases.push(
+ new Staircase(
+ this,
+ area.name,
+ anchor,
+ staircase.flipX,
+ staircase.pixelX,
+ staircase.pixelY
+ )
+ );
+ }
+ });
+ }
+
+ createDoors() {
+ this.iterateRectangles((area) => {
+ const tiles = this.getTilesWithin(
+ this.infraLayer,
+ area.x,
+ area.y,
+ area.width,
+ area.height
+ );
+
+ const doors = tiles.filter((t) => t.properties?.door);
+ for (const door of doors) {
+ if (door) {
+ const anchor = door.properties?.door as 'left' | 'right';
+ this.doors.push(
+ new Door(this, area.name, anchor, door.pixelX, door.pixelY)
+ );
+ }
+ }
+ });
+ }
+
+ async travel(npc: NonPlayerCharacter, room: Room) {
+ const travelOptions = room.travelOptions();
+
+ const possibleOptions = Object.values(travelOptions).filter(
+ (option) => option
+ ) as (Staircase | Elevator | Door)[];
+
+ const option = Phaser.Math.RND.pick(possibleOptions);
+
+ if (option instanceof Staircase && !option.inUse) {
+ return await this.travelStaircase(npc, option);
+ }
+
+ if (option instanceof Elevator && !option.inUse) {
+ return await this.travelElevator(npc, option);
+ }
+
+ if (option instanceof Door && !option.inUse) {
+ return await this.travelDoor(npc, option);
+ }
+ }
+
+ async travelDoor(npc: NonPlayerCharacter, startingDoor: Door) {
+ const endingDoor = this.doors.find(
+ (door) =>
+ door.roomId ===
+ (startingDoor.anchor === 'left'
+ ? Room.left(startingDoor.roomId)
+ : Room.right(startingDoor.roomId)) &&
+ door.anchor !== startingDoor.anchor
+ );
+
+ if (!endingDoor) throw new Error('Door pair not found');
+
+ startingDoor.inUse = true;
+ endingDoor.inUse = true;
+
+ const startingRoom = this.getRoom(startingDoor.roomId);
+ await npc.movement(startingRoom.walls[startingDoor.anchor]);
+ await Promise.all([startingDoor.open(), endingDoor.open()]);
+ const endingRoom = this.getRoom(endingDoor.roomId);
+ await npc.movement(endingRoom.walls[endingDoor.anchor]);
+ npc.setRoom(endingRoom);
+ await Promise.all([startingDoor.close(), endingDoor.close()]);
+
+ startingDoor.inUse = false;
+ endingDoor.inUse = false;
+ }
+
+ async travelStaircase(npc: NonPlayerCharacter, startingStaircase: Staircase) {
+ const endingStaircase = this.staircases.find(
+ (staircase) =>
+ staircase.roomId ===
+ (startingStaircase.anchor === 'bottom'
+ ? Room.above(startingStaircase.roomId)
+ : Room.below(startingStaircase.roomId)) &&
+ staircase.anchor !== startingStaircase.anchor
+ );
+
+ if (!endingStaircase) throw new Error('Staircase pair not found');
+
+ startingStaircase.inUse = true;
+ endingStaircase.inUse = true;
+ await npc.movement(startingStaircase.point);
+ npc.setDepth(Depths.BACKGROUND);
+ npc.setSpeed(MovementSpeed.CLIMBING);
+ await npc.movement(endingStaircase.point);
+ npc.setSpeed(MovementSpeed.WALKING);
+ npc.setRoom(this.getRoom(endingStaircase.roomId));
+ npc.setDepth(Depths.PLAYER);
+ startingStaircase.inUse = false;
+ endingStaircase.inUse = false;
+ }
+
+ async travelElevator(npc: NonPlayerCharacter, startingElevator: Elevator) {
+ const available = this.elevators
+ .filter((e) => e.roomId !== startingElevator.roomId)
+ .filter((e) => !e.inUse);
+
+ if (!available.length) return;
+
+ const endingElevator = Phaser.Math.RND.pick(available);
+ startingElevator.inUse = true;
+ endingElevator.inUse = true;
+
+ await npc.movement(startingElevator.center);
+ await startingElevator.open();
+ npc.setDepth(Depths.INTERACTING);
+ await startingElevator.close();
+ npc.placeAt(endingElevator.center);
+ await npc.idle(1000);
+ npc.setRoom(this.getRoom(endingElevator.roomId));
+ await endingElevator.open();
+ npc.setDepth(Depths.PLAYER);
+ await endingElevator.close();
+
+ startingElevator.inUse = false;
+ endingElevator.inUse = false;
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/camera.ts b/apps/games/hide-and-seek/src/objects/camera.ts
new file mode 100644
index 00000000..2438103a
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/camera.ts
@@ -0,0 +1,15 @@
+import { Building } from './building';
+
+export class Camera {
+ static create(scene: Phaser.Scene, building: Building) {
+ // constrain the camera to the map
+ const camera = scene.cameras.main;
+ if (!camera) throw new Error('Camera not found');
+ camera.setBounds(
+ 0,
+ 0,
+ building.tilemap.widthInPixels,
+ building.tilemap.heightInPixels
+ );
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/controls.ts b/apps/games/hide-and-seek/src/objects/controls.ts
new file mode 100644
index 00000000..9ec72cea
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/controls.ts
@@ -0,0 +1,32 @@
+export class Controls extends Phaser.Cameras.Controls.FixedKeyControl {
+ constructor(scene: Phaser.Scene) {
+ // TODO: figure out if removing the round pixels makes the camera zoom smoothly
+ // without trimming pixels off. this is most notable when zooming in on an idle
+ // npc sprite.
+ scene.cameras.main.setRoundPixels(true);
+ const keyboard = scene.input.keyboard;
+ if (!keyboard) throw new Error('Keyboard not found');
+
+ const cursors = keyboard.createCursorKeys();
+
+ const controlConfig: Phaser.Types.Cameras.Controls.FixedKeyControlConfig = {
+ camera: scene.cameras.main,
+ left: cursors.left,
+ right: cursors.right,
+ up: cursors.up,
+ down: cursors.down,
+ zoomIn: keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.Q),
+ zoomOut: keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.E),
+ zoomSpeed: 0.02,
+ maxZoom: 3,
+ minZoom: 0.5,
+ speed: 0.2,
+ };
+
+ super(controlConfig);
+ }
+
+ update(delta: number) {
+ super.update(delta);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/credits-button.ts b/apps/games/hide-and-seek/src/objects/credits-button.ts
new file mode 100644
index 00000000..a345a832
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/credits-button.ts
@@ -0,0 +1,32 @@
+export class CreditsButton extends Phaser.GameObjects.Container {
+ constructor(scene: Phaser.Scene, x: number, y: number) {
+ super(scene, x, y);
+
+ const button = new Phaser.GameObjects.Sprite(scene, 0, 0, 'button_white')
+ .setScale(1.1)
+ .setInteractive()
+ .on(
+ 'pointerdown',
+ (
+ _p: unknown,
+ _x: unknown,
+ _y: unknown,
+ e: Phaser.Types.Input.EventData
+ ) => {
+ scene.sound.play('menu');
+ scene.scene.launch('credits');
+ scene.scene.stop('instructions');
+ e.stopPropagation();
+ }
+ );
+
+ const icon = new Phaser.GameObjects.Sprite(scene, 0, 0, 'comfort').setScale(
+ 2
+ );
+
+ this.add(button);
+ this.add(icon);
+
+ scene.add.existing(this);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/door.ts b/apps/games/hide-and-seek/src/objects/door.ts
new file mode 100644
index 00000000..ae3e3f64
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/door.ts
@@ -0,0 +1,49 @@
+import { Depths } from '../util';
+import { Building } from './building';
+
+export class Door extends Phaser.GameObjects.Sprite {
+ static size = 16;
+ inUse: boolean;
+ constructor(
+ public building: Building,
+ public roomId: string,
+ public anchor: 'left' | 'right',
+ public x: number,
+ public y: number
+ ) {
+ super(building.scene, x - 1, y, 'door', 0);
+ this.setOrigin(0);
+ building.scene.add.existing(this);
+ this.setDepth(Depths.FOREGROUND);
+ this.inUse = false;
+ if (anchor === 'right') {
+ this.x += Door.size;
+ }
+ }
+
+ async open() {
+ return new Promise((resolve) =>
+ this.play({ key: 'door_open' }).on(
+ 'animationcomplete',
+ (animation: Phaser.Animations.Animation) => {
+ if (animation.key === 'door_open') {
+ resolve(true);
+ }
+ }
+ )
+ );
+ }
+
+ close() {
+ return new Promise((resolve) => {
+ this.play({ key: 'door_close' }).on(
+ 'animationcomplete',
+ (animation: Phaser.Animations.Animation) => {
+ if (animation.key === 'door_close') {
+ resolve(true);
+ }
+ }
+ );
+ });
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/elevator.ts b/apps/games/hide-and-seek/src/objects/elevator.ts
new file mode 100644
index 00000000..acb7d58c
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/elevator.ts
@@ -0,0 +1,72 @@
+import { DEBUGGING, Depths } from '../util';
+import { Building } from './building';
+import { NonPlayerCharacter } from './non-player-character';
+import { Room } from './room';
+
+export class Elevator extends Phaser.GameObjects.Sprite {
+ static size = 32;
+ roomId: string;
+ inUse: boolean;
+ constructor(building: Building, roomId: string, x: number, y: number) {
+ super(building.scene, x, y, 'elevator', 0);
+ this.roomId = roomId;
+ this.setOrigin(0);
+ building.scene.add.existing(this);
+ this.setDepth(Depths.FOREGROUND);
+ this.inUse = false;
+
+ DEBUGGING && this.debug();
+ }
+
+ get center() {
+ return {
+ x: this.x + Elevator.size / 2,
+ y:
+ this.y + Elevator.size - Room.floorOffset - NonPlayerCharacter.size / 2,
+ };
+ }
+
+ debug() {
+ [this.center].map((point) => {
+ const { x, y } = point;
+ const graphics = this.scene.add.graphics({
+ x,
+ y,
+ });
+ graphics.setDepth(1000);
+ graphics.lineStyle(1, 0x0000ff);
+ graphics.strokeRect(-1, -1, 2, 2);
+ });
+ }
+ async open() {
+ return new Promise((resolve) =>
+ this.play({ key: 'elevator_open' }).on(
+ 'animationcomplete',
+ (animation: Phaser.Animations.Animation) => {
+ if (animation.key === 'elevator_open') {
+ resolve(true);
+ }
+ }
+ )
+ );
+ }
+
+ async close() {
+ return new Promise((resolve) => {
+ this.play({ key: 'elevator_close' }).on(
+ 'animationcomplete',
+ (animation: Phaser.Animations.Animation) => {
+ if (animation.key === 'elevator_close') {
+ resolve(true);
+ }
+ }
+ );
+ });
+ }
+
+ async use(fn: () => Promise) {
+ this.inUse = true;
+ await fn();
+ this.inUse = false;
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/non-player-character.ts b/apps/games/hide-and-seek/src/objects/non-player-character.ts
new file mode 100644
index 00000000..0219b8de
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/non-player-character.ts
@@ -0,0 +1,294 @@
+import { waitFor } from '@worksheets/util/time';
+
+import { Coordinate } from '../types';
+import { CHARACTER_SPEEDS, Depths, MovementSpeed } from '../util';
+import { Room } from './room';
+
+class PlayerStatus extends Phaser.GameObjects.Sprite {
+ scene: Phaser.Scene;
+ tween: Phaser.Tweens.Tween;
+ static originalY = -14;
+ constructor(scene: Phaser.Scene) {
+ super(scene, 0, PlayerStatus.originalY, 'pointer_yellow');
+ this.scene = scene;
+ scene.add.existing(this);
+ this.tween = scene.tweens.add({
+ targets: this,
+ y: PlayerStatus.originalY - 4,
+ duration: 250,
+ yoyo: true,
+ repeat: -1,
+ });
+ }
+
+ setStatus(status: 'right' | 'wrong') {
+ this.tween.stop();
+ this.setTexture(status === 'right' ? 'check' : 'cross');
+ this.setY(PlayerStatus.originalY);
+ }
+
+ playTween() {
+ this.tween = this.scene.tweens.add({
+ targets: this,
+ y: PlayerStatus.originalY - 4,
+ duration: 250,
+ yoyo: true,
+ repeat: -1,
+ });
+ }
+
+ reset() {
+ this.playTween();
+ this.setTexture('pointer_yellow');
+ this.setY(PlayerStatus.originalY);
+ }
+}
+
+export class NonPlayerCharacter extends Phaser.GameObjects.Container {
+ static size = 16;
+ static numMaleSprites = 15;
+ static numFemaleSprites = 15;
+ scene: Phaser.Scene;
+ character: Phaser.GameObjects.Sprite;
+ status: PlayerStatus;
+ code: string;
+ room: Room;
+ #speed = CHARACTER_SPEEDS[MovementSpeed.WALKING];
+ #origin = { x: 16, y: 16 };
+
+ static image(key: string) {
+ return `npc_${key}`;
+ }
+
+ static idle(key: string) {
+ return `${NonPlayerCharacter.image(key)}_idle`;
+ }
+
+ static walk(key: string) {
+ return `${NonPlayerCharacter.image(key)}_walk`;
+ }
+
+ constructor(scene: Phaser.Scene, room: Room, code: string) {
+ super(scene, 0, 0);
+ this.room = room;
+ this.scene = scene;
+ this.code = code;
+
+ this.setDepth(Depths.PLAYER);
+ this.placeAt(room.walls.left);
+
+ this.character = scene.add.sprite(0, 0, NonPlayerCharacter.image(code));
+
+ this.character.setDisplayOrigin(this.#origin.x, this.#origin.y);
+ this.character.play({ key: NonPlayerCharacter.idle(code), repeat: -1 });
+ this.character.setInteractive();
+ this.character.on('pointerdown', () => {
+ scene.events.emit('player:click', this);
+ });
+
+ this.status = new PlayerStatus(scene);
+
+ this.add(this.status);
+ this.add(this.character);
+
+ scene.add.existing(this);
+ }
+
+ setStatus(status: 'right' | 'wrong') {
+ this.status.setStatus(status);
+ this.character.removeInteractive();
+ }
+
+ setRoom(room: Room) {
+ this.room = room;
+ }
+
+ placeAt(point: Coordinate) {
+ this.setPosition(point.x, point.y);
+ }
+
+ destroy() {
+ this.scene.tweens.killTweensOf(this);
+ this.character.setActive(false);
+ this.character.destroy();
+ this.status.destroy();
+ }
+
+ async wander() {
+ const loop = async () => {
+ await this.pace();
+ await this.travel();
+ };
+
+ // eslint-disable-next-line no-constant-condition
+ while (this.character.active) {
+ await loop();
+ }
+ }
+ async pace() {
+ const pacing = Phaser.Math.RND.pick([true, true, false, false]);
+ if (pacing) await this.room.pace(this);
+ }
+
+ async travel() {
+ const traveling = Phaser.Math.RND.pick([true, true, true, false]);
+ if (traveling) await this.room.travel(this);
+ }
+
+ async idle(duration: number) {
+ if (!this.character.active) return;
+
+ this.character.play({
+ key: NonPlayerCharacter.idle(this.code),
+ repeat: -1,
+ });
+ await waitFor(duration);
+ }
+
+ async face(point: Coordinate) {
+ if (this.x > point.x) {
+ this.character.setFlipX(true);
+ } else {
+ this.character.setFlipX(false);
+ }
+ }
+
+ async movement(point: Coordinate) {
+ if (!this.character.active) return;
+
+ this.face(point);
+ this.character.play({
+ key: NonPlayerCharacter.walk(this.code),
+ repeat: -1,
+ });
+ const distance = Phaser.Math.Distance.Between(
+ this.x,
+ this.y,
+ point.x,
+ point.y
+ );
+ const duration = distance / this.#speed;
+ return new Promise((resolve) =>
+ this.scene.tweens.add({
+ targets: this,
+ x: point.x,
+ y: point.y,
+ duration,
+ onComplete: () => {
+ if (this.character.active)
+ this.character.play({
+ key: NonPlayerCharacter.idle(this.code),
+ repeat: -1,
+ });
+ resolve(true);
+ },
+ })
+ );
+ }
+
+ setSpeed(speed: MovementSpeed) {
+ this.#speed = CHARACTER_SPEEDS[speed];
+ }
+
+ static preload(scene: Phaser.Scene) {
+ for (const sprite of this.sprites) {
+ this.loadSpritesheet(scene, sprite);
+ }
+ }
+
+ static loadSpritesheet(scene: Phaser.Scene, key: string) {
+ scene.load.spritesheet(
+ NonPlayerCharacter.image(key),
+ `assets/spritesheets/npc/${key}.png`,
+ {
+ frameWidth: 32,
+ frameHeight: 32,
+ }
+ );
+ }
+
+ static create(scene: Phaser.Scene) {
+ for (const sprite of this.sprites) {
+ this.createAnimations(scene, sprite);
+ }
+ }
+
+ static createAnimations(scene: Phaser.Scene, code: string) {
+ scene.anims.create({
+ key: NonPlayerCharacter.walk(code),
+ frameRate: 6,
+ frames: scene.anims.generateFrameNumbers(NonPlayerCharacter.image(code), {
+ start: 0,
+ end: 3,
+ }),
+ });
+ scene.anims.create({
+ key: NonPlayerCharacter.idle(code),
+ frameRate: 6,
+ frames: scene.anims.generateFrameNumbers(NonPlayerCharacter.image(code), {
+ start: 5,
+ end: 7,
+ }),
+ });
+ }
+
+ static get sprites() {
+ return [
+ 'male_1',
+ 'male_2',
+ 'male_3',
+ 'male_4',
+ 'male_5',
+ 'male_6',
+ 'male_7',
+ 'male_8',
+ 'male_9',
+ 'male_10',
+ 'male_11',
+ 'male_12',
+ 'male_13',
+ 'male_14',
+ 'male_15',
+ 'male_16',
+ 'male_17',
+ 'male_18',
+ 'male_19',
+ 'male_20',
+ 'male_21',
+ 'male_22',
+ 'female_1',
+ 'female_2',
+ 'female_3',
+ 'female_4',
+ 'female_5',
+ 'female_6',
+ 'female_7',
+ 'female_8',
+ 'female_9',
+ 'female_10',
+ 'female_11',
+ 'female_12',
+ 'female_13',
+ 'female_14',
+ 'female_15',
+ 'female_16',
+ 'female_17',
+ 'female_18',
+ 'female_19',
+ 'female_20',
+ 'female_21',
+ 'female_22',
+ 'special_1',
+ 'special_2',
+ 'special_3',
+ 'special_4',
+ 'special_5',
+ 'special_6',
+ 'special_7',
+ 'special_8',
+ 'special_9',
+ 'special_10',
+ 'special_11',
+ ];
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/player-poster.ts b/apps/games/hide-and-seek/src/objects/player-poster.ts
new file mode 100644
index 00000000..2e7b3d6d
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/player-poster.ts
@@ -0,0 +1,43 @@
+import { NonPlayerCharacter } from './non-player-character';
+
+export class PlayerPoster extends Phaser.GameObjects.Container {
+ constructor(
+ scene: Phaser.Scene,
+ x: number,
+ y: number,
+ sprite: string,
+ text = 'Find',
+ color = 0xf4b266,
+ status: 'none' | 'right' | 'wrong' = 'none'
+ ) {
+ super(scene, x, y);
+
+ const poster = scene.add.sprite(0, 0, 'panel_white').setScale(1.1, 0.9);
+ const player = scene.add
+ .sprite(0, 10, NonPlayerCharacter.image(sprite))
+ .play({
+ key: NonPlayerCharacter.idle(sprite),
+ repeat: -1,
+ })
+ .setScale(3);
+
+ const title = scene.add
+ .bitmapText(0, -26, 'thick', text, 16)
+ .setTintFill(color)
+ .setOrigin(0.5)
+ .setDropShadow(1, 1, 0x000000, 1);
+
+ const icon = scene.add
+ .sprite(32, 42, 'cross')
+ .setScale(3)
+ .setVisible(false);
+ if (status !== 'none') icon.setVisible(true);
+ if (status === 'right') icon.setTexture('check');
+
+ this.add(poster);
+ this.add(player);
+ this.add(title);
+ this.add(icon);
+ scene.add.existing(this);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/room.ts b/apps/games/hide-and-seek/src/objects/room.ts
new file mode 100644
index 00000000..c3464868
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/room.ts
@@ -0,0 +1,162 @@
+import { waitFor } from '@worksheets/util/time';
+
+import { Coordinate, RectangleObject } from '../types';
+import { DEBUGGING } from '../util';
+import { Building } from './building';
+import { NonPlayerCharacter } from './non-player-character';
+
+export class Room {
+ static minRow = 'a';
+ static maxRow = 'l';
+ static minColumn = 1;
+ static maxColumn = 5;
+ static floorOffset = 2;
+ building: Building;
+ locations: Record;
+ area: RectangleObject;
+
+ constructor(building: Building, area: RectangleObject) {
+ this.building = building;
+ this.area = area;
+ this.locations = {};
+
+ DEBUGGING && this.debug(this.building.scene);
+ }
+
+ createPoints() {
+ this.iteratePoints(({ x, y, name }) => {
+ this.locations[name] = {
+ x,
+ y,
+ };
+ });
+ }
+
+ iteratePoints(fn: (point: { name: string; x: number; y: number }) => void) {
+ this.building.pointsLayer.objects.forEach((point) => {
+ const { x, y, name, rectangle } = point;
+ if (rectangle) return; // ignore objects that are rectangles
+ if (x == null || y == null)
+ throw new Error(`Point ${name} properties not found`);
+ if (!name.includes(this.code)) return; // ignore points outside of the room
+ fn({ name, x, y });
+ });
+ }
+
+ debug(scene: Phaser.Scene) {
+ [this.walls.left, this.walls.right].map((point) => {
+ const { x, y } = point;
+ const graphics = scene.add.graphics({
+ x,
+ y,
+ });
+ graphics.setDepth(1000);
+ graphics.lineStyle(1, 0x00ff00);
+ graphics.strokeRect(-1, -1, 2, 2);
+ });
+ }
+
+ async pace(npc: NonPlayerCharacter) {
+ const minMovements = 0;
+ const maxMovements = 4;
+ const movements = Phaser.Math.RND.integerInRange(
+ minMovements,
+ maxMovements
+ );
+ for (let i = 0; i < movements; i++) {
+ await npc.movement(this.coordinateBetweenWalls());
+ const pause = Phaser.Math.RND.integerInRange(0, 1000);
+ await waitFor(pause);
+ }
+ }
+
+ async travel(npc: NonPlayerCharacter) {
+ await this.building.travel(npc, this);
+ }
+
+ travelOptions() {
+ const doors = this.building.doors.filter(
+ (door) => door.roomId === this.code
+ );
+ return {
+ // rooms can only have one staircase or elevator
+ staircase: this.building.staircases.find(
+ (staircase) => staircase.roomId === this.code
+ ),
+ elevator: this.building.elevators.find(
+ (elevator) => elevator.roomId === this.code
+ ),
+ // rooms can have multiple doors
+ leftDoor: doors.find((door) => door.anchor === 'left'),
+ rightDoor: doors.find((door) => door.anchor === 'right'),
+ };
+ }
+
+ get code() {
+ return this.area.name;
+ }
+
+ coordinateBetweenWalls() {
+ // find a random point in the room
+ const x = Phaser.Math.Between(this.walls.left.x, this.walls.right.x);
+ const y = Phaser.Math.Between(this.walls.left.y, this.walls.right.y);
+ return { x, y };
+ }
+
+ get walls() {
+ const playerOffset = NonPlayerCharacter.size / 2;
+ const y = this.area.y + this.area.height - playerOffset - Room.floorOffset;
+ return {
+ left: { x: this.area.x + playerOffset, y },
+ right: {
+ x: this.area.x + this.area.width - playerOffset,
+ y,
+ },
+ };
+ }
+
+ // vertical access is controlled by the letter, a, b, c...
+ // a is the first floor, b is the second floor, etc.
+ static above(roomId: string) {
+ const letter = roomId[1];
+ if (letter === this.minRow)
+ throw new Error('Cannot go above the first floor');
+ const previousLetter = String.fromCharCode(letter.charCodeAt(0) - 1);
+ return roomId.replace(letter, previousLetter);
+ }
+
+ static below(roomId: string) {
+ const letter = roomId[1];
+ if (letter === this.maxRow)
+ throw new Error('Cannot go below the last floor');
+ const nextLetter = String.fromCharCode(letter.charCodeAt(0) + 1);
+ return roomId.replace(letter, nextLetter);
+ }
+
+ static left(roomId: string) {
+ const number = parseInt(roomId[0]);
+ if (number === this.minColumn)
+ throw new Error('Cannot go left of the first room');
+ const previousNumber = number - 1;
+ return `${previousNumber}${roomId.slice(1)}`;
+ }
+
+ static right(roomId: string) {
+ const number = parseInt(roomId[0]);
+ if (number === this.maxColumn)
+ throw new Error('Cannot go right of the last room');
+ const nextNumber = number + 1;
+ return `${nextNumber}${roomId.slice(1)}`;
+ }
+ static random() {
+ const minRow = this.minRow.charCodeAt(0);
+ const maxRow = this.maxRow.charCodeAt(0);
+ const minColumn = this.minColumn;
+ const maxColumn = this.maxColumn;
+ const randomRow =
+ Math.floor(Math.random() * (maxRow - minRow + 1)) + minRow;
+ const randomColumn =
+ Math.floor(Math.random() * (maxColumn - minColumn + 1)) + minColumn;
+ return randomColumn + String.fromCharCode(randomRow);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/staircase.ts b/apps/games/hide-and-seek/src/objects/staircase.ts
new file mode 100644
index 00000000..e2b940d4
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/staircase.ts
@@ -0,0 +1,44 @@
+import { DEBUGGING } from '../util';
+import { Building } from './building';
+import { Room } from './room';
+
+export class Staircase {
+ static size = 16;
+ static anchorOffset = 6;
+ inUse = false;
+ constructor(
+ public building: Building,
+ public roomId: string,
+ public anchor: 'top' | 'bottom',
+ public flipped: boolean,
+ public x: number,
+ public y: number
+ ) {
+ DEBUGGING && this.debug();
+ }
+
+ get point() {
+ const flipped = this.flipped ? -1 : 1;
+ const top = this.anchor === 'top' ? 1 : -1;
+ const topOffset = this.anchor === 'top' ? 4 : 0;
+ return {
+ x:
+ this.x +
+ Staircase.size / 2 +
+ (Staircase.anchorOffset + topOffset) * flipped * top,
+ y: this.y + Staircase.size / 2 - Room.floorOffset,
+ };
+ }
+ debug() {
+ [this.point].map((point) => {
+ const { x, y } = point;
+ const graphics = this.building.scene.add.graphics({
+ x,
+ y,
+ });
+ graphics.setDepth(1000);
+ graphics.lineStyle(1, 0xff0000);
+ graphics.strokeRect(-1, -1, 2, 2);
+ });
+ }
+}
diff --git a/apps/games/hide-and-seek/src/objects/volume-button.ts b/apps/games/hide-and-seek/src/objects/volume-button.ts
new file mode 100644
index 00000000..3ea24845
--- /dev/null
+++ b/apps/games/hide-and-seek/src/objects/volume-button.ts
@@ -0,0 +1,39 @@
+import { CharityGamesPlugin } from '@worksheets/phaser/plugins';
+
+export class VolumeButton extends Phaser.GameObjects.Container {
+ constructor(scene: Phaser.Scene, x: number, y: number) {
+ super(scene, x, y);
+ const server = CharityGamesPlugin.find(scene);
+ const muted = server.storage.get('muted', false);
+ scene.sound.mute = muted;
+
+ const icon = scene.add
+ .sprite(0, -1, scene.sound.mute ? 'speaker_off' : 'speaker_on')
+ .setScale(1);
+
+ const button = scene.add
+ .sprite(0, 0, 'button_white')
+ .setScale(1.1)
+ .setInteractive()
+ .on(
+ 'pointerdown',
+ (
+ _p: unknown,
+ _x: unknown,
+ _y: unknown,
+ e: Phaser.Types.Input.EventData
+ ) => {
+ server.storage.set('muted', !scene.sound.mute);
+ scene.sound.mute = !scene.sound.mute;
+ icon.setTexture(scene.sound.mute ? 'speaker_on' : 'speaker_off');
+ scene.sound.play('menu');
+ server.storage.save();
+ e.stopPropagation();
+ }
+ );
+
+ this.add(button);
+ this.add(icon);
+ scene.add.existing(this);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/scenes/boot.ts b/apps/games/hide-and-seek/src/scenes/boot.ts
new file mode 100644
index 00000000..e7c2b087
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/boot.ts
@@ -0,0 +1,217 @@
+import { CharityGamesPlugin } from '@worksheets/phaser/plugins';
+
+import { Building } from '../objects/building';
+import { NonPlayerCharacter } from '../objects/non-player-character';
+export class Boot extends Phaser.Scene {
+ server!: CharityGamesPlugin;
+ assetLoadBar!: Phaser.GameObjects.Graphics;
+ assetProgressBar!: Phaser.GameObjects.Graphics;
+
+ serverLoadBar!: Phaser.GameObjects.Graphics;
+ serverProgressBar!: Phaser.GameObjects.Graphics;
+ constructor() {
+ super('boot');
+ }
+
+ preload() {
+ // connect to server
+ this.server = CharityGamesPlugin.find(this);
+ this.server.initialize();
+ this.server.storage.ignore(['targets']);
+
+ // prepare
+ this.createBars();
+ this.setLoadEvents();
+ this.load.image('charity_games', './assets/charity_games.png');
+
+ this.load.image('button_blue_long', 'assets/ui/button_blue_long.png');
+ this.load.image('button_grey_long', 'assets/ui/button_grey_long.png');
+ this.load.image('cross', 'assets/ui/cross.png');
+ this.load.image('check', 'assets/ui/check.png');
+ this.load.image('back', 'assets/ui/back.png');
+ this.load.image('comfort', 'assets/ui/comfort.png');
+
+ this.load.image('arrow_left', 'assets/ui/arrow_left.png');
+ this.load.image('arrow_right', 'assets/ui/arrow_right.png');
+ this.load.image('arrow_up', 'assets/ui/arrow_up.png');
+ this.load.image('arrow_down', 'assets/ui/arrow_down.png');
+
+ this.load.image('tasks', 'assets/ui/tasks.png');
+ this.load.image('siren', 'assets/ui/siren.png');
+ this.load.image('population', 'assets/ui/population.png');
+ this.load.image('panel_blue', 'assets/ui/panel_blue.png');
+ this.load.image('frame_white', 'assets/ui/frame_white.png');
+ this.load.image('frame_white_golden', 'assets/ui/frame_white_golden.png');
+
+ this.load.image('pointer_yellow', 'assets/ui/pointer_yellow.png');
+ this.load.image('continue', 'assets/ui/continue.png');
+ this.load.image('panel_white', 'assets/ui/panel_white.png');
+ this.load.image('button_white', 'assets/ui/button_white.png');
+ this.load.image('speaker_off', 'assets/ui/speaker_off.png');
+ this.load.image('speaker_on', 'assets/ui/speaker_on.png');
+ this.load.image('backgrounds', 'assets/tilesets/backgrounds.png');
+ this.load.image('furniture', 'assets/tilesets/furniture.png');
+ this.load.image('infrastructure', 'assets/tilesets/infrastructure.png');
+ this.load.image('objects', 'assets/tilesets/objects.png');
+ this.load.image('wallpaper', 'assets/tilesets/wallpaper.png');
+ this.load.image('fire', 'assets/tilesets/fire.png');
+ this.load.image('gamer', 'assets/tilesets/gamer.png');
+ this.load.image('halloween', 'assets/tilesets/halloween.png');
+ this.load.image('museum', 'assets/tilesets/museum.png');
+ this.load.image('police', 'assets/tilesets/police.png');
+ this.load.image('winter', 'assets/tilesets/winter.png');
+
+ this.load.tilemapTiledJSON(Building.MAP_KEY, 'assets/buildings/1.json');
+
+ this.load.spritesheet('elevator', 'assets/spritesheets/elevator.png', {
+ frameWidth: 32,
+ frameHeight: 32,
+ });
+ this.load.spritesheet('door', 'assets/spritesheets/door.png', {
+ frameWidth: 16,
+ frameHeight: 32,
+ });
+
+ this.load.bitmapFont(
+ 'pixel',
+ 'assets/fonts/pixel.png',
+ 'assets/fonts/pixel.xml'
+ );
+ this.load.bitmapFont(
+ 'thick',
+ 'assets/fonts/thick.png',
+ 'assets/fonts/thick.xml'
+ );
+ this.load.bitmapFont(
+ 'peaberry_yellow',
+ 'assets/fonts/peaberry_yellow.png',
+ 'assets/fonts/peaberry_yellow.xml'
+ );
+ this.load.bitmapFont(
+ 'peaberry_red',
+ 'assets/fonts/peaberry_red.png',
+ 'assets/fonts/peaberry_red.xml'
+ );
+ this.load.bitmapFont(
+ 'peaberry_blue',
+ 'assets/fonts/peaberry_blue.png',
+ 'assets/fonts/peaberry_blue.xml'
+ );
+
+ this.load.audio('right', 'assets/sounds/right.mp3');
+ this.load.audio('wrong', 'assets/sounds/wrong.mp3');
+ this.load.audio('menu', 'assets/sounds/menu.mp3');
+
+ NonPlayerCharacter.preload(this);
+ }
+
+ create() {
+ this.anims.create({
+ key: 'elevator_open',
+ frames: this.anims.generateFrameNumbers('elevator', {
+ start: 0,
+ end: 4,
+ }),
+ frameRate: 6,
+ });
+
+ this.anims.create({
+ key: 'elevator_close',
+ frames: this.anims.generateFrameNumbers('elevator', {
+ start: 5,
+ end: 9,
+ }),
+ frameRate: 6,
+ });
+
+ this.anims.create({
+ key: 'door_open',
+ frames: this.anims.generateFrameNumbers('door', {
+ start: 0,
+ end: 3,
+ }),
+ frameRate: 6,
+ });
+
+ this.anims.create({
+ key: 'door_close',
+ frames: this.anims.generateFrameNumbers('door', {
+ start: 4,
+ end: 7,
+ }),
+ frameRate: 6,
+ });
+ NonPlayerCharacter.create(this);
+ }
+
+ setLoadEvents() {
+ this.load.on(
+ 'progress',
+ (value: number) => {
+ this.assetProgressBar.clear();
+ this.assetProgressBar.fillStyle(0x0088aa, 1);
+ this.assetProgressBar.fillRect(
+ this.cameras.main.width / 4,
+ this.cameras.main.height * 0.5 - 16,
+ (this.cameras.main.width / 2) * value,
+ 16
+ );
+ },
+ this
+ );
+
+ this.load.on('complete', () => {
+ this.startGame();
+ });
+
+ this.server.on('initializing', (value: number) => {
+ this.serverProgressBar.clear();
+ this.serverProgressBar.fillStyle(0x0088aa, 1);
+ this.serverProgressBar.fillRect(
+ this.cameras.main.width / 4,
+ this.cameras.main.height * 0.5 + 10,
+ (this.cameras.main.width / 2) * value,
+ 16
+ );
+ });
+
+ this.server.on('initialized', () => {
+ this.startGame();
+ });
+ }
+
+ createBars() {
+ this.assetLoadBar = this.add.graphics();
+ this.assetLoadBar.fillStyle(0xd40000, 1);
+ this.assetLoadBar.fillRect(
+ this.cameras.main.width / 4 - 2,
+ this.cameras.main.height * 0.5 - 18,
+ this.cameras.main.width / 2 + 4,
+ 20
+ );
+ this.assetProgressBar = this.add.graphics();
+
+ this.serverLoadBar = this.add.graphics();
+ this.serverLoadBar.fillStyle(0xd40000, 1);
+ this.serverLoadBar.fillRect(
+ this.cameras.main.width / 4 - 2,
+ this.cameras.main.height * 0.5 + 8,
+ this.cameras.main.width / 2 + 4,
+ 20
+ );
+ this.serverProgressBar = this.add.graphics();
+ this.serverProgressBar.fillStyle(0x0088aa, 1);
+ this.serverProgressBar.fillRect(
+ this.cameras.main.width / 4,
+ this.cameras.main.height * 0.5 + 10,
+ (this.cameras.main.width / 2) * 0.05,
+ 16
+ );
+ }
+
+ startGame() {
+ if (this.server.isInitialized && this.load.isReady()) {
+ this.scene.start('game');
+ }
+ }
+}
diff --git a/apps/games/hide-and-seek/src/scenes/credits.ts b/apps/games/hide-and-seek/src/scenes/credits.ts
new file mode 100644
index 00000000..5bb8b4da
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/credits.ts
@@ -0,0 +1,84 @@
+import { GAME_VERSION } from '../util';
+
+export class Credits extends Phaser.Scene {
+ constructor() {
+ super('credits');
+ }
+
+ create() {
+ this.add
+ .sprite(16, 16, 'back')
+ .setScale(2)
+ .setInteractive()
+ .on('pointerdown', () => {
+ this.sound.play('menu');
+ this.scene.launch('instructions');
+ this.scene.stop('credits');
+ });
+
+ this.add
+ .bitmapText(160, 30, 'peaberry_yellow', 'Credits', 24)
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+
+ this.add.sprite(160, 100, 'charity_games').setScale(0.041);
+
+ this.add
+ .bitmapText(160, 150, 'peaberry_yellow', 'Code by ModestDuck', 18)
+ .setDropShadow(2, 2, 0x000000, 1)
+ .setOrigin(0.5);
+
+ this.add
+ .bitmapText(160, 180, 'peaberry_yellow', 'Art by Netherzapdos', 18)
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+
+ this.add
+ .bitmapText(160, 210, 'peaberry_yellow', 'Sound by ColorAlpha', 18)
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+ this.add
+ .bitmapText(4, 230, 'peaberry_yellow', GAME_VERSION, 8)
+ .setDropShadow(0.5, 0.5, 0x000000, 1);
+
+ const logoAnchor = document.createElement('a');
+ logoAnchor.setAttribute('target', '_blank');
+ logoAnchor.setAttribute(
+ 'href',
+ 'https://charity.games/?utm_source=hide-and-seek'
+ );
+ logoAnchor.setAttribute(
+ 'style',
+ 'height:80px;width:80px;background-color: transparent;'
+ );
+
+ this.add.dom(160, 100, logoAnchor);
+
+ const developerAnchor = document.createElement('a');
+ developerAnchor.setAttribute('target', '_blank');
+ developerAnchor.setAttribute('href', 'https://modestduck.com');
+ developerAnchor.setAttribute(
+ 'style',
+ 'height:30px;width:280px;background-color: transparent;'
+ );
+ this.add.dom(160, 150, developerAnchor);
+
+ const artistAnchor = document.createElement('a');
+ artistAnchor.setAttribute(
+ 'style',
+ 'height:30px;width:280px;background-color: transparent;'
+ );
+ artistAnchor.setAttribute('target', '_blank');
+ artistAnchor.setAttribute('href', 'https://netherzapdos.itch.io/');
+ this.add.dom(160, 180, artistAnchor);
+
+ const soundAnchor = document.createElement('a');
+ soundAnchor.setAttribute('target', '_blank');
+ soundAnchor.setAttribute('href', 'https://coloralpha.itch.io/');
+ soundAnchor.setAttribute(
+ 'style',
+ 'height:30px;width:280px;background-color: transparent;'
+ );
+ this.add.dom(160, 210, soundAnchor);
+ }
+}
diff --git a/apps/games/hide-and-seek/src/scenes/game-over.ts b/apps/games/hide-and-seek/src/scenes/game-over.ts
new file mode 100644
index 00000000..5cabe1c7
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/game-over.ts
@@ -0,0 +1,117 @@
+import { CharityGamesPlugin } from '@worksheets/phaser/plugins';
+
+import { NonPlayerCharacter } from '../objects/non-player-character';
+import { PlayerPoster } from '../objects/player-poster';
+
+export type GameOverPayload = {
+ remaining: number;
+ errors: number;
+ found: string[];
+};
+
+export class GameOver extends Phaser.Scene {
+ payload: GameOverPayload;
+ server!: CharityGamesPlugin;
+ constructor() {
+ super('game-over');
+ this.payload = {
+ remaining: 0,
+ errors: 0,
+ found: [],
+ };
+ }
+
+ init(data: GameOverPayload) {
+ this.payload = data;
+ }
+
+ create() {
+ this.server = CharityGamesPlugin.find(this);
+ this.add
+ .bitmapText(160, 40, 'peaberry_yellow', 'Game Over!', 32)
+ .setOrigin(0.5)
+ .setDropShadow(3, 3, 0x000000, 1);
+
+ this.add
+ .bitmapText(
+ 160,
+ 200,
+ 'peaberry_yellow',
+ `${this.sys.game.device.os.desktop ? 'Click' : 'Tap'} to try again`,
+ 24
+ )
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+
+ this.input.on('pointerdown', () => {
+ const game = this.scene.get('game');
+ this.sound.play('menu');
+ game.events.emit('game:restart');
+ const targets = Phaser.Math.RND.shuffle([
+ ...NonPlayerCharacter.sprites,
+ ]).slice(0, 3);
+
+ this.registry.set('targets', targets);
+ });
+
+ const targets = this.registry.get('targets');
+
+ const foundFirst = foundTarget(this.payload.found, targets[0]);
+ const foundSecond = foundTarget(this.payload.found, targets[1]);
+ const foundThird = foundTarget(this.payload.found, targets[2]);
+
+ new PlayerPoster(
+ this,
+ 70,
+ 120,
+ targets[0],
+ foundFirst.text,
+ foundFirst.color,
+ foundFirst.status
+ );
+ new PlayerPoster(
+ this,
+ 160,
+ 120,
+ targets[1],
+ foundSecond.text,
+ foundSecond.color,
+ foundSecond.status
+ );
+ new PlayerPoster(
+ this,
+ 250,
+ 120,
+ targets[2],
+ foundThird.text,
+ foundThird.color,
+ foundThird.status
+ );
+
+ this.submitScore();
+ this.submitAchievements();
+ }
+
+ submitScore() {
+ this.server.score.submit(this.payload.found.length);
+ }
+
+ submitAchievements() {
+ const achievements: string[] = [];
+ const errors = this.payload.errors;
+ const found = this.payload.found.length;
+ errors === 0 && achievements.push('hide-and-seek:perfect');
+ found >= 1 && achievements.push('hide-and-seek:found-one');
+ found >= 2 && achievements.push('hide-and-seek:found-two');
+ found >= 3 && achievements.push('hide-and-seek:found-three');
+ this.server.achievements.unlock(achievements);
+ }
+}
+
+const foundTarget = (array: string[], value: string) => {
+ if (array.includes(value)) {
+ return { text: 'Found!', color: 0x00ff00, status: 'right' as const };
+ } else {
+ return { text: 'Lost!', color: 0xff0000, status: 'wrong' as const };
+ }
+};
diff --git a/apps/games/hide-and-seek/src/scenes/game.ts b/apps/games/hide-and-seek/src/scenes/game.ts
new file mode 100644
index 00000000..44ce4277
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/game.ts
@@ -0,0 +1,102 @@
+import { Building } from '../objects/building';
+import { Camera } from '../objects/camera';
+import { Controls } from '../objects/controls';
+import { NonPlayerCharacter } from '../objects/non-player-character';
+import { Room } from '../objects/room';
+import { UserInterface } from './user-interface';
+
+export class Game extends Phaser.Scene {
+ blur?: Phaser.FX.Blur;
+ controls!: Controls;
+ building!: Building;
+ characters: NonPlayerCharacter[] = [];
+
+ constructor() {
+ super('game');
+ }
+
+ async create() {
+ this.setupEvents();
+ this.characters = [];
+
+ this.building = new Building(this);
+ Camera.create(this, this.building);
+ this.scene.launch('instructions');
+ }
+
+ spawn() {
+ for (const sprite of NonPlayerCharacter.sprites) {
+ const room = this.building.getRoom(Room.random());
+ const character = new NonPlayerCharacter(this, room, sprite);
+ this.characters.push(character);
+ character.wander();
+ }
+ }
+
+ reset() {
+ for (const character of this.characters) {
+ character.destroy();
+ }
+ this.characters = [];
+ }
+
+ setupEvents() {
+ this.events.on('game:over', (data: object) => {
+ this.scene.pause('game');
+ this.scene.stop('user-interface');
+ this.scene.launch('game-over', data);
+ });
+
+ this.events.on('game:start', () => {
+ this.scene.resume('game');
+ this.scene.stop('instructions');
+ this.scene.launch('user-interface');
+ this.spawn();
+ });
+
+ this.events.on('player:click', (npc: NonPlayerCharacter) => {
+ const targets = this.registry.get('targets');
+
+ if (targets.includes(npc.code)) {
+ npc.setStatus('right');
+ this.sound.play('right');
+ this.events.emit(UserInterface.eventPlayerFound, npc.code);
+ } else {
+ npc.setStatus('wrong');
+ this.sound.play('wrong');
+ this.events.emit(UserInterface.eventPlayerNotFound);
+ }
+ });
+
+ this.events.on('game:restart', () => {
+ this.scene.stop('game-over');
+ this.reset();
+ this.scene.launch('instructions');
+ });
+
+ this.events.on('pause', () => {
+ if (!this.blur) {
+ this.blur = this.cameras.main.postFX.addBlur(0, 1, 1, 1, 0xf1f1f1, 8);
+ }
+ });
+
+ this.events.on('resume', () => {
+ if (this.blur) {
+ this.cameras.main.postFX.remove(this.blur);
+ this.blur = undefined;
+ this.scene.launch('user-interface');
+ }
+ });
+
+ this.events.once('shutdown', () => {
+ this.events.off('resume');
+ this.events.off('pause');
+ this.events.off('revive');
+ this.events.off('player:click');
+ this.events.off('game:over');
+ this.events.off('game:start');
+ this.events.off('game:restart');
+ this.blur = undefined;
+ });
+ }
+}
diff --git a/apps/games/hide-and-seek/src/scenes/instructions.ts b/apps/games/hide-and-seek/src/scenes/instructions.ts
new file mode 100644
index 00000000..2e66b010
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/instructions.ts
@@ -0,0 +1,46 @@
+import { CreditsButton } from '../objects/credits-button';
+import { NonPlayerCharacter } from '../objects/non-player-character';
+import { PlayerPoster } from '../objects/player-poster';
+import { VolumeButton } from '../objects/volume-button';
+
+export class Instructions extends Phaser.Scene {
+ constructor() {
+ super('instructions');
+ }
+
+ create() {
+ new VolumeButton(this, 304, 16);
+ new CreditsButton(this, 16, 16);
+
+ this.add
+ .bitmapText(160, 40, 'peaberry_yellow', 'Hide and Seek', 24)
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+
+ this.add
+ .bitmapText(
+ 160,
+ 200,
+ 'peaberry_yellow',
+ `${this.sys.game.device.os.desktop ? 'Click' : 'Tap'} to Start`,
+ 18
+ )
+ .setOrigin(0.5)
+ .setDropShadow(2, 2, 0x000000, 1);
+
+ const targets = Phaser.Math.RND.shuffle([
+ ...NonPlayerCharacter.sprites,
+ ]).slice(0, 3);
+
+ this.input.on('pointerdown', () => {
+ const game = this.scene.get('game');
+ game.events.emit('game:start');
+ this.registry.set('targets', targets);
+ this.sound.play('menu');
+ });
+
+ new PlayerPoster(this, 160, 120, targets[0], 'Find');
+ new PlayerPoster(this, 70, 120, targets[1], 'Find');
+ new PlayerPoster(this, 250, 120, targets[2], 'Find');
+ }
+}
diff --git a/apps/games/hide-and-seek/src/scenes/user-interface.ts b/apps/games/hide-and-seek/src/scenes/user-interface.ts
new file mode 100644
index 00000000..253fb444
--- /dev/null
+++ b/apps/games/hide-and-seek/src/scenes/user-interface.ts
@@ -0,0 +1,491 @@
+import { NonPlayerCharacter } from '../objects/non-player-character';
+
+export class UserInterface extends Phaser.Scene {
+ static eventPlayerFound = 'player:found';
+ static eventPlayerNotFound = 'player:not-found';
+ gameScene!: Phaser.Scene;
+ find!: FindButton;
+ errors!: ErrorsButton;
+ timer!: TimerButton;
+
+ controller?: CameraController;
+ constructor() {
+ super('user-interface');
+ }
+
+ create() {
+ this.gameScene = this.scene.get('game');
+ this.createEvents(this.gameScene);
+
+ this.controller = new CameraController(this, this.gameScene);
+ this.find = new FindButton(this, -2, 194);
+ this.errors = new ErrorsButton(this, 272, 24);
+ this.timer = new TimerButton(this, -2, 24);
+ }
+
+ createEvents(game: Phaser.Scene) {
+ this.events.on('game:over', () => {
+ game.events.emit('game:over', {
+ remaining: this.timer.remainingTime,
+ errors: this.errors.num,
+ found: this.find.getFound(),
+ });
+ });
+ this.events.once('shutdown', () => {
+ this.events.off('game:over');
+ game.events.off(UserInterface.eventPlayerFound);
+ game.events.off(UserInterface.eventPlayerNotFound);
+ });
+ game.events.on(UserInterface.eventPlayerFound, (code: string) => {
+ this.find.playerFound(code);
+ });
+ game.events.on(UserInterface.eventPlayerNotFound, () => {
+ this.errors.increment();
+ });
+ }
+
+ update(time: number, delta: number) {
+ this.controller?.update(time, delta);
+ }
+}
+
+class TimerButton extends Phaser.GameObjects.Container {
+ remainingTime = 60;
+ constructor(scene: Phaser.Scene, x: number, y: number) {
+ super(scene, x, y);
+ const button = scene.add
+ .sprite(0, 0, 'button_grey_long')
+ .setOrigin(0)
+ .setScale(1, 1);
+
+ this.add(button);
+
+ const timer = scene.add
+ .bitmapText(21, 7, 'thick', '0:60', 10)
+ .setOrigin(0)
+ .setLetterSpacing(0)
+ .setDropShadow(1, 1, 0x000, 1)
+ .setTintFill(0xf9c22b);
+ this.add(timer);
+
+ scene.time.addEvent({
+ // decrease time every second
+ delay: 1000,
+ callback: () => {
+ this.remainingTime = this.remainingTime - 1;
+
+ if (this.remainingTime === 0) {
+ timer.setText('0:00');
+ scene.events.emit('game:over');
+ return;
+ }
+
+ const seconds = this.remainingTime % 60;
+ const minutes = Math.floor(this.remainingTime / 60);
+ if (seconds === 0) {
+ timer.setText(`${minutes - 1}:59`);
+ } else {
+ const padded = String(seconds - 1).padStart(2, '0');
+ timer.setText(`${minutes}:${padded}`);
+ }
+ },
+ loop: true,
+ });
+
+ this.add(scene.add.sprite(4, 6, 'siren').setOrigin(0));
+
+ scene.add.existing(this);
+ }
+}
+
+class FindButton extends Phaser.GameObjects.Container {
+ panel: FindPanel;
+ num = 0;
+ constructor(scene: Phaser.Scene, x: number, y: number) {
+ super(scene, x, y);
+ let open = false;
+ const openX = 100;
+ const initialX = x;
+ const button = scene.add
+ .sprite(-6, 0, 'button_blue_long')
+ .setOrigin(0)
+ .setScale(1.1, 1)
+ .setInteractive()
+ .on('pointerdown', () => {
+ button.setTint(0x888888);
+ //slide out to the right to show panel
+ if (open)
+ scene.tweens.add({
+ targets: this,
+ x: initialX,
+ duration: 150,
+ ease: 'Elastic.Out',
+ onComplete: () => {
+ open = false;
+ button.clearTint();
+ },
+ });
+ else
+ scene.tweens.add({
+ targets: this,
+ x: openX,
+ duration: 150,
+ ease: 'Elastic.In',
+
+ onComplete: () => {
+ open = true;
+ button.clearTint();
+ },
+ });
+ });
+ this.add(button);
+
+ this.add(scene.add.sprite(6, 5, 'tasks').setOrigin(0));
+
+ this.add(
+ scene.add
+ .bitmapText(20, 7, 'thick', 'FIND', 10)
+ .setOrigin(0)
+ .setLetterSpacing(0)
+ .setDropShadow(1, 1, 0x000, 1)
+ .setTintFill(0xf9c22b)
+ );
+
+ this.panel = new FindPanel(scene, -104, -145);
+ this.add(this.panel);
+
+ scene.add.existing(this);
+ }
+
+ playerFound(code: string) {
+ this.panel.players[code].found();
+ if (this.getFound().length === 3) this.scene.events.emit('game:over');
+ }
+
+ getFound() {
+ const found: string[] = [];
+ for (const code in this.panel.players) {
+ if (this.panel.players[code].isFound) {
+ found.push(code);
+ }
+ }
+ return found;
+ }
+}
+
+class FindPanel extends Phaser.GameObjects.Container {
+ players: Record;
+ constructor(scene: Phaser.Scene, x: number, y: number) {
+ super(scene, x, y);
+ const players = scene.registry.get('targets');
+ const panel = scene.add.sprite(0, 0, 'panel_blue').setOrigin(0).setScale(1);
+ const player1 = new FindPlayerPanelItem(scene, 30, 30, players[0]);
+ const player2 = new FindPlayerPanelItem(scene, 30, 82, players[1]);
+ const player3 = new FindPlayerPanelItem(scene, 30, 134, players[2]);
+
+ this.add(panel);
+ this.add(player1);
+ this.add(player2);
+ this.add(player3);
+
+ this.players = {
+ [players[0]]: player1,
+ [players[1]]: player2,
+ [players[2]]: player3,
+ };
+ }
+}
+
+class ErrorsButton extends Phaser.GameObjects.Container {
+ ui: UserInterface;
+ errors: Phaser.GameObjects.Sprite[];
+ num = 0;
+ constructor(ui: UserInterface, x: number, y: number) {
+ super(ui, x, y);
+ this.ui = ui;
+
+ const button = ui.add
+ .sprite(0, 0, 'button_grey_long')
+ .setOrigin(0)
+ .setScale(1, 1);
+
+ this.add(button);
+
+ const error1 = ui.add
+ .sprite(4, 6, 'cross')
+ .setOrigin(0)
+ .setTintFill(0x000000);
+ const error2 = ui.add
+ .sprite(19, 6, 'cross')
+ .setOrigin(0)
+ .setTintFill(0x000000);
+ const error3 = ui.add
+ .sprite(34, 6, 'cross')
+ .setOrigin(0)
+ .setTintFill(0x000000);
+
+ this.add(error1);
+ this.add(error2);
+ this.add(error3);
+
+ this.errors = [error1, error2, error3];
+ ui.add.existing(this);
+ }
+
+ increment() {
+ this.errors[this.num].clearTint();
+ this.num++;
+
+ if (this.num >= 3) {
+ this.ui.events.emit('game:over');
+ }
+ }
+}
+
+class FindPlayerPanelItem extends Phaser.GameObjects.Container {
+ isFound = false;
+ frame: Phaser.GameObjects.Sprite;
+ status: Phaser.GameObjects.Sprite;
+ constructor(scene: Phaser.Scene, x: number, y: number, sprite: string) {
+ super(scene, x, y);
+ this.isFound = false;
+
+ const frame = scene.add.sprite(0, 0, 'frame_white').setScale(2);
+
+ const player = scene.add
+ .sprite(0, 2, NonPlayerCharacter.image(sprite))
+ .setScale(2);
+ const status = scene.add.sprite(46, 0, 'cross').setScale(2);
+
+ this.add(frame);
+ this.add(player);
+ this.add(status);
+
+ this.frame = frame;
+ this.status = status;
+ }
+
+ found() {
+ this.frame.setTexture('frame_white_golden');
+ this.status.setTexture('check');
+ this.isFound = true;
+ }
+}
+
+class CameraController extends Phaser.GameObjects.Container {
+ speed = 0.1;
+ detector: BoundaryDetector;
+ game: Phaser.Cameras.Scene2D.Camera;
+ up: CameraButton;
+ down: CameraButton;
+ left: CameraButton;
+ right: CameraButton;
+ constructor(scene: Phaser.Scene, game: Phaser.Scene) {
+ super(scene, 0, 0);
+ const { height, width } = scene.cameras.main;
+ this.game = game.cameras.main;
+ const bounds = this.game.getBounds();
+ const offset = 16;
+
+ this.detector = new BoundaryDetector(this.game, {
+ height: bounds.height - height,
+ width: bounds.width - width,
+ });
+
+ this.up = new CameraButton(scene, width / 2, offset, 'arrow_up');
+ this.down = new CameraButton(
+ scene,
+ width / 2,
+ height - offset,
+ 'arrow_down'
+ );
+ this.left = new CameraButton(scene, offset, height / 2, 'arrow_left');
+ this.right = new CameraButton(
+ scene,
+ width - offset,
+ height / 2,
+ 'arrow_right'
+ );
+
+ scene.add.existing(this);
+ this.setupDetector();
+ this.setupButtons();
+ }
+
+ setupDetector() {
+ this.detector.onTop = () => {
+ this.up.disable();
+ };
+
+ this.detector.offTop = () => {
+ this.up.enable();
+ };
+
+ this.detector.onBottom = () => {
+ this.down.disable();
+ };
+
+ this.detector.offBottom = () => {
+ this.down.enable();
+ };
+
+ this.detector.onLeft = () => {
+ this.left.disable();
+ };
+
+ this.detector.offLeft = () => {
+ this.left.enable();
+ };
+
+ this.detector.onRight = () => {
+ this.right.disable();
+ };
+
+ this.detector.offRight = () => {
+ this.right.enable();
+ };
+ }
+
+ setupButtons() {
+ this.up.onDown = (delta) => {
+ this.game.scrollY -= 0.1 * delta;
+ };
+ this.down.onDown = (delta) => {
+ this.game.scrollY += 0.1 * delta;
+ };
+ this.left.onDown = (delta) => {
+ this.game.scrollX -= 0.1 * delta;
+ };
+ this.right.onDown = (delta) => {
+ this.game.scrollX += 0.1 * delta;
+ };
+
+ this.add(this.up);
+ this.add(this.down);
+ this.add(this.left);
+ this.add(this.right);
+ }
+
+ update(time: number, delta: number) {
+ this.detector.update();
+ this.list.forEach((child) => {
+ if (child instanceof CameraButton) {
+ child.update(time, delta);
+ }
+ });
+ }
+}
+
+class CameraButton extends Phaser.GameObjects.Sprite {
+ onDown?: (delta: number) => void;
+ isDown: boolean;
+
+ constructor(scene: Phaser.Scene, x: number, y: number, texture: string) {
+ super(scene, x, y, texture);
+ this.isDown = false;
+ this.setScale(2);
+ this.setOrigin(0.5);
+ this.setInteractive();
+ this.on('pointerdown', () => {
+ this.isDown = true;
+ });
+ this.on('pointerup', () => {
+ this.isDown = false;
+ });
+ this.on('pointerout', () => {
+ this.isDown = false;
+ });
+ }
+
+ disable() {
+ this.removeInteractive();
+ this.setVisible(false);
+ this.isDown = false;
+ }
+
+ enable() {
+ this.setInteractive();
+ this.setVisible(true);
+ this.isDown = false;
+ }
+
+ update(_: number, delta: number) {
+ if (this.isDown && this.onDown) {
+ this.onDown(delta);
+ }
+ }
+}
+
+class BoundaryDetector {
+ onLeft?: () => void;
+ offLeft?: () => void;
+ onRight?: () => void;
+ offRight?: () => void;
+ onTop?: () => void;
+ offTop?: () => void;
+ onBottom?: () => void;
+ offBottom?: () => void;
+
+ isLeft = false;
+ isRight = false;
+ isTop = false;
+ isBottom = false;
+
+ constructor(
+ private scene: Phaser.Cameras.Scene2D.Camera,
+ private bounds: { height: number; width: number }
+ ) {}
+
+ update() {
+ // left;
+ if (this.scene.scrollX <= 0) {
+ if (!this.isLeft) {
+ this.isLeft = true;
+ this.onLeft?.();
+ }
+ } else if (this.scene.scrollX >= 0) {
+ if (this.isLeft) {
+ this.isLeft = false;
+ this.offLeft?.();
+ }
+ }
+
+ // top
+ if (this.scene.scrollY <= 0) {
+ if (!this.isTop) {
+ this.isTop = true;
+ this.onTop?.();
+ }
+ } else if (this.scene.scrollY >= 0) {
+ if (this.isTop) {
+ this.isTop = false;
+ this.offTop?.();
+ }
+ }
+ // right
+ if (this.scene.scrollX >= this.bounds.width) {
+ if (!this.isRight) {
+ this.isRight = true;
+ this.onRight?.();
+ }
+ } else if (this.scene.scrollX <= this.bounds.width) {
+ if (this.isRight) {
+ this.isRight = false;
+ this.offRight?.();
+ }
+ }
+
+ // bottom
+ if (this.scene.scrollY >= this.bounds.height) {
+ if (!this.isBottom) {
+ this.isBottom = true;
+ this.onBottom?.();
+ }
+ } else if (this.scene.scrollY <= this.bounds.height) {
+ if (this.isBottom) {
+ this.isBottom = false;
+ this.offBottom?.();
+ }
+ }
+ }
+}
diff --git a/apps/games/hide-and-seek/src/styles.css b/apps/games/hide-and-seek/src/styles.css
new file mode 100644
index 00000000..92da31f9
--- /dev/null
+++ b/apps/games/hide-and-seek/src/styles.css
@@ -0,0 +1,22 @@
+body,
+html {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ overflow: hidden;
+ margin: 0px;
+ position: relative;
+ touch-action: none;
+ /* background: linear-gradient(180deg, #fff -10%, #d0eeff 110%); */
+}
+canvas {
+ margin: auto;
+}
+
+@font-face {
+ font-family: 9x13;
+ src: url('/assets/fonts/9x13.ttf');
+ font-weight: 400;
+ font-weight: normal;
+}
diff --git a/apps/games/hide-and-seek/src/types.ts b/apps/games/hide-and-seek/src/types.ts
new file mode 100644
index 00000000..4a56727b
--- /dev/null
+++ b/apps/games/hide-and-seek/src/types.ts
@@ -0,0 +1,14 @@
+export type Coordinate = {
+ x: number;
+ y: number;
+};
+export type Line = { p1: Coordinate; p2: Coordinate };
+
+export type PointObject = { name: string; x: number; y: number };
+export type RectangleObject = {
+ name: string;
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+};
diff --git a/apps/games/hide-and-seek/src/util.ts b/apps/games/hide-and-seek/src/util.ts
new file mode 100644
index 00000000..6d00cc55
--- /dev/null
+++ b/apps/games/hide-and-seek/src/util.ts
@@ -0,0 +1,20 @@
+export const DEBUGGING = false;
+export const TILE_SIZE = 16;
+
+export enum Depths {
+ BACKGROUND = 0,
+ INTERACTING = 1,
+ FOREGROUND = 2,
+ PLAYER = 3,
+}
+
+export enum MovementSpeed {
+ WALKING = 'walking',
+ CLIMBING = 'climbing',
+}
+
+export const CHARACTER_SPEEDS: Record = {
+ climbing: 0.02,
+ walking: 0.04,
+};
+export const GAME_VERSION = 'v1.0.1';
diff --git a/apps/games/hide-and-seek/tsconfig.app.json b/apps/games/hide-and-seek/tsconfig.app.json
new file mode 100644
index 00000000..357ad000
--- /dev/null
+++ b/apps/games/hide-and-seek/tsconfig.app.json
@@ -0,0 +1,9 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../../dist/out-tsc",
+ "types": ["node"]
+ },
+ "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"],
+ "include": ["src/**/*.ts"]
+}
diff --git a/apps/games/hide-and-seek/tsconfig.json b/apps/games/hide-and-seek/tsconfig.json
new file mode 100644
index 00000000..715e5cd6
--- /dev/null
+++ b/apps/games/hide-and-seek/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "files": [],
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ESNext", "DOM"],
+ "moduleResolution": "Node",
+ "strict": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "noEmit": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "skipLibCheck": true,
+ "types": ["vite/client"]
+ },
+ "include": ["src"],
+ "references": [
+ {
+ "path": "./tsconfig.app.json"
+ }
+ ]
+}
diff --git a/apps/games/hide-and-seek/vite.config.mts b/apps/games/hide-and-seek/vite.config.mts
new file mode 100644
index 00000000..9adfa3f8
--- /dev/null
+++ b/apps/games/hide-and-seek/vite.config.mts
@@ -0,0 +1,32 @@
+///
+import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
+import dotenv from 'dotenv';
+import { defineConfig } from 'vite';
+
+dotenv.config({
+ path: '.env',
+});
+
+export default defineConfig({
+ root: __dirname,
+ cacheDir: '../../../node_modules/.vite/apps/games/hide-and-seek',
+ base: './', // Use relative paths for all assets
+ define: {
+ 'process.env': process.env,
+ },
+ server: {
+ port: 7012,
+ host: 'localhost',
+ },
+
+ plugins: [nxViteTsPaths()],
+
+ build: {
+ outDir: '../../../dist/apps/games/hide-and-seek',
+ emptyOutDir: true,
+ reportCompressedSize: true,
+ commonjsOptions: {
+ transformMixedEsModules: true,
+ },
+ },
+});
diff --git a/libs/data/games/src/index.ts b/libs/data/games/src/index.ts
index 3cc74698..6e9dd68e 100644
--- a/libs/data/games/src/index.ts
+++ b/libs/data/games/src/index.ts
@@ -11,6 +11,32 @@ import {
import { SeedableGameSchema } from '@worksheets/util/types';
const integratedGames: SeedableGameSchema[] = [
+ {
+ version: 1,
+ id: 'hide-and-seek',
+ name: 'Hide and Seek',
+ developerId: 'charity-games',
+ iconUrl:
+ 'https://cdn.charity.games/_games/hide-and-seek/assets/thumbnail.png',
+ bannerUrl:
+ 'https://cdn.charity.games/_games/hide-and-seek/assets/banner.png',
+ viewport: viewports['ALL-DEVICES'],
+ categories: ['1p', 'brain', 'puzzle', 'mobile', 'desktop', 'educational'],
+ file: {
+ type: 'HTML',
+ url: 'https://cdn.charity.games/_games/hide-and-seek/index.html',
+ },
+ markets: {},
+ createdAt: new Date('2024-08-01T00:00:00.000Z'),
+ updatedAt: new Date('2024-08-01T00:00:00.000Z'),
+ description:
+ "Hide and Seek is a puzzle game where you must find the hidden characters in the scene. You are given 60 seconds to find three unique characters. If you cannot find all three you'll lose the game. If you make too many mistakes you'll lose the game! Can you find all the hidden players in time?
",
+ multiplier: 1,
+ leaderboard: false,
+ cloudStorage: true,
+ loot: [],
+ achievements: [],
+ },
{
version: 3,
id: 'tall-tower',
diff --git a/libs/phaser/plugins/src/lib/charity-games.ts b/libs/phaser/plugins/src/lib/charity-games.ts
index ca16a8fe..50bf6eec 100644
--- a/libs/phaser/plugins/src/lib/charity-games.ts
+++ b/libs/phaser/plugins/src/lib/charity-games.ts
@@ -32,6 +32,7 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin {
session: SessionAPI;
achievements: AchievementsAPI;
leaderboard: LeaderboardsAPI;
+ score: LeaderboardsAPI;
advertisements: AdvertisementsAPI;
rewards: RewardAPI;
events: Phaser.Events.EventEmitter = new Phaser.Events.EventEmitter();
@@ -44,7 +45,7 @@ export class CharityGamesPlugin extends Phaser.Plugins.BasePlugin {
this.session = new SessionAPI(this);
this.achievements = new AchievementsAPI(this);
this.advertisements = new AdvertisementsAPI(this);
- this.leaderboard = new LeaderboardsAPI(this);
+ this.score = this.leaderboard = new LeaderboardsAPI(this);
this.rewards = new RewardAPI(this);
}
diff --git a/libs/services/leaderboards/src/index.ts b/libs/services/leaderboards/src/index.ts
index 9358c86e..3d70f1e3 100644
--- a/libs/services/leaderboards/src/index.ts
+++ b/libs/services/leaderboards/src/index.ts
@@ -56,13 +56,16 @@ export const submitScore = async (
}
const gameId = game.id;
- await db.gameScore.create({
- data: {
- userId,
- gameId,
- score,
- },
- });
+ if (game.leaderboard) {
+ console.info('Saving user score to leaderboard', { gameId, userId, score });
+ await db.gameScore.create({
+ data: {
+ userId,
+ gameId,
+ score,
+ },
+ });
+ }
const tokens = Math.floor(score * game.multiplier);
diff --git a/libs/services/raffles/src/util/winners.test.ts b/libs/services/raffles/src/util/winners.test.ts
index fdd566da..505abcee 100644
--- a/libs/services/raffles/src/util/winners.test.ts
+++ b/libs/services/raffles/src/util/winners.test.ts
@@ -10,7 +10,7 @@ const sampleUsers: RaffleEntry['user'][] = arrayFromNumber(10).map((i) => ({
jest.retryTimes(3);
describe('pickWinners', () => {
- test('should pick winners', () => {
+ it('should pick winners', () => {
const frequency: Record = {};
for (let i = 0; i < 1000; i++) {
const result = pickWinners(
@@ -28,7 +28,7 @@ describe('pickWinners', () => {
// it might be catastrophic if this test fails, but it's not impossible
// and therefore can be flaky
expect(Object.keys(frequency)).toHaveLength(10);
- expect(Object.values(frequency).every((v) => v > 50)).toBe(true);
+ expect(Object.values(frequency).every((v) => v > 70)).toBe(true);
});
describe("when there aren't enough unique participants", () => {
it('cannot pick more winners than participants', () => {
diff --git a/libs/util/arrays/src/lib/arrays.spec.ts b/libs/util/arrays/src/lib/arrays.spec.ts
index bf5a563e..9a7a8f63 100644
--- a/libs/util/arrays/src/lib/arrays.spec.ts
+++ b/libs/util/arrays/src/lib/arrays.spec.ts
@@ -1,4 +1,6 @@
-import { checkboxGroup } from './arrays';
+import { cloneDeep } from 'lodash';
+
+import { checkboxGroup, frequency, shuffle } from './arrays';
describe('checkboxGroup', () => {
// does not modify original array.
@@ -33,3 +35,24 @@ describe('checkboxGroup', () => {
expect(result).toEqual(expectedOutput);
});
});
+
+describe('shuffle', () => {
+ it.skip('should shuffle an array', () => {
+ const original = [1, 2, 3, 4, 5];
+ const shuffled = shuffle(original);
+
+ expect(shuffled).not.toEqual(original);
+ });
+ it.skip('should create a near average distribution', () => {
+ const original = [1, 2, 3, 4, 5];
+
+ const results = Array.from({ length: 1000000 }, () =>
+ shuffle(cloneDeep(original))
+ );
+ const first = results.map((r) => r[0]);
+ const firstFrequency = frequency(first);
+
+ console.log('firstFrequency', firstFrequency);
+ expect(Object.keys(firstFrequency).length).toEqual(5);
+ });
+});
diff --git a/libs/util/arrays/src/lib/arrays.ts b/libs/util/arrays/src/lib/arrays.ts
index 2e52df6e..40d2b04a 100644
--- a/libs/util/arrays/src/lib/arrays.ts
+++ b/libs/util/arrays/src/lib/arrays.ts
@@ -49,3 +49,12 @@ export const lottery = (
);
return randomArrayElement(total);
};
+
+export const frequency = (
+ arr: T[]
+): Record => {
+ return arr.reduce((acc, curr) => {
+ acc[curr] = (acc[curr] || 0) + 1;
+ return acc;
+ }, {} as Record);
+};