1
- import { BrowserEngineInfo , ExternalEngineInfo , EngineInfo , CevalEngine } from '../types' ;
1
+ import { BrowserEngineInfo , ExternalEngineInfo , EngineInfo , CevalEngine , Requires } from '../types' ;
2
2
import CevalCtrl from '../ctrl' ;
3
3
import { SimpleEngine } from './simpleEngine' ;
4
4
import { StockfishWebEngine } from './stockfishWebEngine' ;
5
5
import { ThreadedEngine } from './threadedEngine' ;
6
6
import { ExternalEngine } from './externalEngine' ;
7
7
import { storedStringProp , StoredProp } from 'common/storage' ;
8
- import { isAndroid , isIOS , isIPad , hasFeature } from 'common/device' ;
8
+ import { isAndroid , isIOS , isIPad , getFirefoxMajorVersion , features , Feature } from 'common/device' ;
9
9
import { xhrHeader } from 'common/xhr' ;
10
- import { pow2floor } from '../util' ;
11
10
import { lichessRules } from 'chessops/compat' ;
12
11
13
12
export class Engines {
14
- private localEngines : BrowserEngineInfo [ ] ;
15
- private localEngineMap : Map < string , WithMake > ;
16
- private externalEngines : ExternalEngineInfo [ ] ;
17
- private selectProp : StoredProp < string > ;
18
13
private _active : EngineInfo | undefined = undefined ;
14
+ localEngines : BrowserEngineInfo [ ] ;
15
+ localEngineMap : Map < string , WithMake > ;
16
+ externalEngines : ExternalEngineInfo [ ] ;
17
+ selectProp : StoredProp < string > ;
18
+ browserSupport : Requires [ ] = features ( ) . slice ( ) ;
19
19
20
20
constructor ( private ctrl : CevalCtrl ) {
21
+ if ( ( getFirefoxMajorVersion ( ) ?? 114 ) > 113 && ! ( 'brave' in navigator ) ) {
22
+ this . browserSupport . push ( 'recentFirefoxOrNotBrave' ) ;
23
+ }
21
24
this . localEngineMap = this . makeEngineMap ( ) ;
22
25
this . localEngines = [ ...this . localEngineMap . values ( ) ] . map ( e => e . info ) ;
23
26
this . externalEngines = this . ctrl . opts . externalEngines ?. map ( e => ( { tech : 'EXTERNAL' , ...e } ) ) ?? [ ] ;
@@ -40,7 +43,7 @@ export class Engines {
40
43
name : 'Fairy Stockfish 14+ NNUE' ,
41
44
short : 'FSF 14+' ,
42
45
tech : 'NNUE' ,
43
- requires : [ 'simd' , 'webWorkerDynamicImport ' ] ,
46
+ requires : [ 'simd' , 'recentFirefoxOrNotBrave ' ] ,
44
47
variants : [ key ] ,
45
48
assets : {
46
49
version : 'sfw003' ,
@@ -68,7 +71,7 @@ export class Engines {
68
71
name : 'Stockfish 16 NNUE · 7MB' ,
69
72
short : 'SF 16 · 7MB' ,
70
73
tech : 'NNUE' ,
71
- requires : [ 'simd' , 'webWorkerDynamicImport ' ] ,
74
+ requires : [ 'simd' , 'recentFirefoxOrNotBrave ' ] ,
72
75
minMem : 1536 ,
73
76
assets : {
74
77
version : 'sfw003' ,
@@ -84,7 +87,7 @@ export class Engines {
84
87
name : 'Stockfish 16 NNUE · 40MB' ,
85
88
short : 'SF 16 · 40MB' ,
86
89
tech : 'NNUE' ,
87
- requires : [ 'simd' , 'webWorkerDynamicImport ' ] ,
90
+ requires : [ 'simd' , 'recentFirefoxOrNotBrave ' ] ,
88
91
minMem : 2048 ,
89
92
assets : {
90
93
version : 'sfw003' ,
@@ -118,7 +121,7 @@ export class Engines {
118
121
name : 'Fairy Stockfish 14+ HCE' ,
119
122
short : 'FSF 14+' ,
120
123
tech : 'HCE' ,
121
- requires : [ 'simd' , 'webWorkerDynamicImport ' ] ,
124
+ requires : [ 'simd' , 'recentFirefoxOrNotBrave ' ] ,
122
125
variants : variants . map ( v => v [ 0 ] ) ,
123
126
assets : {
124
127
version : 'sfw003' ,
@@ -136,6 +139,7 @@ export class Engines {
136
139
short : 'SF 11 MV' ,
137
140
tech : 'HCE' ,
138
141
requires : [ 'sharedMem' ] ,
142
+ minThreads : 1 ,
139
143
variants : variants . map ( v => v [ 0 ] ) ,
140
144
assets : {
141
145
version : 'a022fa' ,
@@ -156,6 +160,7 @@ export class Engines {
156
160
short : 'SF 11' ,
157
161
tech : 'HCE' ,
158
162
requires : [ 'sharedMem' ] ,
163
+ minThreads : 1 ,
159
164
assets : {
160
165
version : 'a022fa' ,
161
166
root : 'npm/stockfish.wasm' ,
@@ -171,6 +176,7 @@ export class Engines {
171
176
name : 'Stockfish WASM' ,
172
177
short : 'Stockfish' ,
173
178
tech : 'HCE' ,
179
+ minThreads : 1 ,
174
180
maxThreads : 1 ,
175
181
requires : [ 'wasm' ] ,
176
182
obsoletedBy : 'sharedMem' ,
@@ -188,6 +194,7 @@ export class Engines {
188
194
name : 'Stockfish JS' ,
189
195
short : 'Stockfish' ,
190
196
tech : 'HCE' ,
197
+ minThreads : 1 ,
191
198
maxThreads : 1 ,
192
199
obsoletedBy : 'wasm' ,
193
200
assets : {
@@ -201,8 +208,8 @@ export class Engines {
201
208
]
202
209
. filter (
203
210
e =>
204
- e . info . requires ?. map ( req => hasFeature ( req ) ) . every ( x => ! ! x ) &&
205
- ! ( e . info . obsoletedBy && hasFeature ( e . info . obsoletedBy ) ) ,
211
+ e . info . requires ?. every ( ( req : Requires ) => this . browserSupport . includes ( req ) ) &&
212
+ ! ( e . info . obsoletedBy && this . browserSupport . includes ( e . info . obsoletedBy as Feature ) ) ,
206
213
)
207
214
. map ( e => [ e . info . id , { info : withDefaults ( e . info as BrowserEngineInfo ) , make : e . make } ] ) ,
208
215
) ;
@@ -268,11 +275,10 @@ export class Engines {
268
275
}
269
276
270
277
function maxHashMB ( ) {
271
- if ( navigator . deviceMemory ) return pow2floor ( navigator . deviceMemory * 128 ) ; // chrome/edge/opera
272
- else if ( isAndroid ( ) ) return 64 ; // budget androids are easy to crash @ 128
278
+ if ( isAndroid ( ) ) return 64 ; // budget androids are easy to crash @ 128
273
279
else if ( isIPad ( ) ) return 64 ; // iPadOS safari pretends to be desktop but acts more like iphone
274
280
else if ( isIOS ( ) ) return 32 ;
275
- return 256 ; // this is safe, mostly desktop firefox / mac safari users here
281
+ return 512 ; // allocating 1024 often fails and offers little benefit over 512, or 16 for that matter
276
282
}
277
283
const maxHash = maxHashMB ( ) ;
278
284
@@ -286,9 +292,10 @@ function externalEngineSupports(e: EngineInfo, v: VariantKey) {
286
292
287
293
const withDefaults = ( engine : BrowserEngineInfo ) : BrowserEngineInfo => ( {
288
294
variants : [ 'standard' , 'chess960' , 'fromPosition' ] ,
289
- maxThreads : navigator . hardwareConcurrency ?? 1 ,
290
295
minMem : 1024 ,
291
296
maxHash,
297
+ minThreads : 2 ,
298
+ maxThreads : 32 ,
292
299
...engine ,
293
300
} ) ;
294
301
0 commit comments