next-chessground 0.10.5 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.es.js CHANGED
@@ -6414,16 +6414,16 @@ const Chessboard = (props, ref) => {
6414
6414
 
6415
6415
  if (!move) {
6416
6416
  show();
6417
+ }
6418
+
6419
+ if (theme.playSounds) {
6420
+ audio(theme.sounds);
6417
6421
  } // pass the chess object to callback function
6418
6422
 
6419
6423
 
6420
6424
  if (typeof props.onMove === 'function') {
6421
6425
  await props.onMove(chess);
6422
6426
  }
6423
-
6424
- if (theme.playSounds) {
6425
- audio(theme.sounds);
6426
- }
6427
6427
  };
6428
6428
 
6429
6429
  return /*#__PURE__*/React.createElement("div", {
@@ -6887,6 +6887,247 @@ const NextEditor = (props, ref) => {
6887
6887
 
6888
6888
  var NextEditor$1 = /*#__PURE__*/forwardRef(NextEditor);
6889
6889
 
6890
+ class Stockfish {
6891
+ constructor() {
6892
+ if (typeof window === 'undefined') {
6893
+ return false;
6894
+ }
6895
+
6896
+ if (!window.chessEngineWorker) {
6897
+ const worker = process.env.STOCKFISH_PATH;
6898
+ window.chessEngineWorker = new Worker(worker);
6899
+ }
6900
+
6901
+ this.skillLevel = 20;
6902
+ this.maxDepth = 40;
6903
+ this.resolveTimeout = null;
6904
+ this.isAnalyzing = false;
6905
+ this.fen = constants.initialFen;
6906
+ }
6907
+
6908
+ getTurnFromFen(fen) {
6909
+ return fen.split(' ')[1];
6910
+ }
6911
+
6912
+ normalizeScoreValue(value) {
6913
+ const {
6914
+ fen
6915
+ } = this;
6916
+ const turn = this.getTurnFromFen(fen);
6917
+
6918
+ if (turn === 'b') {
6919
+ return -1 * value;
6920
+ }
6921
+
6922
+ return value;
6923
+ }
6924
+
6925
+ isInfoMessage(message) {
6926
+ if (!message || !message.data) {
6927
+ return false;
6928
+ }
6929
+
6930
+ return message.data.startsWith('info');
6931
+ }
6932
+
6933
+ setSkillLevel() {
6934
+ /**
6935
+ * skill level is 0-20, higher the stronger
6936
+ * skill level maximum error is 0-5000, lower the stronger
6937
+ * skill level probability is 1-1000, the higher the stronger
6938
+ * seems to be working with max value for maxError and min value for probability
6939
+ */
6940
+ const maxError = 5000;
6941
+ const probability = 1;
6942
+ window.chessEngineWorker.postMessage('setoption name Skill Level value ' + this.skillLevel);
6943
+ window.chessEngineWorker.postMessage('setoption name Skill Level Maximum Error value ' + maxError);
6944
+ window.chessEngineWorker.postMessage('setoption name Skill Level Probability value ' + probability);
6945
+ }
6946
+
6947
+ async init() {
6948
+ await this.use_uci();
6949
+ await this.is_ready();
6950
+ this.setSkillLevel();
6951
+ }
6952
+
6953
+ getScoreFromInfo(msg) {
6954
+ if (msg.startsWith('info depth 0')) {
6955
+ // This happens when game is over.
6956
+ const split = msg.split(' ');
6957
+ const type = split[4];
6958
+ const value = this.normalizeScoreValue(Number(split[5]));
6959
+ this.isAnalyzing = false;
6960
+ return {
6961
+ type,
6962
+ value
6963
+ };
6964
+ } else if (msg.startsWith('info depth ')) {
6965
+ const split = msg.split(' ');
6966
+ const type = split[8];
6967
+ const value = this.normalizeScoreValue(Number(split[9]));
6968
+ return {
6969
+ type,
6970
+ value
6971
+ };
6972
+ }
6973
+
6974
+ return {
6975
+ type: 'cp',
6976
+ value: 0
6977
+ };
6978
+ }
6979
+
6980
+ parseData(data) {
6981
+ const depth = data.split(' ')[2];
6982
+ let pv = '';
6983
+
6984
+ if (data.indexOf(' pv ') > -1) {
6985
+ pv = data.split(' pv ')[1].split(' bmc ')[0];
6986
+ }
6987
+
6988
+ const score = this.getScoreFromInfo(data);
6989
+ return {
6990
+ depth,
6991
+ pv,
6992
+ score
6993
+ };
6994
+ }
6995
+
6996
+ use_uci() {
6997
+ return new Promise(resolve => {
6998
+ window.chessEngineWorker.postMessage('uci');
6999
+
7000
+ window.chessEngineWorker.onmessage = message => {
7001
+ if (message.data === 'uciok') {
7002
+ resolve(message);
7003
+ }
7004
+ };
7005
+ });
7006
+ }
7007
+
7008
+ is_ready() {
7009
+ return new Promise(resolve => {
7010
+ window.chessEngineWorker.postMessage('isready');
7011
+
7012
+ window.chessEngineWorker.onmessage = message => {
7013
+ if (message.data === 'readyok') {
7014
+ resolve(message);
7015
+ }
7016
+ };
7017
+ });
7018
+ }
7019
+
7020
+ set_position(fen) {
7021
+ return new Promise(resolve => {
7022
+ this.fen = fen;
7023
+ window.chessEngineWorker.postMessage('position fen ' + fen);
7024
+ resolve();
7025
+ });
7026
+ }
7027
+
7028
+ async new_position(fen) {
7029
+ await this.stop();
7030
+ await this.is_ready();
7031
+ this.set_position(fen);
7032
+ this.go_infinite();
7033
+ }
7034
+
7035
+ set_multipv(numPv) {
7036
+ window.chessEngineWorker.postMessage('setoption name MultiPV value ' + numPv);
7037
+ }
7038
+
7039
+ get_score(fen, depth = 15) {
7040
+ return new Promise(resolve => {
7041
+ window.chessEngineWorker.postMessage('position fen ' + fen);
7042
+ window.chessEngineWorker.postMessage('go depth 15');
7043
+
7044
+ window.chessEngineWorker.onmessage = message => {
7045
+ if (message.data.startsWith('info depth ' + depth)) {
7046
+ const split = message.data.split(' ');
7047
+ const type = split[8];
7048
+ const value = Number(split[9]);
7049
+ resolve({
7050
+ type,
7051
+ value
7052
+ });
7053
+ } else if (message.data.startsWith('info depth 0')) {
7054
+ // This happens when game is over.
7055
+ const split = message.data.split(' ');
7056
+ const type = split[4];
7057
+ const value = Number(split[5]);
7058
+ resolve({
7059
+ type,
7060
+ value
7061
+ });
7062
+ }
7063
+ };
7064
+ });
7065
+ }
7066
+
7067
+ go_depth(depth) {
7068
+ return new Promise(resolve => {
7069
+ window.chessEngineWorker.postMessage('go depth ' + depth);
7070
+
7071
+ window.chessEngineWorker.onmessage = message => {
7072
+ if (message.data.startsWith('bestmove')) {
7073
+ resolve(message.data);
7074
+ }
7075
+ };
7076
+ });
7077
+ }
7078
+
7079
+ go_time(time) {
7080
+ return new Promise(resolve => {
7081
+ window.chessEngineWorker.postMessage('go movetime ' + time);
7082
+
7083
+ window.chessEngineWorker.onmessage = message => {
7084
+ if (message.data.startsWith('bestmove')) {
7085
+ resolve(message.data);
7086
+ }
7087
+ };
7088
+ });
7089
+ }
7090
+
7091
+ go_infinite(callback) {
7092
+ window.chessEngineWorker.postMessage('go infinite');
7093
+ this.isAnalyzing = true;
7094
+
7095
+ window.chessEngineWorker.onmessage = message => {
7096
+ if (this.isInfoMessage(message) && typeof callback === 'function') {
7097
+ const msgData = this.parseData(message.data);
7098
+
7099
+ if (msgData.depth > this.maxDepth) {
7100
+ this.stop();
7101
+ }
7102
+
7103
+ callback(msgData);
7104
+ }
7105
+ };
7106
+ }
7107
+
7108
+ stop() {
7109
+ return new Promise(resolve => {
7110
+ if (!this.isAnalyzing) {
7111
+ resolve();
7112
+ }
7113
+
7114
+ window.chessEngineWorker.postMessage('stop');
7115
+
7116
+ window.chessEngineWorker.onmessage = message => {
7117
+ if (message.data.startsWith('bestmove')) {
7118
+ this.isAnalyzing = false;
7119
+ resolve(message.data);
7120
+ }
7121
+ };
7122
+ });
7123
+ }
7124
+
7125
+ quit() {
7126
+ window.chessEngineWorker.postMessage('quit');
7127
+ }
7128
+
7129
+ }
7130
+
6890
7131
  function styleInject(css, ref) {
6891
7132
  if (ref === void 0) ref = {};
6892
7133
  var insertAt = ref.insertAt;
@@ -6941,4 +7182,4 @@ var css_248z$7 = ".flex {\n display: flex;\n}\n.flex-col {\n flex-direction: c
6941
7182
  styleInject(css_248z$7);
6942
7183
 
6943
7184
  export default NextChessground$1;
6944
- export { NextChessground$1 as NextChessground, NextEditor$1 as NextEditor, constants, useChess, useChessground };
7185
+ export { NextChessground$1 as NextChessground, NextEditor$1 as NextEditor, Stockfish, constants, useChess, useChessground };
package/dist/index.js CHANGED
@@ -6423,16 +6423,16 @@ const Chessboard = (props, ref) => {
6423
6423
 
6424
6424
  if (!move) {
6425
6425
  show();
6426
+ }
6427
+
6428
+ if (theme.playSounds) {
6429
+ audio(theme.sounds);
6426
6430
  } // pass the chess object to callback function
6427
6431
 
6428
6432
 
6429
6433
  if (typeof props.onMove === 'function') {
6430
6434
  await props.onMove(chess);
6431
6435
  }
6432
-
6433
- if (theme.playSounds) {
6434
- audio(theme.sounds);
6435
- }
6436
6436
  };
6437
6437
 
6438
6438
  return /*#__PURE__*/React__default['default'].createElement("div", {
@@ -6896,6 +6896,247 @@ const NextEditor = (props, ref) => {
6896
6896
 
6897
6897
  var NextEditor$1 = /*#__PURE__*/React.forwardRef(NextEditor);
6898
6898
 
6899
+ class Stockfish {
6900
+ constructor() {
6901
+ if (typeof window === 'undefined') {
6902
+ return false;
6903
+ }
6904
+
6905
+ if (!window.chessEngineWorker) {
6906
+ const worker = process.env.STOCKFISH_PATH;
6907
+ window.chessEngineWorker = new Worker(worker);
6908
+ }
6909
+
6910
+ this.skillLevel = 20;
6911
+ this.maxDepth = 40;
6912
+ this.resolveTimeout = null;
6913
+ this.isAnalyzing = false;
6914
+ this.fen = constants.initialFen;
6915
+ }
6916
+
6917
+ getTurnFromFen(fen) {
6918
+ return fen.split(' ')[1];
6919
+ }
6920
+
6921
+ normalizeScoreValue(value) {
6922
+ const {
6923
+ fen
6924
+ } = this;
6925
+ const turn = this.getTurnFromFen(fen);
6926
+
6927
+ if (turn === 'b') {
6928
+ return -1 * value;
6929
+ }
6930
+
6931
+ return value;
6932
+ }
6933
+
6934
+ isInfoMessage(message) {
6935
+ if (!message || !message.data) {
6936
+ return false;
6937
+ }
6938
+
6939
+ return message.data.startsWith('info');
6940
+ }
6941
+
6942
+ setSkillLevel() {
6943
+ /**
6944
+ * skill level is 0-20, higher the stronger
6945
+ * skill level maximum error is 0-5000, lower the stronger
6946
+ * skill level probability is 1-1000, the higher the stronger
6947
+ * seems to be working with max value for maxError and min value for probability
6948
+ */
6949
+ const maxError = 5000;
6950
+ const probability = 1;
6951
+ window.chessEngineWorker.postMessage('setoption name Skill Level value ' + this.skillLevel);
6952
+ window.chessEngineWorker.postMessage('setoption name Skill Level Maximum Error value ' + maxError);
6953
+ window.chessEngineWorker.postMessage('setoption name Skill Level Probability value ' + probability);
6954
+ }
6955
+
6956
+ async init() {
6957
+ await this.use_uci();
6958
+ await this.is_ready();
6959
+ this.setSkillLevel();
6960
+ }
6961
+
6962
+ getScoreFromInfo(msg) {
6963
+ if (msg.startsWith('info depth 0')) {
6964
+ // This happens when game is over.
6965
+ const split = msg.split(' ');
6966
+ const type = split[4];
6967
+ const value = this.normalizeScoreValue(Number(split[5]));
6968
+ this.isAnalyzing = false;
6969
+ return {
6970
+ type,
6971
+ value
6972
+ };
6973
+ } else if (msg.startsWith('info depth ')) {
6974
+ const split = msg.split(' ');
6975
+ const type = split[8];
6976
+ const value = this.normalizeScoreValue(Number(split[9]));
6977
+ return {
6978
+ type,
6979
+ value
6980
+ };
6981
+ }
6982
+
6983
+ return {
6984
+ type: 'cp',
6985
+ value: 0
6986
+ };
6987
+ }
6988
+
6989
+ parseData(data) {
6990
+ const depth = data.split(' ')[2];
6991
+ let pv = '';
6992
+
6993
+ if (data.indexOf(' pv ') > -1) {
6994
+ pv = data.split(' pv ')[1].split(' bmc ')[0];
6995
+ }
6996
+
6997
+ const score = this.getScoreFromInfo(data);
6998
+ return {
6999
+ depth,
7000
+ pv,
7001
+ score
7002
+ };
7003
+ }
7004
+
7005
+ use_uci() {
7006
+ return new Promise(resolve => {
7007
+ window.chessEngineWorker.postMessage('uci');
7008
+
7009
+ window.chessEngineWorker.onmessage = message => {
7010
+ if (message.data === 'uciok') {
7011
+ resolve(message);
7012
+ }
7013
+ };
7014
+ });
7015
+ }
7016
+
7017
+ is_ready() {
7018
+ return new Promise(resolve => {
7019
+ window.chessEngineWorker.postMessage('isready');
7020
+
7021
+ window.chessEngineWorker.onmessage = message => {
7022
+ if (message.data === 'readyok') {
7023
+ resolve(message);
7024
+ }
7025
+ };
7026
+ });
7027
+ }
7028
+
7029
+ set_position(fen) {
7030
+ return new Promise(resolve => {
7031
+ this.fen = fen;
7032
+ window.chessEngineWorker.postMessage('position fen ' + fen);
7033
+ resolve();
7034
+ });
7035
+ }
7036
+
7037
+ async new_position(fen) {
7038
+ await this.stop();
7039
+ await this.is_ready();
7040
+ this.set_position(fen);
7041
+ this.go_infinite();
7042
+ }
7043
+
7044
+ set_multipv(numPv) {
7045
+ window.chessEngineWorker.postMessage('setoption name MultiPV value ' + numPv);
7046
+ }
7047
+
7048
+ get_score(fen, depth = 15) {
7049
+ return new Promise(resolve => {
7050
+ window.chessEngineWorker.postMessage('position fen ' + fen);
7051
+ window.chessEngineWorker.postMessage('go depth 15');
7052
+
7053
+ window.chessEngineWorker.onmessage = message => {
7054
+ if (message.data.startsWith('info depth ' + depth)) {
7055
+ const split = message.data.split(' ');
7056
+ const type = split[8];
7057
+ const value = Number(split[9]);
7058
+ resolve({
7059
+ type,
7060
+ value
7061
+ });
7062
+ } else if (message.data.startsWith('info depth 0')) {
7063
+ // This happens when game is over.
7064
+ const split = message.data.split(' ');
7065
+ const type = split[4];
7066
+ const value = Number(split[5]);
7067
+ resolve({
7068
+ type,
7069
+ value
7070
+ });
7071
+ }
7072
+ };
7073
+ });
7074
+ }
7075
+
7076
+ go_depth(depth) {
7077
+ return new Promise(resolve => {
7078
+ window.chessEngineWorker.postMessage('go depth ' + depth);
7079
+
7080
+ window.chessEngineWorker.onmessage = message => {
7081
+ if (message.data.startsWith('bestmove')) {
7082
+ resolve(message.data);
7083
+ }
7084
+ };
7085
+ });
7086
+ }
7087
+
7088
+ go_time(time) {
7089
+ return new Promise(resolve => {
7090
+ window.chessEngineWorker.postMessage('go movetime ' + time);
7091
+
7092
+ window.chessEngineWorker.onmessage = message => {
7093
+ if (message.data.startsWith('bestmove')) {
7094
+ resolve(message.data);
7095
+ }
7096
+ };
7097
+ });
7098
+ }
7099
+
7100
+ go_infinite(callback) {
7101
+ window.chessEngineWorker.postMessage('go infinite');
7102
+ this.isAnalyzing = true;
7103
+
7104
+ window.chessEngineWorker.onmessage = message => {
7105
+ if (this.isInfoMessage(message) && typeof callback === 'function') {
7106
+ const msgData = this.parseData(message.data);
7107
+
7108
+ if (msgData.depth > this.maxDepth) {
7109
+ this.stop();
7110
+ }
7111
+
7112
+ callback(msgData);
7113
+ }
7114
+ };
7115
+ }
7116
+
7117
+ stop() {
7118
+ return new Promise(resolve => {
7119
+ if (!this.isAnalyzing) {
7120
+ resolve();
7121
+ }
7122
+
7123
+ window.chessEngineWorker.postMessage('stop');
7124
+
7125
+ window.chessEngineWorker.onmessage = message => {
7126
+ if (message.data.startsWith('bestmove')) {
7127
+ this.isAnalyzing = false;
7128
+ resolve(message.data);
7129
+ }
7130
+ };
7131
+ });
7132
+ }
7133
+
7134
+ quit() {
7135
+ window.chessEngineWorker.postMessage('quit');
7136
+ }
7137
+
7138
+ }
7139
+
6899
7140
  function styleInject(css, ref) {
6900
7141
  if (ref === void 0) ref = {};
6901
7142
  var insertAt = ref.insertAt;
@@ -6951,6 +7192,7 @@ styleInject(css_248z$7);
6951
7192
 
6952
7193
  exports.NextChessground = NextChessground$1;
6953
7194
  exports.NextEditor = NextEditor$1;
7195
+ exports.Stockfish = Stockfish;
6954
7196
  exports.constants = constants;
6955
7197
  exports.default = NextChessground$1;
6956
7198
  exports.useChess = useChess;
package/index.js CHANGED
@@ -3,6 +3,7 @@ import NextEditor from './components/NextEditor';
3
3
  import useChess from './hooks/use-chess';
4
4
  import useChessground from './hooks/use-chessground';
5
5
  import constants from './utils/constants';
6
+ import Stockfish from './utils/stockfish';
6
7
 
7
8
  import './assets/css/board.css';
8
9
  import './assets/css/chess.css';
@@ -15,4 +16,11 @@ import './assets/css/tailwind.css';
15
16
 
16
17
  export default NextChessground;
17
18
 
18
- export { NextChessground, NextEditor, useChess, useChessground, constants };
19
+ export {
20
+ NextChessground,
21
+ NextEditor,
22
+ Stockfish,
23
+ useChess,
24
+ useChessground,
25
+ constants,
26
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-chessground",
3
- "version": "0.10.5",
3
+ "version": "0.11.3",
4
4
  "description": "React and Next wrapper for Chessground with chessboard and pieces out of the box",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",