diff --git a/package-lock.json b/package-lock.json
index a4d67bb..ad32ec0 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "denim_3001",
- "version": "3001.61.3",
+ "version": "3001.62.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "denim_3001",
- "version": "3001.61.2",
+ "version": "3001.62.0",
"license": "ISC",
"dependencies": {
"@discordjs/voice": "^0.17.0",
diff --git a/package.json b/package.json
index 14b2b57..edbd7ba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "denim_3001",
- "version": "3001.61.3",
+ "version": "3001.62.0",
"description": "Toto je velmi kvalitní bot.",
"repository": {
"url": "https://github.com/Histmy/Denim-Bot/"
diff --git a/res/sachy/game.html b/res/sachy/game.html
new file mode 100644
index 0000000..6d74a94
--- /dev/null
+++ b/res/sachy/game.html
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+ Hra - $domena
+
+
+
+
+
+ Hra
+
+ $pecko
+
+
+
+
+
diff --git a/src/modules/sachy.ts b/src/modules/sachy.ts
index ee3364b..e6d7713 100644
--- a/src/modules/sachy.ts
+++ b/src/modules/sachy.ts
@@ -98,7 +98,7 @@ function jeCheck(barva: Hra["hraje"], deska: Deska) {
// od pawnů
[7, 9].forEach(i => {
const pis = deska[index - i];
- if (pis?.typ == "pawn" && pis.barva != barva) check = true;
+ if (pis?.typ == "pawn" && pocetKeStrane[index][i == 7 ? 1 : 3] > 0 && pis.barva != barva) check = true;
});
// od králika
@@ -173,6 +173,13 @@ function tahyProPawny(index: number, deska: Deska) {
if (index % 8 != 7 && deska[index - 7] && deska[index - 7]!.barva != barva)
tahy.push(index - 7);
+ // en croassant
+ if (pocetKeStrane[index][3] > 0 && deska[index - 1]?.enPassantovatelna)
+ tahy.push(index - 9);
+
+ if (pocetKeStrane[index][1] > 0 && deska[index + 1]?.enPassantovatelna)
+ tahy.push(index - 7);
+
// Blokáda
if (deska[index - 8])
return tahy;
@@ -183,13 +190,6 @@ function tahyProPawny(index: number, deska: Deska) {
if (deska[index]?.netahnuta && !deska[index - 16])
tahy.push(index - 16);
- // en croassant
- if (deska[index - 1]?.enPassantovatelna)
- tahy.push(index - 9);
-
- if (deska[index + 1]?.enPassantovatelna)
- tahy.push(index - 7);
-
return tahy;
}
@@ -218,6 +218,8 @@ function tahyProKrale(index: number, deska: Deska) {
break;
}
+ if (Math.abs(i) == 3) continue;
+
const novaDeska = [...deska];
novaDeska[index + i] = deska[index];
novaDeska[index] = undefined;
@@ -302,6 +304,45 @@ function renderHra(hra: Hra, konec?: true) {
const deska = [...hra.deska];
const vybranejPis = hra.vybranejPis;
+ const policka: Policko[] = [];
+
+ hra.tahy = [];
+
+ if (typeof vybranejPis == "number") hra.tahy = legalniTahy(vybranejPis, deska);
+
+ for (let i = 0; i < 64; i++) {
+
+ const figurka = deska[i];
+ const jeTah = hra.tahy.includes(i);
+
+ const cernyPozadi = (Math.floor(i / 8) + (i % 8)) % 2;
+
+ if (!figurka) {
+
+ policka.push(jeTah
+ ? { typ: "tahnutelne", emoutId: cernyPozadi ? "1066376051422404628" : "1066376343807336488" }
+ : { typ: "prazdne", barva: cernyPozadi ? "cerna" : "bila" }
+ );
+
+ } else {
+
+ let klic = (cernyPozadi ? "g" : "w") + (figurka.barva == "bila" ? "w" : "b") + figurka.typ;
+ if (jeTah) klic += "t";
+ else if (figurka.typ == "king" && figurka.barva == hra.hraje && jeCheck(figurka.barva, deska)) klic += "c";
+ const emoutId = fokinLookupTable[klic];
+
+ const tahnutelny = !konec && figurka.barva == hra.hraje || jeTah;
+ policka.push({ emoutId, typ: tahnutelny ? "tahnutelne" : "figurka" });
+
+ }
+
+ }
+
+ return policka;
+}
+
+function generateGameEmbed(hra: Hra, konec?: true) {
+
const embed: APIEmbed = {
fields: [
{
@@ -317,51 +358,64 @@ function renderHra(hra: Hra, konec?: true) {
]
};
- hra.tahy = [];
-
- if (typeof vybranejPis == "number") hra.tahy = legalniTahy(vybranejPis, deska);
+ const policka = renderHra(hra, konec);
for (let i = 0; i < 64; i++) {
- const figurka = deska[i];
- const klikanec = klikance[i];
-
- const prvniDuhy = (i % 8) < 4 ? 0 : 1;
- const field = embed.fields![prvniDuhy];
-
- const cernyPozadi = (Math.floor(i / 8) + (i % 8)) % 2;
-
- if (!figurka) {
-
- field.value += hra.tahy.includes(i)
- ? (cernyPozadi ? `[<:h:1066376051422404628>](http://${sachyDomena}/${klikanec})` : `[<:h:1066376343807336488>](http://${sachyDomena}/${klikanec})`)
- : (cernyPozadi ? "🟩" : "⬜");
-
- } else {
-
- let klic = (cernyPozadi ? "g" : "w") + (figurka.barva == "bila" ? "w" : "b") + figurka.typ;
- if (hra.tahy.includes(i)) klic += "t";
- if (figurka.typ == "king" && figurka.barva == hra.hraje && jeCheck(figurka.barva, deska)) klic += "c";
- const emout = fokinLookupTable[klic];
- const figurkaStr = `<:h:${emout}>`;
-
- if (!konec && figurka.barva == hra.hraje || hra.tahy.includes(i)) {
- field.value += `[${figurkaStr}](http://${sachyDomena}/${klikanec})`;
- } else {
- field.value += figurkaStr;
- }
+ const policko = policka[i];
+ const field = embed.fields![(i % 8) < 4 ? 0 : 1];
+ if (policko.typ == "prazdne")
+ field.value += policko.barva == "bila" ? "⬜" : "🟩";
+ else {
+ const emout = `<:h:${policko.emoutId}>`;
+ field.value += policko.typ == "figurka" ? emout : `[${emout}](http://${sachyDomena}/${klikance[i]})`;
}
- if (i % 8 == 3 || i % 8 == 7) field.value += "\n";
+ if ((i % 8 == 3 || i % 8 == 7)) field.value += "\n";
+ }
+ if (embed.fields![0].value.length > 1024 || embed.fields![1].value.length > 1024) {
+ embed.fields = [
+ {
+ name: "a je to pici!",
+ value: `Tuta pozice by vobsahovala moc vodkazu a diky pice diskordu se teda neda vykreslit. Tuten tah budes muset bohuzel vodehrat [na webu](http://${sachyDomena}/play).`
+ }
+ ];
}
return embed;
}
+emiter.on("render", (hrac, respond) => {
+ const gameID = hraci.get(hrac)!;
+ if (!gameID) return respond("Však vůbec nehraješ ty magore", true);
+ const hra = hry.get(gameID)!;
+ const hraje = hra.hraje == (hra.bila == hrac ? "bila" : "cerna");
+
+ const policka = renderHra(hra);
+ let html = "";
+
+
+ for (let i = 0; i < 64; i++) {
+ const policko = policka[i];
+
+ if (policko.typ == "prazdne")
+ html += policko.barva == "bila" ? ` | ` : ` | `;
+ else {
+ const obrazek = `
`;
+ html += (policko.typ == "figurka" || !hraje) ? `${obrazek} | ` : `${obrazek} | `;
+ }
+
+ if (i % 8 == 7) html += "
";
+ }
+
+ respond(html);
+
+});
+
function konec(mes: Message, hra: Hra, duvod: string) {
- mes.edit({ content: `hra zkoncila ${duvod}`, embeds: [renderHra(hra, true)] });
+ mes.edit({ content: `hra zkoncila ${duvod}`, embeds: [generateGameEmbed(hra, true)] });
const gameID = hra.id;
@@ -399,7 +453,7 @@ function prekreslitHru(hra: Hra) {
if (pat)
return konec(mes, hra, `achylova sytuace`);
- mes.edit({ content: "", embeds: [renderHra(hra)] });
+ mes.edit({ content: "", embeds: [generateGameEmbed(hra)] });
}
emiter.on("tah", (hrac, policko, respond, promo) => {
@@ -412,7 +466,7 @@ emiter.on("tah", (hrac, policko, respond, promo) => {
const index = klikance.findIndex(e => e == policko);
- if (typeof index != "number") return respond("Co to meleš za hovna?");
+ if (index == -1) return respond("Co to meleš za hovna?");
// Kliknul na stejnej pis
if (hra.vybranejPis == index) {
@@ -485,7 +539,7 @@ const exp: Modul = {
hraci.set(mes.author.id, nextGameID);
hraci.set(druhej, nextGameID);
- message.edit({ content: "", embeds: [renderHra(hra)] });
+ message.edit({ content: "", embeds: [generateGameEmbed(hra)] });
}
},
@@ -510,7 +564,7 @@ type Hra = {
bila: string;
cerna: string;
deska: Deska;
- hraje: "bila" | "cerna";
+ hraje: Figurka["barva"];
tahy: number[];
vybranejPis?: number;
message: Message;
@@ -524,3 +578,11 @@ type Figurka = {
netahnuta: boolean;
enPassantovatelna: boolean;
};
+
+type Policko = {
+ typ: "prazdne";
+ barva: Figurka["barva"];
+} | {
+ typ: "figurka" | "tahnutelne";
+ emoutId: string;
+};
diff --git a/src/utils/sachyServer.ts b/src/utils/sachyServer.ts
index 32b0c01..aa208de 100644
--- a/src/utils/sachyServer.ts
+++ b/src/utils/sachyServer.ts
@@ -14,11 +14,13 @@ const indexStranka = readFileSync(`${basePath}/index.html`).toString();
const tahStranka = readFileSync(`${basePath}/tah.html`).toString();
const promoStranka = readFileSync(`${basePath}/promotion.html`).toString();
const chybaStranka = readFileSync(`${basePath}/error.html`).toString();
+const hraStranka = readFileSync(`${basePath}/game.html`).toString();
export const sachyDomena = process.env.sachyDomena ?? "šach.ml";
interface Eventy {
tah: (playerId: string, square: string, verify: (err?: string) => void, promotionType?: string) => void;
+ render: (playerId: string, send: (html: string, err?: true) => void) => void;
}
export const emiter = new TypedEmitter();
@@ -101,9 +103,9 @@ function loginErr(res: ServerResponse) {
);
}
-async function overeni(url: string, session: Session, res: ServerResponse) {
+async function overeni(url: URL, session: Session, res: ServerResponse) {
- const code = (new URL(url, "h:/")).searchParams.get("code");
+ const code = url.searchParams.get("code");
const data = await fetch("https://discord.com/api/v10/oauth2/token", { method: "post", body: `client_id=1064269692165963826&client_secret=8HHKODmb1HTLWoJGVyoinSU_9323dEla&grant_type=authorization_code&code=${code}&redirect_uri=http%3A%2F%2F${encodeURIComponent(sachyDomena)}%2Foauth`, headers: { "Content-type": "application/x-www-form-urlencoded" } })
.then(r => r.json())
.catch(err => log("sachy jednotka:", err));
@@ -146,16 +148,48 @@ function validateMove(res: ServerResponse, session: Session, url: string) {
emiter.emit("tah", session.discordId!, pismenko, overeni, promoNa);
}
+function renderHra(url: URL, session: Session, res: ServerResponse) {
+ if (!session.logedIn) return redirect(res, `/login?redirect=/play${url.search}`);
+
+ let error: string | undefined = undefined;
+
+ function serveHTML(html: string, err?: true) {
+ const vec = hraStranka
+ .replace("$domena", sachyDomena);
+
+ let errForPrint = error ?? err;
+ if (errForPrint) return res.end(vec.replace("$pecko", html).replace("$hra", ""));
+
+ res.end(vec.replace("$hra", html).replace("$pecko", ""));
+ }
+
+ const tah = url.pathname.match(/\/play\/(.)$/);
+ if (!tah) return emiter.emit("render", session.discordId!, serveHTML);
+ const promoNa = url.search[1];
+
+ function handlePromote(err?: string) {
+ if (err == "--promote--")
+ return res.end(promoStranka.replace("$domena", sachyDomena));
+
+ error = err;
+ emiter.emit("render", session.discordId!, serveHTML);
+ }
+ emiter.emit("tah", session.discordId!, tah[1], handlePromote, promoNa);
+
+}
+
const server = createServer((req, res) => {
const session = startSession(req, res);
const url = new URL(req.url!, `http://${sachyDomena}`);
+ // log(url.pathname, url.search, url.searchParams, req.url);
+
// Zpracování tahu
if (url.pathname.length == 2 || url.pathname.length == 4) return validateMove(res, session, req.url!);
- // Oauth
- if (req.url?.startsWith("/oauth")) return overeni(req.url, session, res);
+ // Hra v prohlížeči
+ if (url.pathname.startsWith("/play")) return renderHra(url, session, res);
// Jinak
switch (url.pathname) {
@@ -172,6 +206,9 @@ const server = createServer((req, res) => {
return login(session, res);
}
+ case "/oauth":
+ return overeni(url, session, res);
+
case "/logout":
return logout(session, res);
diff --git a/src/utils/statuslog.ts b/src/utils/statuslog.ts
index 3cec61c..828a7ee 100644
--- a/src/utils/statuslog.ts
+++ b/src/utils/statuslog.ts
@@ -55,7 +55,7 @@ const statusTable: SRecord = {
export function statusToDLOG3(status: ClientPresenceStatusData | null) {
if (!status) return "-";
- let tovje = [];
+ const tovje = [];
for (const [key, value] of Object.entries(status)) {
const platform = platformTable[key] ?? key;