Merge remote-tracking branch 'Leptopoda/linting'
This commit is contained in:
commit
e7f7b6cf6f
|
@ -32,6 +32,7 @@ class Game {
|
||||||
final String tag = "[game]";
|
final String tag = "[game]";
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
|
// TODO: _position is allready initialized with Position(). seems like duplicate code
|
||||||
_position = Position();
|
_position = Position();
|
||||||
focusIndex = blurIndex = invalidIndex;
|
focusIndex = blurIndex = invalidIndex;
|
||||||
}
|
}
|
||||||
|
@ -71,7 +72,7 @@ class Game {
|
||||||
PieceColor.black: false
|
PieceColor.black: false
|
||||||
};
|
};
|
||||||
|
|
||||||
bool aiIsSearching() {
|
bool get aiIsSearching {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"$tag White is searching? ${isSearching[PieceColor.white]}\n"
|
"$tag White is searching? ${isSearching[PieceColor.white]}\n"
|
||||||
"$tag Black is searching? ${isSearching[PieceColor.black]}\n",
|
"$tag Black is searching? ${isSearching[PieceColor.black]}\n",
|
||||||
|
@ -115,14 +116,14 @@ class Game {
|
||||||
blurIndex = invalidIndex;
|
blurIndex = invalidIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doMove(String move) {
|
Future<bool> doMove(String move) async {
|
||||||
if (position.phase == Phase.ready) {
|
if (position.phase == Phase.ready) {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint("$tag AI do move: $move");
|
debugPrint("$tag AI do move: $move");
|
||||||
|
|
||||||
if (!position.doMove(move)) {
|
if (await position.doMove(move) == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import 'package:sanmill/mill/types.dart';
|
||||||
import 'package:sanmill/mill/zobrist.dart';
|
import 'package:sanmill/mill/zobrist.dart';
|
||||||
import 'package:sanmill/services/audios.dart';
|
import 'package:sanmill/services/audios.dart';
|
||||||
import 'package:sanmill/services/engine/engine.dart';
|
import 'package:sanmill/services/engine/engine.dart';
|
||||||
|
import 'package:sanmill/shared/common/config.dart';
|
||||||
|
|
||||||
List<int> posKeyHistory = [];
|
List<int> posKeyHistory = [];
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ class Position {
|
||||||
|
|
||||||
String us = PieceColor.white;
|
String us = PieceColor.white;
|
||||||
String them = PieceColor.black;
|
String them = PieceColor.black;
|
||||||
String winner = PieceColor.nobody;
|
String _winner = PieceColor.nobody;
|
||||||
|
|
||||||
GameOverReason gameOverReason = GameOverReason.noReason;
|
GameOverReason gameOverReason = GameOverReason.noReason;
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ class Position {
|
||||||
st.pliesFromNull = other.st.pliesFromNull;
|
st.pliesFromNull = other.st.pliesFromNull;
|
||||||
|
|
||||||
them = other.them;
|
them = other.them;
|
||||||
winner = other.winner;
|
_winner = other._winner;
|
||||||
gameOverReason = other.gameOverReason;
|
gameOverReason = other.gameOverReason;
|
||||||
|
|
||||||
phase = other.phase;
|
phase = other.phase;
|
||||||
|
@ -135,7 +136,7 @@ class Position {
|
||||||
|
|
||||||
String movedPiece(int move) => pieceOn(fromSq(move));
|
String movedPiece(int move) => pieceOn(fromSq(move));
|
||||||
|
|
||||||
bool movePiece(int from, int to) {
|
Future<bool> movePiece(int from, int to) async {
|
||||||
if (selectPiece(from) == 0) {
|
if (selectPiece(from) == 0) {
|
||||||
return putPiece(to);
|
return putPiece(to);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +262,7 @@ class Position {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool doMove(String move) {
|
Future<bool> doMove(String move) async {
|
||||||
if (move.length > "Player".length &&
|
if (move.length > "Player".length &&
|
||||||
move.substring(0, "Player".length - 1) == "Player") {
|
move.substring(0, "Player".length - 1) == "Player") {
|
||||||
if (move["Player".length] == '1') {
|
if (move["Player".length] == '1') {
|
||||||
|
@ -278,7 +279,7 @@ class Position {
|
||||||
|
|
||||||
if (move == "draw") {
|
if (move == "draw") {
|
||||||
phase = Phase.gameOver;
|
phase = Phase.gameOver;
|
||||||
winner = PieceColor.draw;
|
_winner = PieceColor.draw;
|
||||||
if (score[PieceColor.draw] != null) {
|
if (score[PieceColor.draw] != null) {
|
||||||
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +288,7 @@ class Position {
|
||||||
if (rule.nMoveRule > 0 && posKeyHistory.length >= rule.nMoveRule - 1) {
|
if (rule.nMoveRule > 0 && posKeyHistory.length >= rule.nMoveRule - 1) {
|
||||||
gameOverReason = GameOverReason.drawReasonRule50;
|
gameOverReason = GameOverReason.drawReasonRule50;
|
||||||
} else if (rule.endgameNMoveRule < rule.nMoveRule &&
|
} else if (rule.endgameNMoveRule < rule.nMoveRule &&
|
||||||
isThreeEndgame() &&
|
isThreeEndgame &&
|
||||||
posKeyHistory.length >= rule.endgameNMoveRule - 1) {
|
posKeyHistory.length >= rule.endgameNMoveRule - 1) {
|
||||||
gameOverReason = GameOverReason.drawReasonEndgameRule50;
|
gameOverReason = GameOverReason.drawReasonEndgameRule50;
|
||||||
} else if (rule.threefoldRepetitionRule) {
|
} else if (rule.threefoldRepetitionRule) {
|
||||||
|
@ -308,20 +309,20 @@ class Position {
|
||||||
|
|
||||||
switch (m.type) {
|
switch (m.type) {
|
||||||
case MoveType.remove:
|
case MoveType.remove:
|
||||||
ret = removePiece(m.to) == 0;
|
ret = await removePiece(m.to) == 0;
|
||||||
if (ret) {
|
if (ret) {
|
||||||
// Reset rule 50 counter
|
// Reset rule 50 counter
|
||||||
st.rule50 = 0;
|
st.rule50 = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MoveType.move:
|
case MoveType.move:
|
||||||
ret = movePiece(m.from, m.to);
|
ret = await movePiece(m.from, m.to);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
++st.rule50;
|
++st.rule50;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MoveType.place:
|
case MoveType.place:
|
||||||
ret = putPiece(m.to);
|
ret = await putPiece(m.to);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
// Reset rule 50 counter
|
// Reset rule 50 counter
|
||||||
st.rule50 = 0;
|
st.rule50 = 0;
|
||||||
|
@ -414,7 +415,7 @@ class Position {
|
||||||
setSideToMove(PieceColor.white);
|
setSideToMove(PieceColor.white);
|
||||||
action = Act.place;
|
action = Act.place;
|
||||||
|
|
||||||
winner = PieceColor.nobody;
|
_winner = PieceColor.nobody;
|
||||||
gameOverReason = GameOverReason.noReason;
|
gameOverReason = GameOverReason.noReason;
|
||||||
|
|
||||||
clearBoard();
|
clearBoard();
|
||||||
|
@ -457,7 +458,7 @@ class Position {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool putPiece(int s) {
|
Future<bool> putPiece(int s) async {
|
||||||
var piece = Piece.noPiece;
|
var piece = Piece.noPiece;
|
||||||
final us = _sideToMove;
|
final us = _sideToMove;
|
||||||
|
|
||||||
|
@ -472,6 +473,7 @@ class Position {
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: use switch case
|
||||||
if (phase == Phase.placing) {
|
if (phase == Phase.placing) {
|
||||||
piece = sideToMove;
|
piece = sideToMove;
|
||||||
if (pieceInHandCount[us] != null) {
|
if (pieceInHandCount[us] != null) {
|
||||||
|
@ -501,7 +503,7 @@ class Position {
|
||||||
|
|
||||||
if (pieceInHandCount[PieceColor.white] == 0 &&
|
if (pieceInHandCount[PieceColor.white] == 0 &&
|
||||||
pieceInHandCount[PieceColor.black] == 0) {
|
pieceInHandCount[PieceColor.black] == 0) {
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,14 +518,14 @@ class Position {
|
||||||
changeSideToMove();
|
changeSideToMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
changeSideToMove();
|
changeSideToMove();
|
||||||
}
|
}
|
||||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||||
Audios.playTone(Audios.placeSoundId);
|
await Audios.playTone(Sound.place);
|
||||||
} else {
|
} else {
|
||||||
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
||||||
updateKeyMisc();
|
updateKeyMisc();
|
||||||
|
@ -539,7 +541,7 @@ class Position {
|
||||||
|
|
||||||
if (pieceInHandCount[PieceColor.white] == 0 &&
|
if (pieceInHandCount[PieceColor.white] == 0 &&
|
||||||
pieceInHandCount[PieceColor.black] == 0) {
|
pieceInHandCount[PieceColor.black] == 0) {
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +552,7 @@ class Position {
|
||||||
changeSideToMove();
|
changeSideToMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,10 +561,10 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||||
Audios.playTone(Audios.millSoundId);
|
await Audios.playTone(Sound.mill);
|
||||||
}
|
}
|
||||||
} else if (phase == Phase.moving) {
|
} else if (phase == Phase.moving) {
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,18 +605,18 @@ class Position {
|
||||||
action = Act.select;
|
action = Act.select;
|
||||||
changeSideToMove();
|
changeSideToMove();
|
||||||
|
|
||||||
if (checkIfGameIsOver()) {
|
if (isGameOver()) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||||
Audios.playTone(Audios.placeSoundId);
|
await Audios.playTone(Sound.place);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
pieceToRemoveCount = rule.mayRemoveMultiple ? n : 1;
|
||||||
updateKeyMisc();
|
updateKeyMisc();
|
||||||
action = Act.remove;
|
action = Act.remove;
|
||||||
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
gameInstance.focusIndex = squareToIndex[s] ?? invalidIndex;
|
||||||
Audios.playTone(Audios.millSoundId);
|
await Audios.playTone(Sound.mill);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
assert(false);
|
||||||
|
@ -623,7 +625,7 @@ class Position {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int removePiece(int s) {
|
Future<int> removePiece(int s) async {
|
||||||
if (phase == Phase.ready || phase == Phase.gameOver) return -1;
|
if (phase == Phase.ready || phase == Phase.gameOver) return -1;
|
||||||
|
|
||||||
if (action != Act.remove) return -1;
|
if (action != Act.remove) return -1;
|
||||||
|
@ -641,7 +643,7 @@ class Position {
|
||||||
|
|
||||||
revertKey(s);
|
revertKey(s);
|
||||||
|
|
||||||
Audios.playTone(Audios.removeSoundId);
|
await Audios.playTone(Sound.remove);
|
||||||
|
|
||||||
if (rule.hasBannedLocations && phase == Phase.placing) {
|
if (rule.hasBannedLocations && phase == Phase.placing) {
|
||||||
// Remove and put ban
|
// Remove and put ban
|
||||||
|
@ -685,7 +687,7 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule.isDefenderMoveFirst) {
|
if (rule.isDefenderMoveFirst) {
|
||||||
checkIfGameIsOver();
|
isGameOver();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -696,7 +698,7 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
changeSideToMove();
|
changeSideToMove();
|
||||||
checkIfGameIsOver();
|
isGameOver();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -733,14 +735,12 @@ class Position {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getWinner() {
|
String get winner => _winner;
|
||||||
return winner;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setGameOver(String w, GameOverReason reason) {
|
void setGameOver(String w, GameOverReason reason) {
|
||||||
phase = Phase.gameOver;
|
phase = Phase.gameOver;
|
||||||
gameOverReason = reason;
|
gameOverReason = reason;
|
||||||
winner = w;
|
_winner = w;
|
||||||
|
|
||||||
debugPrint("[position] Game over, $w win, because of $reason");
|
debugPrint("[position] Game over, $w win, because of $reason");
|
||||||
updateScore();
|
updateScore();
|
||||||
|
@ -748,7 +748,7 @@ class Position {
|
||||||
|
|
||||||
void updateScore() {
|
void updateScore() {
|
||||||
if (phase == Phase.gameOver) {
|
if (phase == Phase.gameOver) {
|
||||||
if (winner == PieceColor.draw) {
|
if (_winner == PieceColor.draw) {
|
||||||
if (score[PieceColor.draw] != null) {
|
if (score[PieceColor.draw] != null) {
|
||||||
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
||||||
}
|
}
|
||||||
|
@ -756,13 +756,13 @@ class Position {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (score[winner] != null) {
|
if (score[_winner] != null) {
|
||||||
score[winner] = score[winner]! + 1;
|
score[_winner] = score[_winner]! + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isThreeEndgame() {
|
bool get isThreeEndgame {
|
||||||
if (phase == Phase.placing) {
|
if (phase == Phase.placing) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -771,7 +771,7 @@ class Position {
|
||||||
pieceOnBoardCount[PieceColor.black] == 3;
|
pieceOnBoardCount[PieceColor.black] == 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkIfGameIsOver() {
|
bool isGameOver() {
|
||||||
if (phase == Phase.ready || phase == Phase.gameOver) {
|
if (phase == Phase.ready || phase == Phase.gameOver) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -782,7 +782,7 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rule.endgameNMoveRule < rule.nMoveRule &&
|
if (rule.endgameNMoveRule < rule.nMoveRule &&
|
||||||
isThreeEndgame() &&
|
isThreeEndgame &&
|
||||||
posKeyHistory.length >= rule.endgameNMoveRule) {
|
posKeyHistory.length >= rule.endgameNMoveRule) {
|
||||||
setGameOver(PieceColor.draw, GameOverReason.drawReasonEndgameRule50);
|
setGameOver(PieceColor.draw, GameOverReason.drawReasonEndgameRule50);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1047,7 +1047,7 @@ class Position {
|
||||||
nPiecesInHand;
|
nPiecesInHand;
|
||||||
pieceToRemoveCount = 0;
|
pieceToRemoveCount = 0;
|
||||||
|
|
||||||
winner = PieceColor.nobody;
|
_winner = PieceColor.nobody;
|
||||||
Mills.adjacentSquaresInit();
|
Mills.adjacentSquaresInit();
|
||||||
Mills.millTableInit();
|
Mills.millTableInit();
|
||||||
currentSquare = 0;
|
currentSquare = 0;
|
||||||
|
@ -1086,25 +1086,29 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Future<String> gotoHistory(HistoryMove move, [int? index]) async {
|
||||||
Future<String> _gotoHistory(int moveIndex) async {
|
final int moveIndex = _gotoHistoryIndex(move, index);
|
||||||
String errString = "";
|
|
||||||
|
|
||||||
if (recorder == null) {
|
if (recorder == null) {
|
||||||
debugPrint("[goto] recorder is null.");
|
debugPrint("[goto] recorder is null.");
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recorder!.cur == moveIndex) {
|
||||||
|
debugPrint("[goto] cur is equal to moveIndex.");
|
||||||
|
return "equal";
|
||||||
|
}
|
||||||
|
|
||||||
final history = recorder!.history;
|
final history = recorder!.history;
|
||||||
|
|
||||||
if (moveIndex < -1 || history.length <= moveIndex) {
|
if (moveIndex < -1 || history.length <= moveIndex) {
|
||||||
debugPrint("[goto] moveIndex is out of range.");
|
debugPrint("[goto] moveIndex is out of range.");
|
||||||
return "out-of-range";
|
return "out-of-range";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recorder!.cur == moveIndex) {
|
String errString = "";
|
||||||
debugPrint("[goto] cur is equal to moveIndex.");
|
|
||||||
return "equal";
|
Audios.isTemporaryMute = true;
|
||||||
}
|
|
||||||
|
|
||||||
// Backup context
|
// Backup context
|
||||||
final engineTypeBackup = gameInstance.engineType;
|
final engineTypeBackup = gameInstance.engineType;
|
||||||
|
@ -1121,13 +1125,10 @@ class Position {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i <= moveIndex; i++) {
|
for (var i = 0; i <= moveIndex; i++) {
|
||||||
if (gameInstance.doMove(history[i].move!) == false) {
|
if (await gameInstance.doMove(history[i].move!) == false) {
|
||||||
errString = history[i].move!;
|
errString = history[i].move!;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//await Future.delayed(Duration(seconds: 1));
|
|
||||||
//setState(() {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore context
|
// Restore context
|
||||||
|
@ -1136,31 +1137,46 @@ class Position {
|
||||||
recorder!.history = historyBack;
|
recorder!.history = historyBack;
|
||||||
recorder!.cur = moveIndex;
|
recorder!.cur = moveIndex;
|
||||||
|
|
||||||
|
Audios.isTemporaryMute = false;
|
||||||
|
await _gotoHistoryPlaySound(move);
|
||||||
|
|
||||||
return errString;
|
return errString;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> takeBackN(int n) async {
|
int _gotoHistoryIndex(HistoryMove move, [int? index]) {
|
||||||
int index = recorder!.cur - n;
|
switch (move) {
|
||||||
if (index < -1) {
|
case HistoryMove.forwardAll:
|
||||||
index = -1;
|
return recorder!.history.length - 1;
|
||||||
|
case HistoryMove.backAll:
|
||||||
|
return -1;
|
||||||
|
case HistoryMove.farward:
|
||||||
|
return recorder!.cur + 1;
|
||||||
|
case HistoryMove.backN:
|
||||||
|
assert(index != null);
|
||||||
|
int _index = recorder!.cur - index!;
|
||||||
|
if (_index < -1) {
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
return _index;
|
||||||
|
case HistoryMove.backOne:
|
||||||
|
return recorder!.cur - 1;
|
||||||
}
|
}
|
||||||
return _gotoHistory(index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> takeBack() async {
|
Future<void> _gotoHistoryPlaySound(HistoryMove move) async {
|
||||||
return _gotoHistory(recorder!.cur - 1);
|
if (!Config.keepMuteWhenTakingBack) {
|
||||||
}
|
switch (move) {
|
||||||
|
case HistoryMove.forwardAll:
|
||||||
|
case HistoryMove.farward:
|
||||||
|
await Audios.playTone(Sound.place);
|
||||||
|
break;
|
||||||
|
case HistoryMove.backAll:
|
||||||
|
case HistoryMove.backN:
|
||||||
|
|
||||||
Future<String> stepForward() async {
|
case HistoryMove.backOne:
|
||||||
return _gotoHistory(recorder!.cur + 1);
|
await Audios.playTone(Sound.remove);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Future<String> takeBackAll() async {
|
|
||||||
return _gotoHistory(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<String> stepForwardAll() async {
|
|
||||||
return _gotoHistory(recorder!.history.length - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String movesSinceLastRemove() {
|
String movesSinceLastRemove() {
|
||||||
|
@ -1205,3 +1221,5 @@ class Position {
|
||||||
|
|
||||||
String? get lastPositionWithRemove => recorder!.lastPositionWithRemove;
|
String? get lastPositionWithRemove => recorder!.lastPositionWithRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum HistoryMove { forwardAll, backAll, farward, backN, backOne }
|
||||||
|
|
|
@ -172,7 +172,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic onBoardTap(int index) {
|
Future<dynamic> onBoardTap(int index) async {
|
||||||
if (!isReady) {
|
if (!isReady) {
|
||||||
debugPrint("[tap] Not ready, ignore tapping.");
|
debugPrint("[tap] Not ready, ignore tapping.");
|
||||||
return false;
|
return false;
|
||||||
|
@ -208,18 +208,18 @@ class _GamePageState extends State<GamePage>
|
||||||
gameInstance.newGame();
|
gameInstance.newGame();
|
||||||
|
|
||||||
if (gameInstance.isAiToMove) {
|
if (gameInstance.isAiToMove) {
|
||||||
if (gameInstance.aiIsSearching()) {
|
if (gameInstance.aiIsSearching) {
|
||||||
debugPrint("$tag AI is thinking, skip tapping.");
|
debugPrint("$tag AI is thinking, skip tapping.");
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
debugPrint("[tap] AI is not thinking. AI is to move.");
|
debugPrint("[tap] AI is not thinking. AI is to move.");
|
||||||
engineToGo(false);
|
await engineToGo(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gameInstance.isAiToMove || gameInstance.aiIsSearching()) {
|
if (gameInstance.isAiToMove || gameInstance.aiIsSearching) {
|
||||||
debugPrint("[tap] AI's turn, skip tapping.");
|
debugPrint("[tap] AI's turn, skip tapping.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -231,12 +231,12 @@ class _GamePageState extends State<GamePage>
|
||||||
// Human to go
|
// Human to go
|
||||||
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
Chain.capture(() {
|
await Chain.capture(() async {
|
||||||
switch (position.action) {
|
switch (position.action) {
|
||||||
case Act.place:
|
case Act.place:
|
||||||
if (position.putPiece(sq)) {
|
if (await position.putPiece(sq)) {
|
||||||
if (position.action == Act.remove) {
|
if (position.action == Act.remove) {
|
||||||
//Audios.playTone(Audios.millSoundId);
|
//Audios.playTone(Audios.mill);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showTip(S.of(context).tipMill);
|
showTip(S.of(context).tipMill);
|
||||||
if (Config.screenReaderSupport) {
|
if (Config.screenReaderSupport) {
|
||||||
|
@ -244,7 +244,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Audios.playTone(Audios.placeSoundId);
|
//Audios.playTone(Audios.place);
|
||||||
if (gameInstance.engineType == EngineType.humanVsAi && mounted) {
|
if (gameInstance.engineType == EngineType.humanVsAi && mounted) {
|
||||||
if (rule.mayOnlyRemoveUnplacedPieceInPlacingPhase) {
|
if (rule.mayOnlyRemoveUnplacedPieceInPlacingPhase) {
|
||||||
showTip(S.of(context).continueToMakeMove);
|
showTip(S.of(context).continueToMakeMove);
|
||||||
|
@ -296,7 +296,7 @@ class _GamePageState extends State<GamePage>
|
||||||
final int selectRet = position.selectPiece(sq);
|
final int selectRet = position.selectPiece(sq);
|
||||||
switch (selectRet) {
|
switch (selectRet) {
|
||||||
case 0:
|
case 0:
|
||||||
Audios.playTone(Audios.selectSoundId);
|
await Audios.playTone(Sound.select);
|
||||||
gameInstance.select(index);
|
gameInstance.select(index);
|
||||||
ret = true;
|
ret = true;
|
||||||
debugPrint("[tap] selectPiece: [$sq]");
|
debugPrint("[tap] selectPiece: [$sq]");
|
||||||
|
@ -325,7 +325,7 @@ class _GamePageState extends State<GamePage>
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint("[tap] selectPiece: skip [$sq]");
|
debugPrint("[tap] selectPiece: skip [$sq]");
|
||||||
if (mounted && position.phase != Phase.gameOver) {
|
if (mounted && position.phase != Phase.gameOver) {
|
||||||
showTip(S.of(context).tipCannotMove);
|
showTip(S.of(context).tipCannotMove);
|
||||||
|
@ -336,7 +336,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint("[tap] selectPiece: skip [$sq]");
|
debugPrint("[tap] selectPiece: skip [$sq]");
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showTip(S.of(context).tipCanMoveOnePoint);
|
showTip(S.of(context).tipCanMoveOnePoint);
|
||||||
|
@ -347,7 +347,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case -4:
|
case -4:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint("[tap] selectPiece: skip [$sq]");
|
debugPrint("[tap] selectPiece: skip [$sq]");
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showTip(S.of(context).tipSelectPieceToMove);
|
showTip(S.of(context).tipSelectPieceToMove);
|
||||||
|
@ -357,7 +357,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint("[tap] selectPiece: skip [$sq]");
|
debugPrint("[tap] selectPiece: skip [$sq]");
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
showTip(S.of(context).tipSelectWrong);
|
showTip(S.of(context).tipSelectWrong);
|
||||||
|
@ -372,11 +372,11 @@ class _GamePageState extends State<GamePage>
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Act.remove:
|
case Act.remove:
|
||||||
final int removeRet = position.removePiece(sq);
|
final int removeRet = await position.removePiece(sq);
|
||||||
|
|
||||||
switch (removeRet) {
|
switch (removeRet) {
|
||||||
case 0:
|
case 0:
|
||||||
//Audios.playTone(Audios.removeSoundId);
|
//Audios.playTone(Audios.remove);
|
||||||
ret = true;
|
ret = true;
|
||||||
debugPrint("[tap] removePiece: [$sq]");
|
debugPrint("[tap] removePiece: [$sq]");
|
||||||
if (gameInstance.position.pieceToRemoveCount >= 1) {
|
if (gameInstance.position.pieceToRemoveCount >= 1) {
|
||||||
|
@ -404,7 +404,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case -2:
|
case -2:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"[tap] removePiece: Cannot Remove our pieces, skip [$sq]",
|
"[tap] removePiece: Cannot Remove our pieces, skip [$sq]",
|
||||||
);
|
);
|
||||||
|
@ -416,7 +416,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"[tap] removePiece: Cannot remove piece from Mill, skip [$sq]",
|
"[tap] removePiece: Cannot remove piece from Mill, skip [$sq]",
|
||||||
);
|
);
|
||||||
|
@ -432,7 +432,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Audios.playTone(Audios.illegalSoundId);
|
await Audios.playTone(Sound.illegal);
|
||||||
debugPrint("[tap] removePiece: skip [$sq]");
|
debugPrint("[tap] removePiece: skip [$sq]");
|
||||||
if (mounted && position.phase != Phase.gameOver) {
|
if (mounted && position.phase != Phase.gameOver) {
|
||||||
showTip(S.of(context).tipBanRemove);
|
showTip(S.of(context).tipBanRemove);
|
||||||
|
@ -587,7 +587,7 @@ class _GamePageState extends State<GamePage>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
gameInstance.doMove(move.move!);
|
await gameInstance.doMove(move.move!);
|
||||||
showTips();
|
showTips();
|
||||||
if (Config.screenReaderSupport && move.notation != null) {
|
if (Config.screenReaderSupport && move.notation != null) {
|
||||||
showSnackBar(context, "${S.of(context).ai}: ${move.notation!}");
|
showSnackBar(context, "${S.of(context).ai}: ${move.notation!}");
|
||||||
|
@ -657,7 +657,7 @@ class _GamePageState extends State<GamePage>
|
||||||
debugPrint("Clipboard text:");
|
debugPrint("Clipboard text:");
|
||||||
debugPrint(text);
|
debugPrint(text);
|
||||||
|
|
||||||
await onTakeBackAllButtonPressed(pop: false);
|
await onTakeBackAllButtonPressed(false);
|
||||||
gameInstance.position.recorder!.clear();
|
gameInstance.position.recorder!.clear();
|
||||||
final importFailedStr = gameInstance.position.recorder!.import(text);
|
final importFailedStr = gameInstance.position.recorder!.import(text);
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ class _GamePageState extends State<GamePage>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await onStepForwardAllButtonPressed(pop: false);
|
await onStepForwardAllButtonPressed(false);
|
||||||
|
|
||||||
showTip(S.of(context).gameImported);
|
showTip(S.of(context).gameImported);
|
||||||
if (Config.screenReaderSupport) {
|
if (Config.screenReaderSupport) {
|
||||||
|
@ -774,8 +774,8 @@ class _GamePageState extends State<GamePage>
|
||||||
Future<void> onAutoReplayButtonPressed() async {
|
Future<void> onAutoReplayButtonPressed() async {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
||||||
await onTakeBackAllButtonPressed(pop: false);
|
await onTakeBackAllButtonPressed(false);
|
||||||
await onStepForwardAllButtonPressed(pop: false);
|
await onStepForwardAllButtonPressed(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onGameButtonPressed() {
|
void onGameButtonPressed() {
|
||||||
|
@ -969,8 +969,9 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onGotoHistoryButtonsPressed(
|
Future<void> onGotoHistoryButtonsPressed(
|
||||||
Future<String> func, {
|
HistoryMove move, {
|
||||||
bool pop = true,
|
bool pop = true,
|
||||||
|
int? number,
|
||||||
}) async {
|
}) async {
|
||||||
if (pop == true) {
|
if (pop == true) {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
@ -989,9 +990,7 @@ class _GamePageState extends State<GamePage>
|
||||||
|
|
||||||
isGoingToHistory = true;
|
isGoingToHistory = true;
|
||||||
|
|
||||||
Audios.isTemporaryMute = Config.keepMuteWhenTakingBack;
|
final errMove = await gameInstance.position.gotoHistory(move, number);
|
||||||
|
|
||||||
final errMove = await func;
|
|
||||||
|
|
||||||
switch (errMove) {
|
switch (errMove) {
|
||||||
case "":
|
case "":
|
||||||
|
@ -1008,14 +1007,10 @@ class _GamePageState extends State<GamePage>
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Audios.isTemporaryMute = false;
|
|
||||||
|
|
||||||
isGoingToHistory = false;
|
isGoingToHistory = false;
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
String text = "";
|
|
||||||
final pos = gameInstance.position;
|
final pos = gameInstance.position;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
String us = "";
|
String us = "";
|
||||||
String them = "";
|
String them = "";
|
||||||
|
@ -1028,6 +1023,7 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
late final String text;
|
||||||
final lastEffectiveMove = pos.recorder!.lastEffectiveMove;
|
final lastEffectiveMove = pos.recorder!.lastEffectiveMove;
|
||||||
if (lastEffectiveMove != null && lastEffectiveMove.notation != null) {
|
if (lastEffectiveMove != null && lastEffectiveMove.notation != null) {
|
||||||
text = "${S.of(context).lastMove}: ${lastEffectiveMove.notation}";
|
text = "${S.of(context).lastMove}: ${lastEffectiveMove.notation}";
|
||||||
|
@ -1044,28 +1040,37 @@ class _GamePageState extends State<GamePage>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onTakeBackButtonPressed({bool pop = true}) async {
|
Future<void> onTakeBackButtonPressed([bool pop = true]) async =>
|
||||||
onGotoHistoryButtonsPressed(gameInstance.position.takeBack(), pop: pop);
|
onGotoHistoryButtonsPressed(
|
||||||
}
|
HistoryMove.backOne,
|
||||||
|
pop: pop,
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> onStepForwardButtonPressed({bool pop = true}) async {
|
Future<void> onStepForwardButtonPressed([bool pop = true]) async =>
|
||||||
onGotoHistoryButtonsPressed(gameInstance.position.stepForward(), pop: pop);
|
onGotoHistoryButtonsPressed(
|
||||||
}
|
HistoryMove.farward,
|
||||||
|
pop: pop,
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> onTakeBackAllButtonPressed({bool pop = true}) async {
|
Future<void> onTakeBackAllButtonPressed([bool pop = true]) async =>
|
||||||
onGotoHistoryButtonsPressed(gameInstance.position.takeBackAll(), pop: pop);
|
onGotoHistoryButtonsPressed(
|
||||||
}
|
HistoryMove.backAll,
|
||||||
|
pop: pop,
|
||||||
|
);
|
||||||
|
|
||||||
Future<void> onStepForwardAllButtonPressed({bool pop = true}) async {
|
Future<void> onStepForwardAllButtonPressed([bool pop = true]) async {
|
||||||
onGotoHistoryButtonsPressed(
|
onGotoHistoryButtonsPressed(
|
||||||
gameInstance.position.stepForwardAll(),
|
HistoryMove.forwardAll,
|
||||||
pop: pop,
|
pop: pop,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onTakeBackNButtonPressed(int n, {bool pop = true}) async {
|
Future<void> onTakeBackNButtonPressed(int n, [bool pop = true]) async =>
|
||||||
onGotoHistoryButtonsPressed(gameInstance.position.takeBackN(n), pop: pop);
|
onGotoHistoryButtonsPressed(
|
||||||
}
|
HistoryMove.backN,
|
||||||
|
number: n,
|
||||||
|
pop: pop,
|
||||||
|
);
|
||||||
|
|
||||||
void onMoveListButtonPressed() {
|
void onMoveListButtonPressed() {
|
||||||
final moveHistoryText = gameInstance.position.moveHistoryText;
|
final moveHistoryText = gameInstance.position.moveHistoryText;
|
||||||
|
@ -1177,7 +1182,7 @@ class _GamePageState extends State<GamePage>
|
||||||
|
|
||||||
debugPrint("[config] isPrivacyPolicyAccepted: $value");
|
debugPrint("[config] isPrivacyPolicyAccepted: $value");
|
||||||
|
|
||||||
Config.save();
|
await Config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> onShowPrivacyDialog() async {
|
Future<void> onShowPrivacyDialog() async {
|
||||||
|
@ -1259,10 +1264,10 @@ class _GamePageState extends State<GamePage>
|
||||||
|
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case GameResult.win:
|
case GameResult.win:
|
||||||
//Audios.playTone(Audios.winSoundId);
|
//Audios.playTone(Audios.win);
|
||||||
break;
|
break;
|
||||||
case GameResult.lose:
|
case GameResult.lose:
|
||||||
//Audios.playTone(Audios.loseSoundId);
|
//Audios.playTone(Audios.lose);
|
||||||
break;
|
break;
|
||||||
case GameResult.draw:
|
case GameResult.draw:
|
||||||
break;
|
break;
|
||||||
|
@ -1694,7 +1699,7 @@ class _GamePageState extends State<GamePage>
|
||||||
color: Color(Config.navigationToolbarIconColor),
|
color: Color(Config.navigationToolbarIconColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => onTakeBackAllButtonPressed(pop: false),
|
onPressed: () => onTakeBackAllButtonPressed(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
final takeBackButton = TextButton(
|
final takeBackButton = TextButton(
|
||||||
|
@ -1707,7 +1712,7 @@ class _GamePageState extends State<GamePage>
|
||||||
color: Color(Config.navigationToolbarIconColor),
|
color: Color(Config.navigationToolbarIconColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => onTakeBackButtonPressed(pop: false),
|
onPressed: () async => onTakeBackButtonPressed(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
final stepForwardButton = TextButton(
|
final stepForwardButton = TextButton(
|
||||||
|
@ -1720,7 +1725,7 @@ class _GamePageState extends State<GamePage>
|
||||||
color: Color(Config.navigationToolbarIconColor),
|
color: Color(Config.navigationToolbarIconColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => onStepForwardButtonPressed(pop: false),
|
onPressed: () async => onStepForwardButtonPressed(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
final stepForwardAllButton = TextButton(
|
final stepForwardAllButton = TextButton(
|
||||||
|
@ -1733,7 +1738,7 @@ class _GamePageState extends State<GamePage>
|
||||||
color: Color(Config.navigationToolbarIconColor),
|
color: Color(Config.navigationToolbarIconColor),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => onStepForwardAllButtonPressed(pop: false),
|
onPressed: () async => onStepForwardAllButtonPressed(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
return GamePageToolBar(
|
return GamePageToolBar(
|
||||||
|
|
|
@ -24,22 +24,35 @@ import 'package:sanmill/shared/common/config.dart';
|
||||||
import 'package:soundpool/soundpool.dart';
|
import 'package:soundpool/soundpool.dart';
|
||||||
import 'package:stack_trace/stack_trace.dart';
|
import 'package:stack_trace/stack_trace.dart';
|
||||||
|
|
||||||
|
enum Sound {
|
||||||
|
draw,
|
||||||
|
fly,
|
||||||
|
go,
|
||||||
|
illegal,
|
||||||
|
lose,
|
||||||
|
mill,
|
||||||
|
place,
|
||||||
|
remove,
|
||||||
|
select,
|
||||||
|
win,
|
||||||
|
}
|
||||||
|
|
||||||
class Audios {
|
class Audios {
|
||||||
const Audios._();
|
const Audios._();
|
||||||
//static AudioPlayer? _player;
|
//static AudioPlayer? _player;
|
||||||
static Soundpool? _soundpool;
|
static final Soundpool _soundpool = Soundpool.fromOptions();
|
||||||
// TODO: use enum for the sounds
|
static bool _initialized = false;
|
||||||
static int? _alarmSoundStreamId;
|
static int _alarmSoundStreamId = 0;
|
||||||
static int? drawSoundId;
|
static late final int _drawSoundId;
|
||||||
static int? flySoundId;
|
static late final int _flySoundId;
|
||||||
static int? goSoundId;
|
static late final int _goSoundId;
|
||||||
static int? illegalSoundId;
|
static late final int _illegalSoundId;
|
||||||
static int? loseSoundId;
|
static late final int _loseSoundId;
|
||||||
static int? millSoundId;
|
static late final int _millSoundId;
|
||||||
static int? placeSoundId;
|
static late final int _placeSoundId;
|
||||||
static int? removeSoundId;
|
static late final int _removeSoundId;
|
||||||
static int? selectSoundId;
|
static late final int _selectSoundId;
|
||||||
static int? winSoundId;
|
static late final int _winSoundId;
|
||||||
static bool isTemporaryMute = false;
|
static bool isTemporaryMute = false;
|
||||||
|
|
||||||
static Future<void> loadSounds() async {
|
static Future<void> loadSounds() async {
|
||||||
|
@ -48,156 +61,110 @@ class Audios {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_soundpool ??= Soundpool.fromOptions();
|
_drawSoundId = await _soundpool.load(
|
||||||
|
await rootBundle.load("assets/audios/draw.mp3"),
|
||||||
|
);
|
||||||
|
|
||||||
if (_soundpool == null) {
|
_flySoundId = await _soundpool.load(
|
||||||
if (Config.developerMode) {
|
await rootBundle.load("assets/audios/fly.mp3"),
|
||||||
assert(false);
|
);
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: _soundpool is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
drawSoundId ??=
|
_goSoundId = await _soundpool.load(
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/draw.mp3"));
|
await rootBundle.load("assets/audios/go.mp3"),
|
||||||
if (drawSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: drawSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
flySoundId ??=
|
_illegalSoundId = await _soundpool.load(
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/fly.mp3"));
|
await rootBundle.load("assets/audios/illegal.mp3"),
|
||||||
if (flySoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: flySoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
goSoundId ??=
|
_loseSoundId = await _soundpool.load(
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/go.mp3"));
|
await rootBundle.load("assets/audios/lose.mp3"),
|
||||||
if (goSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: goSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
illegalSoundId = await _soundpool!
|
_millSoundId = await _soundpool.load(
|
||||||
.load(await rootBundle.load("assets/audios/illegal.mp3"));
|
await rootBundle.load("assets/audios/mill.mp3"),
|
||||||
if (illegalSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: illegalSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loseSoundId ??=
|
_placeSoundId = await _soundpool.load(
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/lose.mp3"));
|
await rootBundle.load("assets/audios/place.mp3"),
|
||||||
if (loseSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: loseSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
millSoundId ??=
|
_removeSoundId = await _soundpool.load(
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/mill.mp3"));
|
await rootBundle.load("assets/audios/remove.mp3"),
|
||||||
if (millSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: millSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
placeSoundId ??= await _soundpool!
|
_selectSoundId = await _soundpool.load(
|
||||||
.load(await rootBundle.load("assets/audios/place.mp3"));
|
await rootBundle.load("assets/audios/select.mp3"),
|
||||||
if (placeSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: placeSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
removeSoundId ??= await _soundpool!
|
_winSoundId = await _soundpool.load(
|
||||||
.load(await rootBundle.load("assets/audios/remove.mp3"));
|
await rootBundle.load("assets/audios/win.mp3"),
|
||||||
if (removeSoundId == null) {
|
);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: removeSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
selectSoundId ??= await _soundpool!
|
_initialized = true;
|
||||||
.load(await rootBundle.load("assets/audios/select.mp3"));
|
|
||||||
if (selectSoundId == null) {
|
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: selectSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
winSoundId ??=
|
|
||||||
await _soundpool!.load(await rootBundle.load("assets/audios/win.mp3"));
|
|
||||||
if (winSoundId == null) {
|
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: winSoundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _playSound(int? soundId) async {
|
static Future<void> _playSound(Sound sound) async {
|
||||||
if (Platform.isWindows) {
|
assert(!Platform.isWindows);
|
||||||
return;
|
|
||||||
|
late final int soundId;
|
||||||
|
|
||||||
|
switch (sound) {
|
||||||
|
case Sound.draw:
|
||||||
|
soundId = _drawSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.fly:
|
||||||
|
soundId = _flySoundId;
|
||||||
|
break;
|
||||||
|
case Sound.go:
|
||||||
|
soundId = _goSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.illegal:
|
||||||
|
soundId = _illegalSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.lose:
|
||||||
|
soundId = _loseSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.mill:
|
||||||
|
soundId = _millSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.place:
|
||||||
|
soundId = _placeSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.remove:
|
||||||
|
soundId = _removeSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.select:
|
||||||
|
soundId = _selectSoundId;
|
||||||
|
break;
|
||||||
|
case Sound.win:
|
||||||
|
soundId = _winSoundId;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundId == null) {
|
_alarmSoundStreamId = await _soundpool.play(soundId);
|
||||||
if (Config.developerMode) {
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
debugPrint("[audio] Error: soundId is null.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_alarmSoundStreamId = await _soundpool!.play(soundId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> _stopSound() async {
|
static Future<void> _stopSound() async {
|
||||||
if (Platform.isWindows) {
|
assert(!Platform.isWindows);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_alarmSoundStreamId != null && _alarmSoundStreamId! > 0) {
|
if (_alarmSoundStreamId > 0) {
|
||||||
await _soundpool!.stop(_alarmSoundStreamId!);
|
await _soundpool.stop(_alarmSoundStreamId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> disposePool() async {
|
static void disposePool() {
|
||||||
if (Platform.isWindows) {
|
assert(!Platform.isWindows);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_soundpool!.dispose();
|
_soundpool.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> playTone(int? soundId) async {
|
static Future<void> playTone(Sound sound) async {
|
||||||
Chain.capture(() async {
|
await Chain.capture(() async {
|
||||||
if (!Config.toneEnabled ||
|
if (!Config.toneEnabled ||
|
||||||
isTemporaryMute ||
|
isTemporaryMute ||
|
||||||
Config.screenReaderSupport) {
|
Config.screenReaderSupport ||
|
||||||
|
!_initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,14 +173,11 @@ class Audios {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: isn't debug chain meant to catch errors? so why catching them in here and not in onError??
|
||||||
try {
|
try {
|
||||||
if (_soundpool == null) {
|
|
||||||
await loadSounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
await _stopSound();
|
await _stopSound();
|
||||||
|
|
||||||
_playSound(soundId);
|
await _playSound(sound);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Fallback for all errors
|
// Fallback for all errors
|
||||||
debugPrint(e.toString());
|
debugPrint(e.toString());
|
||||||
|
|
|
@ -111,7 +111,7 @@ class _DrawerControllerState extends State<DrawerController>
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> getInitState() async {
|
bool getInitState() {
|
||||||
scrollController.jumpTo(
|
scrollController.jumpTo(
|
||||||
widget.drawerWidth,
|
widget.drawerWidth,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue