engine.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. import 'dart:async';
  2. import 'dart:io';
  3. import 'package:flutter/foundation.dart';
  4. import '../foundation/customer_notifier.dart';
  5. import '../global.dart';
  6. import 'engine_type.dart';
  7. class Engine extends CustomNotifier<String> {
  8. Engine(this.engine);
  9. final EngineType engine;
  10. List<Completer<String>> readyCompleters = [];
  11. Completer<bool>? stopCompleter;
  12. bool ready = false;
  13. Process? process;
  14. Future<Process?> init() {
  15. ready = false;
  16. if (!isSupportEngine) {
  17. return Future.value(null);
  18. }
  19. String path = '${Directory.current.path}/assets/engines/${engine.path}';
  20. if (!File(path).existsSync()) {
  21. path =
  22. '${Directory.current.path}/data/flutter_assets/assets/engines/${engine.path}';
  23. }
  24. return Process.start(path, [], mode: ProcessStartMode.normal).then((value) {
  25. process = value;
  26. ready = true;
  27. process?.stdout.listen(onMessage);
  28. process?.stdin.writeln(engine.scheme);
  29. return process!;
  30. });
  31. }
  32. static bool get isSupportEngine {
  33. if (kIsWeb) {
  34. return false;
  35. }
  36. if (Platform.isWindows) {
  37. return true;
  38. }
  39. return false;
  40. }
  41. void onMessage(List<int> event) {
  42. String lines = String.fromCharCodes(event).trim();
  43. lines.split('\n').forEach((line) {
  44. line = line.trim();
  45. if (line == 'bye') {
  46. ready = false;
  47. process = null;
  48. if (stopCompleter != null && !stopCompleter!.isCompleted) {
  49. stopCompleter?.complete(true);
  50. }
  51. } else if (line.isNotEmpty && hasListeners) {
  52. if (line.startsWith('nobestmove') || line.startsWith('bestmove ')) {
  53. if (stopCompleter != null && !stopCompleter!.isCompleted) {
  54. stopCompleter!.complete(true);
  55. } else if (readyCompleters.isNotEmpty) {
  56. readyCompleters.removeAt(0).complete(line);
  57. }
  58. }
  59. notifyListeners(line);
  60. }
  61. });
  62. }
  63. Future<String> requestMove(
  64. String fen, {
  65. int time = 0,
  66. int increment = 0,
  67. String type = '',
  68. int depth = 0,
  69. int nodes = 0,
  70. }) {
  71. Completer<String> readyCompleter = Completer();
  72. stop().then((b) {
  73. if (b) {
  74. readyCompleters.add(readyCompleter);
  75. position(fen);
  76. go(
  77. time: time,
  78. increment: increment,
  79. type: type,
  80. depth: depth,
  81. nodes: nodes,
  82. );
  83. } else {
  84. readyCompleter.complete('isbusy');
  85. }
  86. });
  87. return readyCompleter.future;
  88. }
  89. void sendCommand(String command) {
  90. if (!ready) {
  91. logger.info('Engine is not ready');
  92. return;
  93. }
  94. logger.info('command: $command');
  95. process?.stdin.writeln(command);
  96. }
  97. void setOption(String option) {
  98. sendCommand('setoption $option');
  99. }
  100. void position(String fen) {
  101. sendCommand('position fen $fen');
  102. }
  103. void banMoves(List<String> moveList) {
  104. sendCommand('banmoves ${moveList.join(' ')}');
  105. }
  106. void go({
  107. int time = 0,
  108. int increment = 0,
  109. String type = '',
  110. int depth = 0,
  111. int nodes = 0,
  112. }) {
  113. if (time > 0) {
  114. sendCommand('go $type time $time increment $increment');
  115. } else if (depth > 0) {
  116. sendCommand('go depth $depth');
  117. } else if (depth < 0) {
  118. sendCommand('go depth infinite');
  119. } else if (nodes > 0) {
  120. sendCommand('go nodes $depth');
  121. }
  122. }
  123. void ponderHit(String type) {
  124. sendCommand('ponderhit $type');
  125. }
  126. void probe(String fen) {
  127. sendCommand('probe $fen');
  128. }
  129. Future<bool> stop() {
  130. if (!ready || (stopCompleter != null && !stopCompleter!.isCompleted)) {
  131. return Future.value(false);
  132. }
  133. stopCompleter = Completer();
  134. sendCommand('stop');
  135. return stopCompleter!.future;
  136. }
  137. void quit() {
  138. sendCommand('quit');
  139. ready = false;
  140. }
  141. }