aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Reeder2022-04-19 22:09:46 -0600
committerColin Reeder2022-04-19 22:09:46 -0600
commit239e2e7cc1e3604a0d8986e17b4c30f89f3b9e91 (patch)
tree3389aca9cd06d021321f69aea90917e8410cf227
parente6471f3af5b9d008e2327995a92cc56402bc8baa (diff)
downloadaur-239e2e7cc1e3604a0d8986e17b4c30f89f3b9e91.tar.gz
Update to 7.15.2, use fairy-stockfish for offline play
-rw-r--r--.SRCINFO15
-rw-r--r--PKGBUILD27
-rw-r--r--README.md2
-rw-r--r--index.js9
-rw-r--r--native-stockfish.patch152
-rw-r--r--preload.js27
6 files changed, 218 insertions, 14 deletions
diff --git a/.SRCINFO b/.SRCINFO
index ec9fdc72bfd8..1dda7993ce61 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,20 +1,23 @@
pkgbase = lichobile-electron
pkgdesc = lichess.org mobile application, packaged with electron
- pkgver = 7.11.3
- pkgrel = 3
+ pkgver = 7.15.2
+ pkgrel = 4
url = https://lichess.org/mobile
arch = any
license = GPL-3.0-or-later
makedepends = npm
- depends = electron
- source = https://github.com/veloce/lichobile/archive/refs/tags/v7.11.3.tar.gz
+ source = https://github.com/veloce/lichobile/archive/refs/tags/v7.15.2.tar.gz
source = appconfig.prod.json
source = run.sh
source = lichobile-electron.desktop
source = lichesslogowhite.svg
source = hide-scrollbar.patch
+ source = native-stockfish.patch
source = index.js
- sha256sums = 27719c7be577931e8b2020d6e27760a00982b55efd1d6a507128e0f2168224a6
+ source = preload.js
+ sha256sums = 62d2922ee28d706e7a164629e41e516d203772fc69a3f7a30dc19239f2fb352b
+ sha256sums = SKIP
+ sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
sha256sums = SKIP
@@ -23,3 +26,5 @@ pkgbase = lichobile-electron
sha256sums = SKIP
pkgname = lichobile-electron
+ depends = electron
+ depends = fairy-stockfish
diff --git a/PKGBUILD b/PKGBUILD
index 264c5cd823cb..e7976e35efce 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,23 +1,34 @@
+shopt -s globstar
+
_pkgname=lichobile
pkgname="$_pkgname-electron"
-pkgver=7.11.3
-pkgrel=3
+pkgver=7.15.2
+pkgrel=4
pkgdesc="lichess.org mobile application, packaged with electron"
arch=(any)
url="https://lichess.org/mobile"
license=("GPL-3.0-or-later")
-depends=(electron)
makedepends=(npm)
-source=("https://github.com/veloce/lichobile/archive/refs/tags/v$pkgver.tar.gz" "appconfig.prod.json" "run.sh" "lichobile-electron.desktop" "lichesslogowhite.svg" "hide-scrollbar.patch" "index.js")
-sha256sums=("27719c7be577931e8b2020d6e27760a00982b55efd1d6a507128e0f2168224a6" "SKIP" "SKIP" "SKIP" "SKIP" "SKIP" "SKIP")
+source=("https://github.com/veloce/lichobile/archive/refs/tags/v$pkgver.tar.gz" "appconfig.prod.json" "run.sh" "lichobile-electron.desktop" "lichesslogowhite.svg" "hide-scrollbar.patch" "native-stockfish.patch" "index.js" "preload.js")
+sha256sums=('62d2922ee28d706e7a164629e41e516d203772fc69a3f7a30dc19239f2fb352b'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP'
+ 'SKIP')
prepare() {
cd "$_pkgname-$pkgver"
- npm install
cp ../appconfig.prod.json ./
patch -Np1 -i ../hide-scrollbar.patch
+ patch -Np1 -i ../native-stockfish.patch
+
+ npm install
}
build() {
@@ -26,6 +37,8 @@ build() {
}
package() {
+ depends=(electron fairy-stockfish)
+
cd "$_pkgname-$pkgver"
install -d "$pkgdir"/usr/share/webapps/$_pkgname
@@ -37,6 +50,6 @@ package() {
install -Dm644 -t "$pkgdir"/usr/share/applications ../lichobile-electron.desktop
install -Dm644 -t "$pkgdir"/usr/share/icons/hicolor/scalable/apps ../lichesslogowhite.svg
- install -Dm644 -t "$pkgdir"/usr/lib/$pkgname ../index.js
+ install -Dm644 -t "$pkgdir"/usr/lib/$pkgname ../index.js ../preload.js
ln -s /usr/share/webapps/$_pkgname "$pkgdir"/usr/lib/$pkgname/www
}
diff --git a/README.md b/README.md
index 8d27da60637b..b3992317cdd1 100644
--- a/README.md
+++ b/README.md
@@ -5,4 +5,4 @@ A set of files to allow the lichess mobile app to run on linux mobile platforms
Currently an Arch package is provided, but it should be possible to do something similar for other distros.
## Known Issues
-- Local Stockfish doesn't work
+- AI sometimes plays multiple moves in offline games
diff --git a/index.js b/index.js
index fb2b3672d4d7..ba5fa395046c 100644
--- a/index.js
+++ b/index.js
@@ -1,7 +1,14 @@
const { app, BrowserWindow } = require("electron");
+const path = require("path");
app.whenReady().then(() => {
- const mainWindow = new BrowserWindow({autoHideMenuBar: true, backgroundColor: "#161512"});
+ const mainWindow = new BrowserWindow({
+ autoHideMenuBar: true,
+ backgroundColor: "#161512",
+ webPreferences: {
+ preload: path.join(app.getAppPath(), "preload.js"),
+ },
+ });
mainWindow.loadFile("www/index.html");
mainWindow.webContents.session.webRequest.onBeforeSendHeaders(
{urls: ["wss://socket.lichess.org/*"]},
diff --git a/native-stockfish.patch b/native-stockfish.patch
new file mode 100644
index 000000000000..8457babc9669
--- /dev/null
+++ b/native-stockfish.patch
@@ -0,0 +1,152 @@
+diff --git a/src/stockfish/index.ts b/src/stockfish/index.ts
+index 75cf3ec01..0adb23643 100644
+--- a/src/stockfish/index.ts
++++ b/src/stockfish/index.ts
+@@ -1,58 +1,69 @@
+-import { Capacitor, registerPlugin } from '@capacitor/core'
+-import { Stockfish, StockfishPlugin as IStockfishPlugin } from 'capacitor-stockfish'
+ import { VariantKey } from '../lichess/interfaces/variant'
+-import settings from '../settings'
+
+-export const StockfishVariants = registerPlugin<IStockfishPlugin>('StockfishVariants', {
+- web: () => import('./StockfishVariantsWeb').then(m => new m.StockfishVariantsWeb()),
+-})
++// stub for externally used functionality
++export const StockfishVariants = {
++ getMaxMemory: () => Promise.reject("unimplemented"),
++ getCPUArch: () => Promise.reject("unimplemented"),
++};
++
++interface INativeEngine {
++ send(line: string): void;
++ addListener(listener: (line: string) => void): void;
++ removeListener(listener: (line: string) => void): void;
++ kill(): boolean;
++}
++
++declare const startStockfish: () => INativeEngine;
+
+ export class StockfishPlugin {
+- private plugin: IStockfishPlugin
++ private engine: INativeEngine | undefined
++ private startPromise: Promise<{ engineName: string }> | undefined
+
+ constructor(readonly variant: VariantKey) {
+- this.plugin = !this.isVariant() &&
+- canUseNNUE() &&
+- settings.analyse.cevalUseNNUE() ? Stockfish : StockfishVariants
+ }
+
+ public async start(): Promise<{ engineName: string }> {
+- return new Promise((resolve) => {
+- let engineName = 'Stockfish'
+- const listener = (e: Event) => {
+- const line = (e as any).output
+- console.debug('[stockfish >>] ' + line)
+- if (line.startsWith('id name ')) {
+- engineName = line.substring('id name '.length)
+- }
+- if (line.startsWith('uciok')) {
+- window.removeEventListener('stockfish', listener, false)
+- resolve({ engineName })
+- }
+- }
+- window.addEventListener('stockfish', listener, { passive: true })
+- this.plugin.start()
+- .then(() => this.send('uci'))
+- })
++ console.log('trying to start stockfish')
++ if(typeof this.startPromise === 'undefined') {
++ this.startPromise = new Promise<{engineName: string}>((resolve) => {
++ let engineName = 'Stockfish'
++ this.engine = startStockfish();
++
++ const listener = (line: string) => {
++ console.debug('[stockfish >>] ' + line)
++ if (line.startsWith('id name ')) {
++ engineName = line.substring('id name '.length)
++ }
++ if (line.startsWith('uciok')) {
++ this.engine!.removeListener(listener)
++ resolve({ engineName })
++ }
++ }
++ this.engine.addListener(listener)
++ this.send('uci')
++ })
++ }
++
++ return this.startPromise
+ }
+
+ public isReady(): Promise<void> {
+ return new Promise((resolve) => {
+- const listener = (e: Event) => {
+- const line = (e as any).output
++ const listener = (line: string) => {
+ if (line.startsWith('readyok')) {
+- window.removeEventListener('stockfish', listener, false)
++ this.engine!.removeListener(listener)
+ resolve()
+ }
+ }
+- window.addEventListener('stockfish', listener, { passive: true })
++ this.engine!.addListener(listener)
+ this.send('isready')
+ })
+ }
+
+ public send(text: string): Promise<void> {
+ console.debug('[stockfish <<] ' + text)
+- return this.plugin.cmd({ cmd: text })
++ this.engine!.send(text)
++ return Promise.resolve()
+ }
+
+ public setOption(name: string, value: string | number | boolean): Promise<void> {
+@@ -61,10 +72,8 @@ export class StockfishPlugin {
+
+ public setVariant(): Promise<void> {
+ if (this.isVariant()) {
+- if (Capacitor.getPlatform() !== 'web' && this.variant === 'threeCheck')
++ if (this.variant === 'threeCheck')
+ return this.setOption('UCI_Variant', '3check')
+- if (Capacitor.getPlatform() === 'web' && this.variant === 'antichess')
+- return this.setOption('UCI_Variant', 'giveaway')
+ else
+ return this.setOption('UCI_Variant', this.variant.toLowerCase())
+ } else {
+@@ -73,7 +82,11 @@ export class StockfishPlugin {
+ }
+
+ public exit(): Promise<void> {
+- return this.plugin.exit()
++ if(this.engine!.kill()) {
++ return Promise.resolve()
++ } else {
++ return Promise.reject('Failed to kill process')
++ }
+ }
+
+ private isVariant() {
+@@ -95,11 +108,13 @@ export function getNbCores(): number {
+ }
+
+ export function canUseNNUE(): boolean {
+- if (Capacitor.getPlatform() === 'android') {
+- return window.lichess.cpuArch === 'arm64-v8a'
+- } else if (Capacitor.getPlatform() === 'ios') {
+- return true
+- } else {
+- return false
+- }
++ // TODO maybe later
++ return false
+ }
++
++window.addEventListener("stockfish-outer" as any, (evt: CustomEvent) => {
++ const newEvent = new CustomEvent("stockfish");
++ (newEvent as any).output = evt.detail;
++
++ window.dispatchEvent(newEvent);
++});
diff --git a/preload.js b/preload.js
new file mode 100644
index 000000000000..ae186cf8a16a
--- /dev/null
+++ b/preload.js
@@ -0,0 +1,27 @@
+const childProcess = require("child_process");
+const { contextBridge } = require("electron");
+const readline = require("readline");
+
+function startStockfish() {
+ const proc = childProcess.exec("fairy-stockfish");
+ const reader = readline.createInterface(proc.stdout);
+
+ console.log("starting stockfish");
+
+ reader.on("line", line => {
+ const evt = new CustomEvent("stockfish-outer", {detail: line});
+ window.dispatchEvent(evt);
+ });
+
+ return {
+ send: line => {
+ console.log("sending", line);
+ proc.stdin.write(line + "\r\n");
+ },
+ addListener: listener => reader.on("line", listener),
+ removeListener: listener => reader.off("line", listener),
+ kill: () => proc.kill(),
+ };
+}
+
+contextBridge.exposeInMainWorld("startStockfish", startStockfish);