flutter: Migrate to null-safety (2, tools)
This commit is contained in:
parent
1fe2b01741
commit
42aade876b
|
@ -23,24 +23,24 @@ import 'package:path_provider/path_provider.dart';
|
|||
|
||||
class Profile {
|
||||
static const defaultFileName = 'default-profile.json';
|
||||
static Profile _shared;
|
||||
static Profile? _shared;
|
||||
|
||||
File _file;
|
||||
Map<String, dynamic> _values = {};
|
||||
late File _file;
|
||||
Map<String, dynamic>? _values = {};
|
||||
|
||||
static shared() async {
|
||||
if (_shared == null) {
|
||||
_shared = Profile();
|
||||
await _shared._load(defaultFileName);
|
||||
await _shared!._load(defaultFileName);
|
||||
print("defaultFileName: $defaultFileName");
|
||||
}
|
||||
|
||||
return _shared;
|
||||
}
|
||||
|
||||
operator [](String key) => _values[key];
|
||||
operator [](String key) => _values![key];
|
||||
|
||||
operator []=(String key, dynamic value) => _values[key] = value;
|
||||
operator []=(String key, dynamic value) => _values![key] = value;
|
||||
|
||||
Future<bool> commit() async {
|
||||
_file.create(recursive: true);
|
||||
|
|
|
@ -38,5 +38,5 @@ abstract class AiEngine {
|
|||
Future<void> setOptions() async {}
|
||||
Future<void> startup() async {}
|
||||
Future<void> shutdown() async {}
|
||||
Future<EngineResponse> search(Position position, {bool byUser = true});
|
||||
Future<EngineResponse> search(Position? position, {bool byUser = true});
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class NativeEngine extends AiEngine {
|
|||
await platform.invokeMethod('send', command);
|
||||
}
|
||||
|
||||
Future<String> read() async {
|
||||
Future<String?> read() async {
|
||||
return await platform.invokeMethod('read');
|
||||
}
|
||||
|
||||
|
@ -46,19 +46,19 @@ class NativeEngine extends AiEngine {
|
|||
await platform.invokeMethod('shutdown');
|
||||
}
|
||||
|
||||
Future<bool> isReady() async {
|
||||
Future<bool?> isReady() async {
|
||||
return await platform.invokeMethod('isReady');
|
||||
}
|
||||
|
||||
FutureOr<bool> isThinking() async {
|
||||
FutureOr<bool?> isThinking() async {
|
||||
return await platform.invokeMethod('isThinking');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EngineResponse> search(Position position, {bool byUser = true}) async {
|
||||
if (await isThinking()) await stopSearching();
|
||||
Future<EngineResponse> search(Position? position, {bool byUser = true}) async {
|
||||
if (await (isThinking() as FutureOr<bool>)) await stopSearching();
|
||||
|
||||
send(getPositionFen(position));
|
||||
send(getPositionFen(position!));
|
||||
send('go');
|
||||
|
||||
final response = await waitResponse(['bestmove', 'nobestmove']);
|
||||
|
|
|
@ -45,7 +45,7 @@ Future<void> main() async {
|
|||
//String formattedDate = DateFormat('yyyy-MM-dd_kk-mm').format(now);
|
||||
String externalDirStr;
|
||||
try {
|
||||
Directory externalDir = await getExternalStorageDirectory();
|
||||
Directory externalDir = await (getExternalStorageDirectory() as FutureOr<Directory>);
|
||||
externalDirStr = externalDir.path.toString();
|
||||
} catch (e) {
|
||||
print(e);
|
||||
|
|
|
@ -27,7 +27,7 @@ enum PlayerType { human, AI }
|
|||
Map<String, bool> isAi = {PieceColor.black: false, PieceColor.white: true};
|
||||
|
||||
class Game {
|
||||
static Game _instance;
|
||||
static Game? _instance;
|
||||
|
||||
Position _position = Position();
|
||||
int _focusIndex = Move.invalidMove;
|
||||
|
@ -100,7 +100,7 @@ class Game {
|
|||
|
||||
String getTips() => tips;
|
||||
|
||||
bool isAiToMove() {
|
||||
bool? isAiToMove() {
|
||||
return isAi[sideToMove];
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ class Move {
|
|||
String removed = Piece.noPiece;
|
||||
|
||||
// 'move' is the UCI engine's move-string
|
||||
String move = "";
|
||||
String? move = "";
|
||||
|
||||
MoveType type = MoveType.none;
|
||||
|
||||
|
@ -125,26 +125,26 @@ class Move {
|
|||
throw "Error: Invalid Move: $move";
|
||||
}
|
||||
|
||||
if (move[0] == '-' && move.length == "-(1,2)".length) {
|
||||
if (move![0] == '-' && move!.length == "-(1,2)".length) {
|
||||
type = MoveType.remove;
|
||||
from = fromFile = fromRank = fromIndex = invalidMove;
|
||||
toFile = int.parse(move[2]);
|
||||
toRank = int.parse(move[4]);
|
||||
toFile = int.parse(move![2]);
|
||||
toRank = int.parse(move![4]);
|
||||
//captured = Piece.noPiece;
|
||||
} else if (move.length == "(1,2)->(3,4)".length) {
|
||||
} else if (move!.length == "(1,2)->(3,4)".length) {
|
||||
type = MoveType.move;
|
||||
fromFile = int.parse(move[1]);
|
||||
fromRank = int.parse(move[3]);
|
||||
fromFile = int.parse(move![1]);
|
||||
fromRank = int.parse(move![3]);
|
||||
from = makeSquare(fromFile, fromRank);
|
||||
fromIndex = squareToIndex[from] ?? invalidMove;
|
||||
toFile = int.parse(move[8]);
|
||||
toRank = int.parse(move[10]);
|
||||
toFile = int.parse(move![8]);
|
||||
toRank = int.parse(move![10]);
|
||||
removed = Piece.noPiece;
|
||||
} else if (move.length == "(1,2)".length) {
|
||||
} else if (move!.length == "(1,2)".length) {
|
||||
type = MoveType.place;
|
||||
from = fromFile = fromRank = fromIndex = invalidMove;
|
||||
toFile = int.parse(move[1]);
|
||||
toRank = int.parse(move[3]);
|
||||
toFile = int.parse(move![1]);
|
||||
toRank = int.parse(move![3]);
|
||||
removed = Piece.noPiece;
|
||||
} else if (move == "draw") {
|
||||
// TODO
|
||||
|
@ -171,7 +171,7 @@ class Move {
|
|||
parse();
|
||||
}
|
||||
|
||||
static bool legal(String move) {
|
||||
static bool legal(String? move) {
|
||||
if (move == "draw") {
|
||||
return true; // TODO
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ class Position {
|
|||
List<String> board = List.filled(sqNumber, "");
|
||||
List<String> _grid = List.filled(7 * 7, "");
|
||||
|
||||
GameRecorder recorder;
|
||||
GameRecorder? recorder;
|
||||
|
||||
Map<String, int> pieceInHandCount = {
|
||||
PieceColor.black: -1,
|
||||
|
@ -64,7 +64,7 @@ class Position {
|
|||
int pliesFromNull = 0;
|
||||
|
||||
// TODO
|
||||
StateInfo st;
|
||||
StateInfo? st;
|
||||
|
||||
String us = PieceColor.black;
|
||||
String them = PieceColor.white;
|
||||
|
@ -84,25 +84,25 @@ class Position {
|
|||
int currentSquare = 0;
|
||||
int nPlayed = 0;
|
||||
|
||||
String cmdline;
|
||||
String? cmdline;
|
||||
|
||||
var millTable;
|
||||
var moveTable;
|
||||
late var millTable;
|
||||
late var moveTable;
|
||||
|
||||
// TODO: null-safety
|
||||
Move move;
|
||||
Move? move;
|
||||
|
||||
Position.boardToGrid() {
|
||||
_grid = [];
|
||||
for (int sq = 0; sq < board.length; sq++) {
|
||||
_grid[squareToIndex[sq]] = board[sq];
|
||||
_grid[squareToIndex[sq]!] = board[sq];
|
||||
}
|
||||
}
|
||||
|
||||
Position.gridToBoard() {
|
||||
board = [];
|
||||
for (int i = 0; i < _grid.length; i++) {
|
||||
board[indexToSquare[i]] = _grid[i];
|
||||
board[indexToSquare[i]!] = _grid[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ class Position {
|
|||
// Piece placement data
|
||||
for (var file = 1; file <= fileNumber; file++) {
|
||||
for (var rank = 1; rank <= rankNumber; rank++) {
|
||||
final piece = pieceOnGrid(squareToIndex[makeSquare(file, rank)]);
|
||||
final piece = pieceOnGrid(squareToIndex[makeSquare(file, rank)]!);
|
||||
ss += piece;
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ class Position {
|
|||
phase = Phase.gameOver;
|
||||
winner = PieceColor.draw;
|
||||
if (score[PieceColor.draw] != null) {
|
||||
score[PieceColor.draw] = score[PieceColor.draw] + 1;
|
||||
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
@ -374,7 +374,7 @@ class Position {
|
|||
|
||||
this.move = m;
|
||||
|
||||
recorder.moveIn(m, this);
|
||||
recorder!.moveIn(m, this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -396,34 +396,34 @@ class Position {
|
|||
if (board[s] == Piece.blackStone) {
|
||||
if (pieceOnBoardCount[PieceColor.black] != null) {
|
||||
pieceOnBoardCount[PieceColor.black] =
|
||||
pieceOnBoardCount[PieceColor.black] + 1;
|
||||
pieceOnBoardCount[PieceColor.black]! + 1;
|
||||
}
|
||||
} else if (board[s] == Piece.whiteStone) {
|
||||
if (pieceOnBoardCount[PieceColor.white] != null) {
|
||||
pieceOnBoardCount[PieceColor.white] =
|
||||
pieceOnBoardCount[PieceColor.white] + 1;
|
||||
pieceOnBoardCount[PieceColor.white]! + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pieceOnBoardCount[PieceColor.black] > rule.piecesCount ||
|
||||
pieceOnBoardCount[PieceColor.white] > rule.piecesCount) {
|
||||
if (pieceOnBoardCount[PieceColor.black]! > rule.piecesCount ||
|
||||
pieceOnBoardCount[PieceColor.white]! > rule.piecesCount) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pieceOnBoardCount[PieceColor.black] +
|
||||
pieceOnBoardCount[PieceColor.white];
|
||||
return pieceOnBoardCount[PieceColor.black]! +
|
||||
pieceOnBoardCount[PieceColor.white]!;
|
||||
}
|
||||
|
||||
int getNPiecesInHand() {
|
||||
pieceInHandCount[PieceColor.black] =
|
||||
rule.piecesCount - pieceOnBoardCount[PieceColor.black];
|
||||
rule.piecesCount - pieceOnBoardCount[PieceColor.black]!;
|
||||
pieceInHandCount[PieceColor.white] =
|
||||
rule.piecesCount - pieceOnBoardCount[PieceColor.white];
|
||||
rule.piecesCount - pieceOnBoardCount[PieceColor.white]!;
|
||||
|
||||
return pieceOnBoardCount[PieceColor.black] +
|
||||
pieceOnBoardCount[PieceColor.white];
|
||||
return pieceOnBoardCount[PieceColor.black]! +
|
||||
pieceOnBoardCount[PieceColor.white]!;
|
||||
}
|
||||
|
||||
void clearBoard() {
|
||||
|
@ -538,14 +538,14 @@ class Position {
|
|||
if (phase == Phase.placing) {
|
||||
piece = sideToMove();
|
||||
if (pieceInHandCount[us] != null) {
|
||||
pieceInHandCount[us] = pieceInHandCount[us] - 1;
|
||||
pieceInHandCount[us] = pieceInHandCount[us]! - 1;
|
||||
}
|
||||
|
||||
if (pieceOnBoardCount[us] != null) {
|
||||
pieceOnBoardCount[us] = pieceOnBoardCount[us] + 1;
|
||||
pieceOnBoardCount[us] = pieceOnBoardCount[us]! + 1;
|
||||
}
|
||||
|
||||
_grid[index] = piece;
|
||||
_grid[index!] = piece;
|
||||
board[s] = piece;
|
||||
|
||||
cmdline = "(" + fileOf(s).toString() + "," + rankOf(s).toString() + ")";
|
||||
|
@ -555,8 +555,8 @@ class Position {
|
|||
int n = millsCount(currentSquare);
|
||||
|
||||
if (n == 0) {
|
||||
assert(pieceInHandCount[PieceColor.black] >= 0 &&
|
||||
pieceInHandCount[PieceColor.white] >= 0);
|
||||
assert(pieceInHandCount[PieceColor.black]! >= 0 &&
|
||||
pieceInHandCount[PieceColor.white]! >= 0);
|
||||
|
||||
if (pieceInHandCount[PieceColor.black] == 0 &&
|
||||
pieceInHandCount[PieceColor.white] == 0) {
|
||||
|
@ -598,7 +598,7 @@ class Position {
|
|||
}
|
||||
|
||||
// if illegal
|
||||
if (pieceOnBoardCount[sideToMove()] > rule.piecesAtLeastCount ||
|
||||
if (pieceOnBoardCount[sideToMove()]! > rule.piecesAtLeastCount ||
|
||||
!rule.mayFly) {
|
||||
int md;
|
||||
|
||||
|
@ -625,9 +625,9 @@ class Position {
|
|||
|
||||
rule50++;
|
||||
|
||||
board[s] = _grid[squareToIndex[s]] = board[currentSquare];
|
||||
board[s] = _grid[squareToIndex[s]!] = board[currentSquare];
|
||||
board[currentSquare] =
|
||||
_grid[squareToIndex[currentSquare]] = Piece.noPiece;
|
||||
_grid[squareToIndex[currentSquare]!] = Piece.noPiece;
|
||||
|
||||
currentSquare = s;
|
||||
int n = millsCount(currentSquare);
|
||||
|
@ -676,20 +676,20 @@ class Position {
|
|||
Audios.playTone('remove.mp3');
|
||||
|
||||
if (rule.hasBannedLocations && phase == Phase.placing) {
|
||||
board[s] = _grid[squareToIndex[s]] = Piece.ban;
|
||||
board[s] = _grid[squareToIndex[s]!] = Piece.ban;
|
||||
} else {
|
||||
// Remove
|
||||
board[s] = _grid[squareToIndex[s]] = Piece.noPiece;
|
||||
board[s] = _grid[squareToIndex[s]!] = Piece.noPiece;
|
||||
}
|
||||
|
||||
cmdline = "-(" + fileOf(s).toString() + "," + rankOf(s).toString() + ")";
|
||||
rule50 = 0; // TODO: Need to move out?
|
||||
|
||||
if (pieceOnBoardCount[them] != null) {
|
||||
pieceOnBoardCount[them] = pieceOnBoardCount[them] - 1;
|
||||
pieceOnBoardCount[them] = pieceOnBoardCount[them]! - 1;
|
||||
}
|
||||
|
||||
if (pieceOnBoardCount[them] + pieceInHandCount[them] <
|
||||
if (pieceOnBoardCount[them]! + pieceInHandCount[them]! <
|
||||
rule.piecesAtLeastCount) {
|
||||
setGameOver(sideToMove(), GameOverReason.loseReasonlessThanThree);
|
||||
return true;
|
||||
|
@ -775,14 +775,14 @@ class Position {
|
|||
if (phase == Phase.gameOver) {
|
||||
if (winner == PieceColor.draw) {
|
||||
if (score[PieceColor.draw] != null) {
|
||||
score[PieceColor.draw] = score[PieceColor.draw] + 1;
|
||||
score[PieceColor.draw] = score[PieceColor.draw]! + 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (score[winner] != null) {
|
||||
score[winner] = score[winner] + 1;
|
||||
score[winner] = score[winner]! + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -802,8 +802,8 @@ class Position {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (pieceOnBoardCount[PieceColor.black] +
|
||||
pieceOnBoardCount[PieceColor.white] >=
|
||||
if (pieceOnBoardCount[PieceColor.black]! +
|
||||
pieceOnBoardCount[PieceColor.white]! >=
|
||||
rankNumber * fileNumber) {
|
||||
if (rule.isBlackLoseButNotDrawWhenBoardFull) {
|
||||
setGameOver(PieceColor.white, GameOverReason.loseReasonBoardIsFull);
|
||||
|
@ -842,7 +842,7 @@ class Position {
|
|||
s = f * rankNumber + r;
|
||||
|
||||
if (board[s] == Piece.ban) {
|
||||
board[s] = _grid[squareToIndex[s]] = Piece.noPiece;
|
||||
board[s] = _grid[squareToIndex[s]!] = Piece.noPiece;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1389,7 +1389,7 @@ class Position {
|
|||
|
||||
if (from != 0) {
|
||||
ptBak = board[from];
|
||||
board[from] = _grid[squareToIndex[from]] = Piece.noPiece;
|
||||
board[from] = _grid[squareToIndex[from]!] = Piece.noPiece;
|
||||
}
|
||||
|
||||
for (int l = 0; l < lineDirectionNumber; l++) {
|
||||
|
@ -1399,7 +1399,7 @@ class Position {
|
|||
}
|
||||
|
||||
if (from != 0) {
|
||||
board[from] = _grid[squareToIndex[from]] = ptBak;
|
||||
board[from] = _grid[squareToIndex[from]!] = ptBak;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
@ -1407,9 +1407,9 @@ class Position {
|
|||
|
||||
int millsCount(int s) {
|
||||
int n = 0;
|
||||
List<int> idx = [0, 0, 0];
|
||||
List<int?> idx = [0, 0, 0];
|
||||
int min = 0;
|
||||
int temp = 0;
|
||||
int? temp = 0;
|
||||
String m = colorOn(s);
|
||||
|
||||
for (int i = 0; i < idx.length; i++) {
|
||||
|
@ -1418,7 +1418,7 @@ class Position {
|
|||
idx[2] = millTable[s][i][1];
|
||||
|
||||
// no mill
|
||||
if (!(m == board[idx[1]] && m == board[idx[2]])) {
|
||||
if (!(m == board[idx[1]!] && m == board[idx[2]!])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1429,7 +1429,7 @@ class Position {
|
|||
min = j;
|
||||
|
||||
for (int k = j + 1; k < 3; k++) {
|
||||
if (idx[min] > idx[k]) min = k;
|
||||
if (idx[min]! > idx[k]!) min = k;
|
||||
}
|
||||
|
||||
if (min == j) {
|
||||
|
@ -1461,21 +1461,21 @@ class Position {
|
|||
|
||||
bool isAllSurrounded() {
|
||||
// Full
|
||||
if (pieceOnBoardCount[PieceColor.black] +
|
||||
pieceOnBoardCount[PieceColor.white] >=
|
||||
if (pieceOnBoardCount[PieceColor.black]! +
|
||||
pieceOnBoardCount[PieceColor.white]! >=
|
||||
rankNumber * fileNumber) {
|
||||
//print("Board is full.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Can fly
|
||||
if (pieceOnBoardCount[sideToMove()] <= rule.piecesAtLeastCount &&
|
||||
if (pieceOnBoardCount[sideToMove()]! <= rule.piecesAtLeastCount &&
|
||||
rule.mayFly) {
|
||||
//print("Can fly.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int moveSquare;
|
||||
int? moveSquare;
|
||||
|
||||
for (int s = sqBegin; s < sqEnd; s++) {
|
||||
if (!(sideToMove() == colorOn(s))) {
|
||||
|
@ -1484,7 +1484,7 @@ class Position {
|
|||
|
||||
for (int d = moveDirectionBegin; d < moveDirectionNumber; d++) {
|
||||
moveSquare = moveTable[s][d];
|
||||
if (moveSquare != 0 && board[moveSquare] == Piece.noPiece) {
|
||||
if (moveSquare != 0 && board[moveSquare!] == Piece.noPiece) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1506,7 +1506,7 @@ class Position {
|
|||
|
||||
bool regret() {
|
||||
// TODO
|
||||
final lastMove = recorder.removeLast();
|
||||
final lastMove = recorder!.removeLast();
|
||||
if (lastMove == null) return false;
|
||||
|
||||
_grid[lastMove.from] = _grid[lastMove.to];
|
||||
|
@ -1517,15 +1517,15 @@ class Position {
|
|||
changeSideToMove();
|
||||
|
||||
final counterMarks = GameRecorder.fromCounterMarks(lastMove.counterMarks);
|
||||
recorder.halfMove = counterMarks.halfMove;
|
||||
recorder.fullMove = counterMarks.fullMove;
|
||||
recorder!.halfMove = counterMarks.halfMove;
|
||||
recorder!.fullMove = counterMarks.fullMove;
|
||||
|
||||
if (lastMove.removed != Piece.noPiece) {
|
||||
//
|
||||
// Find last remove position (or opening), NativeEngine need
|
||||
final tempPosition = Position.clone(this);
|
||||
|
||||
final moves = recorder.reverseMovesToPrevRemove();
|
||||
final moves = recorder!.reverseMovesToPrevRemove();
|
||||
moves.forEach((move) {
|
||||
//
|
||||
tempPosition._grid[move.from] = tempPosition._grid[move.to];
|
||||
|
@ -1535,7 +1535,7 @@ class Position {
|
|||
PieceColor.opponent(tempPosition._sideToMove);
|
||||
});
|
||||
|
||||
recorder.lastPositionWithRemove = tempPosition.fen();
|
||||
recorder!.lastPositionWithRemove = tempPosition.fen();
|
||||
}
|
||||
|
||||
result = GameResult.pending;
|
||||
|
@ -1544,15 +1544,15 @@ class Position {
|
|||
}
|
||||
|
||||
String movesSinceLastRemove() {
|
||||
int i = 0;
|
||||
int? i = 0;
|
||||
String moves = "";
|
||||
int posAfterLastRemove = 0;
|
||||
|
||||
//print("recorder.movesCount = ${recorder.movesCount}");
|
||||
|
||||
for (i = recorder.movesCount - 1; i >= 0; i--) {
|
||||
for (i = recorder!.movesCount - 1; i! >= 0; i--) {
|
||||
//if (recorder.moveAt(i).type == MoveType.remove) break;
|
||||
if (recorder.moveAt(i).move[0] == '-') break;
|
||||
if (recorder!.moveAt(i).move![0] == '-') break;
|
||||
}
|
||||
|
||||
if (i >= 0) {
|
||||
|
@ -1561,8 +1561,8 @@ class Position {
|
|||
|
||||
//print("[movesSinceLastRemove] posAfterLastRemove = $posAfterLastRemove");
|
||||
|
||||
for (int i = posAfterLastRemove; i < recorder.movesCount; i++) {
|
||||
moves += " ${recorder.moveAt(i).move}";
|
||||
for (int i = posAfterLastRemove; i < recorder!.movesCount; i++) {
|
||||
moves += " ${recorder!.moveAt(i).move}";
|
||||
}
|
||||
|
||||
//print("moves = $moves");
|
||||
|
@ -1576,7 +1576,7 @@ class Position {
|
|||
return moves.length > 0 ? moves.substring(1) : '';
|
||||
}
|
||||
|
||||
get manualText => recorder.buildManualText();
|
||||
get manualText => recorder!.buildManualText();
|
||||
|
||||
get side => _sideToMove;
|
||||
|
||||
|
@ -1586,11 +1586,11 @@ class Position {
|
|||
print("$_sideToMove to move.");
|
||||
}
|
||||
|
||||
get halfMove => recorder.halfMove;
|
||||
get halfMove => recorder!.halfMove;
|
||||
|
||||
get fullMove => recorder.fullMove;
|
||||
get fullMove => recorder!.fullMove;
|
||||
|
||||
get lastMove => recorder.last;
|
||||
get lastMove => recorder!.last;
|
||||
|
||||
get lastPositionWithRemove => recorder.lastPositionWithRemove;
|
||||
get lastPositionWithRemove => recorder!.lastPositionWithRemove;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import 'position.dart';
|
|||
import 'types.dart';
|
||||
|
||||
class GameRecorder {
|
||||
int halfMove, fullMove;
|
||||
String lastPositionWithRemove = "";
|
||||
int? halfMove, fullMove;
|
||||
String? lastPositionWithRemove = "";
|
||||
final _history = <Move>[];
|
||||
|
||||
GameRecorder(
|
||||
|
@ -47,13 +47,13 @@ class GameRecorder {
|
|||
if (move.type == MoveType.remove) {
|
||||
halfMove = 0;
|
||||
} else {
|
||||
if (halfMove != null) halfMove = halfMove + 1;
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
}
|
||||
|
||||
if (fullMove == 0) {
|
||||
if (halfMove != null) halfMove = halfMove + 1;
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
} else if (position.side != PieceColor.black) {
|
||||
if (halfMove != null) halfMove = halfMove + 1;
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
}
|
||||
|
||||
if (_history.length > 0) {
|
||||
|
@ -71,7 +71,7 @@ class GameRecorder {
|
|||
}
|
||||
}
|
||||
|
||||
Move removeLast() {
|
||||
Move? removeLast() {
|
||||
if (_history.isEmpty) return null;
|
||||
return _history.removeLast();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import 'package:sanmill/widgets/board.dart';
|
|||
import 'painter_base.dart';
|
||||
|
||||
class BoardPainter extends PiecesBasePainter {
|
||||
BoardPainter({@required double width}) : super(width: width);
|
||||
BoardPainter({required double width}) : super(width: width);
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
|
@ -51,8 +51,8 @@ class BoardPainter extends PiecesBasePainter {
|
|||
Paint paint,
|
||||
double gridWidth,
|
||||
double squareWidth, {
|
||||
double offsetX,
|
||||
double offsetY,
|
||||
required double offsetX,
|
||||
required double offsetY,
|
||||
}) {
|
||||
paint.color = Color(Config.boardLineColor);
|
||||
paint.style = PaintingStyle.stroke;
|
||||
|
|
|
@ -26,7 +26,7 @@ abstract class PiecesBasePainter extends CustomPainter {
|
|||
final gridWidth;
|
||||
final squareWidth;
|
||||
|
||||
PiecesBasePainter({@required this.width})
|
||||
PiecesBasePainter({required this.width})
|
||||
: gridWidth = (width - Board.padding * 2),
|
||||
squareWidth = (width - Board.padding * 2) / 7;
|
||||
}
|
||||
|
|
|
@ -27,21 +27,21 @@ import 'painter_base.dart';
|
|||
|
||||
class PiecePaintPair {
|
||||
// TODO: null-safety
|
||||
final String piece;
|
||||
final Offset pos;
|
||||
final String? piece;
|
||||
final Offset? pos;
|
||||
PiecePaintPair({this.piece, this.pos});
|
||||
}
|
||||
|
||||
class PiecesPainter extends PiecesBasePainter {
|
||||
final Position position;
|
||||
final int focusIndex, blurIndex;
|
||||
final Position? position;
|
||||
final int? focusIndex, blurIndex;
|
||||
|
||||
// TODO: null-safety
|
||||
double pieceWidth = 0.0;
|
||||
double? pieceWidth = 0.0;
|
||||
|
||||
PiecesPainter({
|
||||
@required double width,
|
||||
@required this.position,
|
||||
required double width,
|
||||
required this.position,
|
||||
this.focusIndex = Move.invalidMove,
|
||||
this.blurIndex = Move.invalidMove,
|
||||
}) : super(width: width) {
|
||||
|
@ -73,14 +73,14 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
static doPaint(
|
||||
Canvas canvas,
|
||||
Paint paint, {
|
||||
Position position,
|
||||
double gridWidth,
|
||||
double squareWidth,
|
||||
double pieceWidth,
|
||||
double offsetX,
|
||||
double offsetY,
|
||||
int focusIndex = Move.invalidMove,
|
||||
int blurIndex = Move.invalidMove,
|
||||
Position? position,
|
||||
double? gridWidth,
|
||||
double? squareWidth,
|
||||
double? pieceWidth,
|
||||
double? offsetX,
|
||||
double? offsetY,
|
||||
int? focusIndex = Move.invalidMove,
|
||||
int? blurIndex = Move.invalidMove,
|
||||
}) {
|
||||
//
|
||||
final left = offsetX;
|
||||
|
@ -90,7 +90,7 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
final piecesToDraw = <PiecePaintPair>[];
|
||||
|
||||
// TODO: null-safety
|
||||
Color blurPositionColor;
|
||||
Color? blurPositionColor;
|
||||
Color focusPositionColor;
|
||||
|
||||
// Draw pieces on board
|
||||
|
@ -98,16 +98,16 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
for (var col = 0; col < 7; col++) {
|
||||
//
|
||||
final piece =
|
||||
position.pieceOnGrid(row * 7 + col); // No Pieces when initial
|
||||
position!.pieceOnGrid(row * 7 + col); // No Pieces when initial
|
||||
|
||||
if (piece == Piece.noPiece) continue;
|
||||
|
||||
var pos = Offset(left + squareWidth * col, top + squareWidth * row);
|
||||
var pos = Offset(left! + squareWidth! * col, top! + squareWidth * row);
|
||||
|
||||
piecesToDraw.add(PiecePaintPair(piece: piece, pos: pos));
|
||||
|
||||
shadowPath.addOval(
|
||||
Rect.fromCenter(center: pos, width: pieceWidth, height: pieceWidth),
|
||||
Rect.fromCenter(center: pos, width: pieceWidth!, height: pieceWidth),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -126,23 +126,23 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
*/
|
||||
|
||||
piecesToDraw.forEach((pps) {
|
||||
var pieceRadius = pieceWidth / 2;
|
||||
var pieceRadius = pieceWidth! / 2;
|
||||
var pieceInnerRadius = pieceRadius * 0.99;
|
||||
|
||||
// Draw Border of Piece
|
||||
switch (pps.piece) {
|
||||
case Piece.blackStone:
|
||||
paint.color = UIColors.blackPieceBorderColor;
|
||||
canvas.drawCircle(pps.pos, pieceRadius, paint); // For debugging
|
||||
canvas.drawCircle(pps.pos!, pieceRadius, paint); // For debugging
|
||||
paint.color = Color(Config.blackPieceColor);
|
||||
canvas.drawCircle(pps.pos, pieceInnerRadius, paint);
|
||||
canvas.drawCircle(pps.pos!, pieceInnerRadius, paint);
|
||||
blurPositionColor = Color(Config.blackPieceColor).withOpacity(0.1);
|
||||
break;
|
||||
case Piece.whiteStone:
|
||||
paint.color = UIColors.whitePieceBorderColor;
|
||||
canvas.drawCircle(pps.pos, pieceRadius, paint); // For debugging
|
||||
canvas.drawCircle(pps.pos!, pieceRadius, paint); // For debugging
|
||||
paint.color = Color(Config.whitePieceColor);
|
||||
canvas.drawCircle(pps.pos, pieceInnerRadius, paint);
|
||||
canvas.drawCircle(pps.pos!, pieceInnerRadius, paint);
|
||||
blurPositionColor = Color(Config.whitePieceColor).withOpacity(0.1);
|
||||
break;
|
||||
case Piece.ban:
|
||||
|
@ -157,7 +157,7 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
// draw focus and blur position
|
||||
|
||||
if (focusIndex != Move.invalidMove) {
|
||||
final int row = focusIndex ~/ 7, column = focusIndex % 7;
|
||||
final int row = focusIndex! ~/ 7, column = focusIndex % 7;
|
||||
|
||||
focusPositionColor = Color.fromARGB(
|
||||
(Color(Config.blackPieceColor).alpha +
|
||||
|
@ -179,21 +179,21 @@ class PiecesPainter extends PiecesBasePainter {
|
|||
paint.strokeWidth = 2;
|
||||
|
||||
canvas.drawCircle(
|
||||
Offset(left + column * squareWidth, top + row * squareWidth),
|
||||
pieceWidth / 2,
|
||||
Offset(left! + column * squareWidth!, top! + row * squareWidth),
|
||||
pieceWidth! / 2,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
||||
if (blurIndex != Move.invalidMove) {
|
||||
final row = blurIndex ~/ 7, column = blurIndex % 7;
|
||||
final row = blurIndex! ~/ 7, column = blurIndex % 7;
|
||||
|
||||
paint.color = blurPositionColor;
|
||||
paint.color = blurPositionColor!;
|
||||
paint.style = PaintingStyle.fill;
|
||||
|
||||
canvas.drawCircle(
|
||||
Offset(left + column * squareWidth, top + row * squareWidth),
|
||||
pieceWidth / 2 * 0.8,
|
||||
Offset(left! + column * squareWidth!, top! + row * squareWidth),
|
||||
pieceWidth! / 2 * 0.8,
|
||||
paint,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import 'package:sanmill/common/config.dart';
|
|||
|
||||
class Audios {
|
||||
//
|
||||
static AudioPlayer _player;
|
||||
static AudioPlayer? _player;
|
||||
|
||||
static playTone(String fileName) async {
|
||||
if (!Config.toneEnabled) {
|
||||
|
@ -41,9 +41,9 @@ class Audios {
|
|||
_player = AudioPlayer();
|
||||
}
|
||||
|
||||
await _player.stop();
|
||||
await _player.setAsset("assets/audios/" + fileName);
|
||||
_player.play();
|
||||
await _player!.stop();
|
||||
await _player!.setAsset("assets/audios/" + fileName);
|
||||
_player!.play();
|
||||
} on PlayerException catch (e) {
|
||||
// iOS/macOS: maps to NSError.code
|
||||
// Android: maps to ExoPlayerException.type
|
||||
|
@ -66,8 +66,8 @@ class Audios {
|
|||
|
||||
static Future<void> release() async {
|
||||
if (_player != null) {
|
||||
await _player.stop();
|
||||
await _player.dispose();
|
||||
await _player!.stop();
|
||||
await _player!.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class Board extends StatelessWidget {
|
|||
final double height;
|
||||
final Function(BuildContext, int) onBoardTap;
|
||||
|
||||
Board({@required this.width, @required this.onBoardTap}) : height = width;
|
||||
Board({required this.width, required this.onBoardTap}) : height = width;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:sanmill/widgets/home_drawer.dart';
|
|||
|
||||
class DrawerUserController extends StatefulWidget {
|
||||
const DrawerUserController({
|
||||
Key key,
|
||||
Key? key,
|
||||
this.drawerWidth = 250,
|
||||
this.onDrawerCall,
|
||||
this.screenView,
|
||||
|
@ -15,12 +15,12 @@ class DrawerUserController extends StatefulWidget {
|
|||
}) : super(key: key);
|
||||
|
||||
final double drawerWidth;
|
||||
final Function(DrawerIndex) onDrawerCall;
|
||||
final Widget screenView;
|
||||
final Function(bool) drawerIsOpen;
|
||||
final Function(DrawerIndex)? onDrawerCall;
|
||||
final Widget? screenView;
|
||||
final Function(bool)? drawerIsOpen;
|
||||
final AnimatedIconData animatedIconData;
|
||||
final Widget menuView;
|
||||
final DrawerIndex screenIndex;
|
||||
final Widget? menuView;
|
||||
final DrawerIndex? screenIndex;
|
||||
|
||||
@override
|
||||
_DrawerUserControllerState createState() => _DrawerUserControllerState();
|
||||
|
@ -28,9 +28,9 @@ class DrawerUserController extends StatefulWidget {
|
|||
|
||||
class _DrawerUserControllerState extends State<DrawerUserController>
|
||||
with TickerProviderStateMixin {
|
||||
ScrollController scrollController;
|
||||
AnimationController iconAnimationController;
|
||||
AnimationController animationController;
|
||||
ScrollController? scrollController;
|
||||
AnimationController? iconAnimationController;
|
||||
AnimationController? animationController;
|
||||
|
||||
double scrolloffset = 0.0;
|
||||
|
||||
|
@ -48,22 +48,22 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
ScrollController(initialScrollOffset: widget.drawerWidth);
|
||||
scrollController
|
||||
..addListener(() {
|
||||
if (scrollController.offset <= 0) {
|
||||
if (scrollController!.offset <= 0) {
|
||||
if (scrolloffset != 1.0) {
|
||||
setState(() {
|
||||
scrolloffset = 1.0;
|
||||
try {
|
||||
widget.drawerIsOpen(true);
|
||||
widget.drawerIsOpen!(true);
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
iconAnimationController.animateTo(0.0,
|
||||
iconAnimationController!.animateTo(0.0,
|
||||
duration: const Duration(milliseconds: 0),
|
||||
curve: Curves.fastOutSlowIn);
|
||||
} else if (scrollController.offset > 0 &&
|
||||
scrollController.offset < widget.drawerWidth.floor()) {
|
||||
iconAnimationController.animateTo(
|
||||
(scrollController.offset * 100 / (widget.drawerWidth)) / 100,
|
||||
} else if (scrollController!.offset > 0 &&
|
||||
scrollController!.offset < widget.drawerWidth.floor()) {
|
||||
iconAnimationController!.animateTo(
|
||||
(scrollController!.offset * 100 / (widget.drawerWidth)) / 100,
|
||||
duration: const Duration(milliseconds: 0),
|
||||
curve: Curves.fastOutSlowIn);
|
||||
} else {
|
||||
|
@ -71,21 +71,21 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
setState(() {
|
||||
scrolloffset = 0.0;
|
||||
try {
|
||||
widget.drawerIsOpen(false);
|
||||
widget.drawerIsOpen!(false);
|
||||
} catch (_) {}
|
||||
});
|
||||
}
|
||||
iconAnimationController.animateTo(1.0,
|
||||
iconAnimationController!.animateTo(1.0,
|
||||
duration: const Duration(milliseconds: 0),
|
||||
curve: Curves.fastOutSlowIn);
|
||||
}
|
||||
});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => getInitState());
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) => getInitState());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Future<bool> getInitState() async {
|
||||
scrollController.jumpTo(
|
||||
scrollController!.jumpTo(
|
||||
widget.drawerWidth,
|
||||
);
|
||||
return true;
|
||||
|
@ -110,12 +110,12 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
//we divided first drawer Width with HomeDrawer and second full-screen Width with all home screen, we called screen View
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: AnimatedBuilder(
|
||||
animation: iconAnimationController,
|
||||
builder: (BuildContext context, Widget child) {
|
||||
animation: iconAnimationController!,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return Transform(
|
||||
//transform we use for the stable drawer we, not need to move with scroll view
|
||||
transform: Matrix4.translationValues(
|
||||
scrollController.offset, 0.0, 0.0),
|
||||
scrollController!.offset, 0.0, 0.0),
|
||||
child: HomeDrawer(
|
||||
screenIndex: widget.screenIndex == null
|
||||
? DrawerIndex.humanVsAi
|
||||
|
@ -124,7 +124,7 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
callBackIndex: (DrawerIndex indexType) {
|
||||
onDrawerClick();
|
||||
try {
|
||||
widget.onDrawerCall(indexType);
|
||||
widget.onDrawerCall!(indexType);
|
||||
} catch (e) {}
|
||||
},
|
||||
),
|
||||
|
@ -179,7 +179,7 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
: AnimatedIcon(
|
||||
icon: widget.animatedIconData,
|
||||
color: Colors.white,
|
||||
progress: iconAnimationController),
|
||||
progress: iconAnimationController!),
|
||||
),
|
||||
onTap: () {
|
||||
FocusScope.of(context)
|
||||
|
@ -203,14 +203,14 @@ class _DrawerUserControllerState extends State<DrawerUserController>
|
|||
|
||||
void onDrawerClick() {
|
||||
//if scrollcontroller.offset != 0.0 then we set to closed the drawer(with animation to offset zero position) if is not 1 then open the drawer
|
||||
if (scrollController.offset != 0.0) {
|
||||
scrollController.animateTo(
|
||||
if (scrollController!.offset != 0.0) {
|
||||
scrollController!.animateTo(
|
||||
0.0,
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
);
|
||||
} else {
|
||||
scrollController.animateTo(
|
||||
scrollController!.animateTo(
|
||||
widget.drawerWidth,
|
||||
duration: const Duration(milliseconds: 400),
|
||||
curve: Curves.fastOutSlowIn,
|
||||
|
|
|
@ -47,7 +47,7 @@ class GamePage extends StatefulWidget {
|
|||
|
||||
class _GamePageState extends State<GamePage> with RouteAware {
|
||||
// TODO: null-safety
|
||||
String _status = '';
|
||||
String? _status = '';
|
||||
bool _searching = false;
|
||||
|
||||
@override
|
||||
|
@ -61,7 +61,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
widget.engine.startup();
|
||||
}
|
||||
|
||||
changeStatus(String status) {
|
||||
changeStatus(String? status) {
|
||||
setState(() => _status = status);
|
||||
}
|
||||
|
||||
|
@ -74,16 +74,16 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
final winner = Game.shared.position.winner;
|
||||
|
||||
Map<String, String> colorWinStrings = {
|
||||
PieceColor.black: S.of(context).blackWin,
|
||||
PieceColor.white: S.of(context).whiteWin,
|
||||
PieceColor.draw: S.of(context).draw
|
||||
PieceColor.black: S.of(context)!.blackWin,
|
||||
PieceColor.white: S.of(context)!.whiteWin,
|
||||
PieceColor.draw: S.of(context)!.draw
|
||||
};
|
||||
|
||||
if (winner == PieceColor.nobody) {
|
||||
if (Game.shared.position.phase == Phase.placing) {
|
||||
changeStatus(S.of(context).tipPlace);
|
||||
changeStatus(S.of(context)!.tipPlace);
|
||||
} else if (Game.shared.position.phase == Phase.moving) {
|
||||
changeStatus(S.of(context).tipMove);
|
||||
changeStatus(S.of(context)!.tipMove);
|
||||
}
|
||||
} else {
|
||||
changeStatus(colorWinStrings[winner]);
|
||||
|
@ -99,7 +99,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
|
||||
final position = Game.shared.position;
|
||||
|
||||
int sq = indexToSquare[index];
|
||||
int? sq = indexToSquare[index];
|
||||
|
||||
if (sq == null) {
|
||||
//print("putPiece skip index: $index");
|
||||
|
@ -121,17 +121,17 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
if (position.putPiece(sq)) {
|
||||
if (position.action == Act.remove) {
|
||||
//Audios.playTone('mill.mp3');
|
||||
changeStatus(S.of(context).tipRemove);
|
||||
changeStatus(S.of(context)!.tipRemove);
|
||||
} else {
|
||||
//Audios.playTone('place.mp3');
|
||||
changeStatus(S.of(context).tipPlaced);
|
||||
changeStatus(S.of(context)!.tipPlaced);
|
||||
}
|
||||
ret = true;
|
||||
print("putPiece: [$sq]");
|
||||
break;
|
||||
} else {
|
||||
print("putPiece: skip [$sq]");
|
||||
changeStatus(S.of(context).tipBanPlace);
|
||||
changeStatus(S.of(context)!.tipBanPlace);
|
||||
}
|
||||
|
||||
// If cannot move, retry select, do not break
|
||||
|
@ -144,11 +144,11 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
Game.shared.select(index);
|
||||
ret = true;
|
||||
print("selectPiece: [$sq]");
|
||||
changeStatus(S.of(context).tipPlace);
|
||||
changeStatus(S.of(context)!.tipPlace);
|
||||
} else {
|
||||
Audios.playTone('illegal.mp3');
|
||||
print("selectPiece: skip [$sq]");
|
||||
changeStatus(S.of(context).tipSelectWrong);
|
||||
changeStatus(S.of(context)!.tipSelectWrong);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -157,11 +157,11 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
//Audios.playTone('remove.mp3');
|
||||
ret = true;
|
||||
print("removePiece: [$sq]");
|
||||
changeStatus(S.of(context).tipRemoved);
|
||||
changeStatus(S.of(context)!.tipRemoved);
|
||||
} else {
|
||||
Audios.playTone('illegal.mp3');
|
||||
print("removePiece: skip [$sq]");
|
||||
changeStatus(S.of(context).tipBanRemove);
|
||||
changeStatus(S.of(context)!.tipBanRemove);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -218,7 +218,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
|
||||
changeStatus(score);
|
||||
} else {
|
||||
changeStatus(S.of(context).thinking);
|
||||
changeStatus(S.of(context)!.thinking);
|
||||
}
|
||||
|
||||
final response = await widget.engine.search(Game.shared.position);
|
||||
|
@ -246,7 +246,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
confirm() {
|
||||
Navigator.of(context).pop();
|
||||
Game.shared.newGame();
|
||||
changeStatus(S.of(context).gameStarted);
|
||||
changeStatus(S.of(context)!.gameStarted);
|
||||
|
||||
if (Game.shared.isAiToMove()) {
|
||||
print("New game, AI to move.");
|
||||
|
@ -260,53 +260,53 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(S.of(context).newGame,
|
||||
title: Text(S.of(context)!.newGame,
|
||||
style: TextStyle(color: UIColors.primaryColor)),
|
||||
content:
|
||||
SingleChildScrollView(child: Text(S.of(context).restartGame)),
|
||||
SingleChildScrollView(child: Text(S.of(context)!.restartGame)),
|
||||
actions: <Widget>[
|
||||
TextButton(child: Text(S.of(context).restart), onPressed: confirm),
|
||||
TextButton(child: Text(S.of(context).cancel), onPressed: cancel),
|
||||
TextButton(child: Text(S.of(context)!.restart), onPressed: confirm),
|
||||
TextButton(child: Text(S.of(context)!.cancel), onPressed: cancel),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
String getGameOverReasonString(GameOverReason reason, String winner) {
|
||||
String getGameOverReasonString(GameOverReason? reason, String? winner) {
|
||||
String loseReasonStr;
|
||||
//String winnerStr =
|
||||
// winner == Color.black ? S.of(context).black : S.of(context).white;
|
||||
String loserStr =
|
||||
winner == PieceColor.black ? S.of(context).white : S.of(context).black;
|
||||
winner == PieceColor.black ? S.of(context)!.white : S.of(context)!.black;
|
||||
|
||||
switch (Game.shared.position.gameOverReason) {
|
||||
case GameOverReason.loseReasonlessThanThree:
|
||||
loseReasonStr = loserStr + S.of(context).loseReasonlessThanThree;
|
||||
loseReasonStr = loserStr + S.of(context)!.loseReasonlessThanThree;
|
||||
break;
|
||||
case GameOverReason.loseReasonResign:
|
||||
loseReasonStr = loserStr + S.of(context).loseReasonResign;
|
||||
loseReasonStr = loserStr + S.of(context)!.loseReasonResign;
|
||||
break;
|
||||
case GameOverReason.loseReasonNoWay:
|
||||
loseReasonStr = loserStr + S.of(context).loseReasonNoWay;
|
||||
loseReasonStr = loserStr + S.of(context)!.loseReasonNoWay;
|
||||
break;
|
||||
case GameOverReason.loseReasonBoardIsFull:
|
||||
loseReasonStr = loserStr + S.of(context).loseReasonBoardIsFull;
|
||||
loseReasonStr = loserStr + S.of(context)!.loseReasonBoardIsFull;
|
||||
break;
|
||||
case GameOverReason.loseReasonTimeOver:
|
||||
loseReasonStr = loserStr + S.of(context).loseReasonTimeOver;
|
||||
loseReasonStr = loserStr + S.of(context)!.loseReasonTimeOver;
|
||||
break;
|
||||
case GameOverReason.drawReasonRule50:
|
||||
loseReasonStr = S.of(context).drawReasonRule50;
|
||||
loseReasonStr = S.of(context)!.drawReasonRule50;
|
||||
break;
|
||||
case GameOverReason.drawReasonBoardIsFull:
|
||||
loseReasonStr = S.of(context).drawReasonBoardIsFull;
|
||||
loseReasonStr = S.of(context)!.drawReasonBoardIsFull;
|
||||
break;
|
||||
case GameOverReason.drawReasonThreefoldRepetition:
|
||||
loseReasonStr = S.of(context).drawReasonThreefoldRepetition;
|
||||
loseReasonStr = S.of(context)!.drawReasonThreefoldRepetition;
|
||||
break;
|
||||
default:
|
||||
loseReasonStr = S.of(context).gameOverUnknownReason;
|
||||
loseReasonStr = S.of(context)!.gameOverUnknownReason;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -314,12 +314,12 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
}
|
||||
|
||||
GameResult getGameResult(var winner) {
|
||||
if (isAi[PieceColor.black] && isAi[PieceColor.white]) {
|
||||
if (isAi[PieceColor.black]! && isAi[PieceColor.white]!) {
|
||||
return GameResult.none;
|
||||
}
|
||||
|
||||
if (winner == PieceColor.black) {
|
||||
if (isAi[PieceColor.black]) {
|
||||
if (isAi[PieceColor.black]!) {
|
||||
return GameResult.lose;
|
||||
} else {
|
||||
return GameResult.win;
|
||||
|
@ -327,7 +327,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
}
|
||||
|
||||
if (winner == PieceColor.white) {
|
||||
if (isAi[PieceColor.white]) {
|
||||
if (isAi[PieceColor.white]!) {
|
||||
return GameResult.lose;
|
||||
} else {
|
||||
return GameResult.win;
|
||||
|
@ -359,9 +359,9 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
}
|
||||
|
||||
Map<GameResult, String> retMap = {
|
||||
GameResult.win: S.of(context).youWin,
|
||||
GameResult.lose: S.of(context).youLose,
|
||||
GameResult.draw: S.of(context).draw
|
||||
GameResult.win: S.of(context)!.youWin,
|
||||
GameResult.lose: S.of(context)!.youLose,
|
||||
GameResult.draw: S.of(context)!.draw
|
||||
};
|
||||
|
||||
var dialogTitle = retMap[result];
|
||||
|
@ -381,17 +381,17 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
content: Text(getGameOverReasonString(
|
||||
Game.shared.position.gameOverReason,
|
||||
Game.shared.position.winner) +
|
||||
S.of(context).challengeHarderLevel),
|
||||
S.of(context)!.challengeHarderLevel),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).yes),
|
||||
child: Text(S.of(context)!.yes),
|
||||
onPressed: () {
|
||||
Config.skillLevel++;
|
||||
Config.save();
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
TextButton(
|
||||
child: Text(S.of(context).no),
|
||||
child: Text(S.of(context)!.no),
|
||||
onPressed: () => Navigator.of(context).pop()),
|
||||
],
|
||||
);
|
||||
|
@ -410,7 +410,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
Game.shared.position.winner)),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
child: Text(S.of(context)!.ok),
|
||||
onPressed: () => Navigator.of(context).pop()),
|
||||
],
|
||||
);
|
||||
|
@ -434,12 +434,12 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
|
||||
Widget createPageHeader() {
|
||||
Map<EngineType, String> engineTypeToString = {
|
||||
EngineType.humanVsAi: S.of(context).humanVsAi,
|
||||
EngineType.humanVsHuman: S.of(context).humanVsHuman,
|
||||
EngineType.aiVsAi: S.of(context).aiVsAi,
|
||||
EngineType.humanVsCloud: S.of(context).humanVsCloud,
|
||||
EngineType.humanVsLAN: S.of(context).humanVsLAN,
|
||||
EngineType.testViaLAN: S.of(context).testViaLAN,
|
||||
EngineType.humanVsAi: S.of(context)!.humanVsAi,
|
||||
EngineType.humanVsHuman: S.of(context)!.humanVsHuman,
|
||||
EngineType.aiVsAi: S.of(context)!.aiVsAi,
|
||||
EngineType.humanVsCloud: S.of(context)!.humanVsCloud,
|
||||
EngineType.humanVsLAN: S.of(context)!.humanVsLAN,
|
||||
EngineType.testViaLAN: S.of(context)!.testViaLAN,
|
||||
};
|
||||
|
||||
Map<EngineType, IconData> engineTypeToIconLeft = {
|
||||
|
@ -535,7 +535,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(_status, maxLines: 1, style: subTitleStyle),
|
||||
child: Text(_status!, maxLines: 1, style: subTitleStyle),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -621,21 +621,21 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(S.of(context).gameRecord,
|
||||
title: Text(S.of(context)!.gameRecord,
|
||||
style: TextStyle(color: Colors.yellow)),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(manualText, style: manualStyle)),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).copy, style: manualStyle),
|
||||
child: Text(S.of(context)!.copy, style: manualStyle),
|
||||
onPressed: () =>
|
||||
Clipboard.setData(ClipboardData(text: manualText))
|
||||
.then((_) {
|
||||
showSnackBar(S.of(context).moveHistoryCopied);
|
||||
showSnackBar(S.of(context)!.moveHistoryCopied);
|
||||
}),
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel, style: manualStyle),
|
||||
child: Text(S.of(context)!.cancel, style: manualStyle),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
|
@ -652,13 +652,13 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
title: Text(S.of(context).analyze,
|
||||
title: Text(S.of(context)!.analyze,
|
||||
style: TextStyle(color: Colors.yellow)),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(analyzeText, style: manualStyle)),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok, style: manualStyle),
|
||||
child: Text(S.of(context)!.ok, style: manualStyle),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
|
@ -717,28 +717,28 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
|
||||
@override
|
||||
void didPush() {
|
||||
final route = ModalRoute.of(context).settings.name;
|
||||
final route = ModalRoute.of(context)!.settings.name;
|
||||
print('Game Page didPush route: $route');
|
||||
widget.engine.setOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
void didPopNext() {
|
||||
final route = ModalRoute.of(context).settings.name;
|
||||
final route = ModalRoute.of(context)!.settings.name;
|
||||
print('Game Page didPopNext route: $route');
|
||||
widget.engine.setOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
void didPushNext() {
|
||||
final route = ModalRoute.of(context).settings.name;
|
||||
final route = ModalRoute.of(context)!.settings.name;
|
||||
print('Game Page didPushNext route: $route');
|
||||
widget.engine.setOptions();
|
||||
}
|
||||
|
||||
@override
|
||||
void didPop() {
|
||||
final route = ModalRoute.of(context).settings.name;
|
||||
final route = ModalRoute.of(context)!.settings.name;
|
||||
print('Game Page didPop route: $route');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
|
||||
showBoardColorDialog() async {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(S.of(context).pick + S.of(context).boardColor),
|
||||
title: Text(S.of(context)!.pick + S.of(context)!.boardColor),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: Color(Config.boardBackgroundColor),
|
||||
|
@ -58,7 +58,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).confirm),
|
||||
child: Text(S.of(context)!.confirm),
|
||||
onPressed: () {
|
||||
setState(() => currentColor = pickerColor);
|
||||
Config.boardBackgroundColor = pickerColor.value;
|
||||
|
@ -67,7 +67,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel),
|
||||
child: Text(S.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -86,7 +86,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
|
||||
showBackgroundColorDialog() async {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(S.of(context).pick + S.of(context).backgroudColor),
|
||||
title: Text(S.of(context)!.pick + S.of(context)!.backgroudColor),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: Color(Config.darkBackgroundColor),
|
||||
|
@ -97,7 +97,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).confirm),
|
||||
child: Text(S.of(context)!.confirm),
|
||||
onPressed: () {
|
||||
setState(() => currentColor = pickerColor);
|
||||
Config.darkBackgroundColor = pickerColor.value;
|
||||
|
@ -106,7 +106,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel),
|
||||
child: Text(S.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -125,7 +125,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
|
||||
showBoardLineColorDialog() async {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(S.of(context).pick + S.of(context).lineColor),
|
||||
title: Text(S.of(context)!.pick + S.of(context)!.lineColor),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: Color(Config.boardLineColor),
|
||||
|
@ -136,7 +136,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).confirm),
|
||||
child: Text(S.of(context)!.confirm),
|
||||
onPressed: () {
|
||||
setState(() => currentColor = pickerColor);
|
||||
Config.boardLineColor = pickerColor.value;
|
||||
|
@ -145,7 +145,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel),
|
||||
child: Text(S.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -164,7 +164,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
|
||||
showBlackPieceColorDialog() async {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(S.of(context).pick + S.of(context).blackPieceColor),
|
||||
title: Text(S.of(context)!.pick + S.of(context)!.blackPieceColor),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: Color(Config.blackPieceColor),
|
||||
|
@ -175,7 +175,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).confirm),
|
||||
child: Text(S.of(context)!.confirm),
|
||||
onPressed: () {
|
||||
setState(() => currentColor = pickerColor);
|
||||
Config.blackPieceColor = pickerColor.value;
|
||||
|
@ -184,7 +184,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel),
|
||||
child: Text(S.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -203,7 +203,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
|
||||
showWhitePieceColorDialog() async {
|
||||
AlertDialog alert = AlertDialog(
|
||||
title: Text(S.of(context).pick + S.of(context).whitePieceColor),
|
||||
title: Text(S.of(context)!.pick + S.of(context)!.whitePieceColor),
|
||||
content: SingleChildScrollView(
|
||||
child: ColorPicker(
|
||||
pickerColor: Color(Config.whitePieceColor),
|
||||
|
@ -214,7 +214,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).confirm),
|
||||
child: Text(S.of(context)!.confirm),
|
||||
onPressed: () {
|
||||
setState(() => currentColor = pickerColor);
|
||||
Config.whitePieceColor = pickerColor.value;
|
||||
|
@ -223,7 +223,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
},
|
||||
),
|
||||
TextButton(
|
||||
child: Text(S.of(context).cancel),
|
||||
child: Text(S.of(context)!.cancel),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
|
@ -505,16 +505,16 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(S.of(context).restore,
|
||||
title: Text(S.of(context)!.restore,
|
||||
style: TextStyle(color: UIColors.primaryColor)),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(S.of(context).restoreDefaultSettings +
|
||||
child: Text(S.of(context)!.restoreDefaultSettings +
|
||||
"?\n" +
|
||||
S.of(context).exitApp),
|
||||
S.of(context)!.exitApp),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(child: Text(S.of(context).ok), onPressed: confirm),
|
||||
TextButton(child: Text(S.of(context).cancel), onPressed: cancel),
|
||||
TextButton(child: Text(S.of(context)!.ok), onPressed: confirm),
|
||||
TextButton(child: Text(S.of(context)!.cancel), onPressed: cancel),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -532,7 +532,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
backgroundColor: UIColors.lightBackgroundColor,
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
title: Text(S.of(context).settings),
|
||||
title: Text(S.of(context)!.settings),
|
||||
backgroundColor: UIColors.primaryColor),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
|
@ -540,7 +540,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const SizedBox(height: 10.0),
|
||||
Text(S.of(context).skillLevel, style: headerStyle),
|
||||
Text(S.of(context)!.skillLevel, style: headerStyle),
|
||||
const SizedBox(height: 10.0),
|
||||
Card(
|
||||
color: cardColor,
|
||||
|
@ -549,7 +549,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
child: Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(S.of(context).skillLevel, style: itemStyle),
|
||||
title: Text(S.of(context)!.skillLevel, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(""), // TODO
|
||||
|
@ -561,14 +561,14 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.aiIsLazy,
|
||||
title: Text(S.of(context).aiIsLazy, style: itemStyle),
|
||||
title: Text(S.of(context)!.aiIsLazy, style: itemStyle),
|
||||
onChanged: setAiIsLazy,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).sound, style: headerStyle),
|
||||
Text(S.of(context)!.sound, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
|
@ -577,14 +577,14 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.toneEnabled,
|
||||
title: Text(S.of(context).tone, style: itemStyle),
|
||||
title: Text(S.of(context)!.tone, style: itemStyle),
|
||||
onChanged: setTone,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).whoMovesFirst, style: headerStyle),
|
||||
Text(S.of(context)!.whoMovesFirst, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
|
@ -595,8 +595,8 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
value: !Config.aiMovesFirst,
|
||||
title: Text(
|
||||
Config.aiMovesFirst
|
||||
? S.of(context).ai
|
||||
: S.of(context).human,
|
||||
? S.of(context)!.ai
|
||||
: S.of(context)!.human,
|
||||
style: itemStyle),
|
||||
onChanged: setWhoMovesFirst,
|
||||
),
|
||||
|
@ -604,7 +604,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).misc, style: headerStyle),
|
||||
Text(S.of(context)!.misc, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
|
@ -613,7 +613,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.isAutoRestart,
|
||||
title: Text(S.of(context).isAutoRestart, style: itemStyle),
|
||||
title: Text(S.of(context)!.isAutoRestart, style: itemStyle),
|
||||
onChanged: setIsAutoRestart,
|
||||
),
|
||||
_buildDivider(),
|
||||
|
@ -621,14 +621,14 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
activeColor: UIColors.primaryColor,
|
||||
value: Config.shufflingEnabled,
|
||||
title:
|
||||
Text(S.of(context).shufflingEnabled, style: itemStyle),
|
||||
Text(S.of(context)!.shufflingEnabled, style: itemStyle),
|
||||
onChanged: setShufflingEnabled,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).display, style: headerStyle),
|
||||
Text(S.of(context)!.display, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
|
@ -637,13 +637,13 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.isPieceCountInHandShown,
|
||||
title: Text(S.of(context).isPieceCountInHandShown,
|
||||
title: Text(S.of(context)!.isPieceCountInHandShown,
|
||||
style: itemStyle),
|
||||
onChanged: setIsPieceCountInHandShown,
|
||||
),
|
||||
_buildDivider(),
|
||||
ListTile(
|
||||
title: Text(S.of(context).boardBorderLineWidth,
|
||||
title: Text(S.of(context)!.boardBorderLineWidth,
|
||||
style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
|
@ -655,7 +655,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
_buildDivider(),
|
||||
ListTile(
|
||||
title: Text(S.of(context).boardInnerLineWidth,
|
||||
title: Text(S.of(context)!.boardInnerLineWidth,
|
||||
style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
|
@ -669,14 +669,14 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).color, style: headerStyle),
|
||||
Text(S.of(context)!.color, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(S.of(context).boardColor, style: itemStyle),
|
||||
title: Text(S.of(context)!.boardColor, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.boardBackgroundColor.toRadixString(16),
|
||||
|
@ -690,7 +690,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
_buildDivider(),
|
||||
ListTile(
|
||||
title: Text(S.of(context).backgroudColor, style: itemStyle),
|
||||
title: Text(S.of(context)!.backgroudColor, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.darkBackgroundColor.toRadixString(16),
|
||||
|
@ -704,7 +704,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
_buildDivider(),
|
||||
ListTile(
|
||||
title: Text(S.of(context).lineColor, style: itemStyle),
|
||||
title: Text(S.of(context)!.lineColor, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.boardLineColor.toRadixString(16),
|
||||
|
@ -718,7 +718,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
_buildDivider(),
|
||||
ListTile(
|
||||
title:
|
||||
Text(S.of(context).blackPieceColor, style: itemStyle),
|
||||
Text(S.of(context)!.blackPieceColor, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.blackPieceColor.toRadixString(16),
|
||||
|
@ -732,7 +732,7 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
_buildDivider(),
|
||||
ListTile(
|
||||
title:
|
||||
Text(S.of(context).whitePieceColor, style: itemStyle),
|
||||
Text(S.of(context)!.whitePieceColor, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.whitePieceColor.toRadixString(16),
|
||||
|
@ -747,14 +747,14 @@ class _GameSettingsPageState extends State<GameSettingsPage> {
|
|||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).restore, style: headerStyle),
|
||||
Text(S.of(context)!.restore, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(S.of(context).restoreDefaultSettings,
|
||||
title: Text(S.of(context)!.restoreDefaultSettings,
|
||||
style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
|
|
|
@ -6,22 +6,22 @@ import 'package:sanmill/style/app_theme.dart';
|
|||
|
||||
class HomeDrawer extends StatefulWidget {
|
||||
const HomeDrawer(
|
||||
{Key key,
|
||||
{Key? key,
|
||||
this.screenIndex,
|
||||
this.iconAnimationController,
|
||||
this.callBackIndex})
|
||||
: super(key: key);
|
||||
|
||||
final AnimationController iconAnimationController;
|
||||
final DrawerIndex screenIndex;
|
||||
final Function(DrawerIndex) callBackIndex;
|
||||
final AnimationController? iconAnimationController;
|
||||
final DrawerIndex? screenIndex;
|
||||
final Function(DrawerIndex?)? callBackIndex;
|
||||
|
||||
@override
|
||||
_HomeDrawerState createState() => _HomeDrawerState();
|
||||
}
|
||||
|
||||
class _HomeDrawerState extends State<HomeDrawer> {
|
||||
List<DrawerList> drawerList;
|
||||
late List<DrawerList> drawerList;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
@ -31,32 +31,32 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
drawerList = <DrawerList>[
|
||||
DrawerList(
|
||||
index: DrawerIndex.humanVsAi,
|
||||
labelName: S.of(context).humanVsAi,
|
||||
labelName: S.of(context)!.humanVsAi,
|
||||
icon: Icon(Icons.person),
|
||||
),
|
||||
DrawerList(
|
||||
index: DrawerIndex.humanVsHuman,
|
||||
labelName: S.of(context).humanVsHuman,
|
||||
labelName: S.of(context)!.humanVsHuman,
|
||||
icon: Icon(Icons.group),
|
||||
),
|
||||
DrawerList(
|
||||
index: DrawerIndex.aiVsAi,
|
||||
labelName: S.of(context).aiVsAi,
|
||||
labelName: S.of(context)!.aiVsAi,
|
||||
icon: Icon(Icons.computer),
|
||||
),
|
||||
DrawerList(
|
||||
index: DrawerIndex.settings,
|
||||
labelName: S.of(context).settings,
|
||||
labelName: S.of(context)!.settings,
|
||||
icon: Icon(Icons.settings),
|
||||
),
|
||||
DrawerList(
|
||||
index: DrawerIndex.ruleSettings,
|
||||
labelName: S.of(context).ruleSettings,
|
||||
labelName: S.of(context)!.ruleSettings,
|
||||
icon: Icon(Icons.rule),
|
||||
),
|
||||
DrawerList(
|
||||
index: DrawerIndex.Help,
|
||||
labelName: S.of(context).help,
|
||||
labelName: S.of(context)!.help,
|
||||
icon: Icon(Icons.help),
|
||||
),
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
*/
|
||||
DrawerList(
|
||||
index: DrawerIndex.About,
|
||||
labelName: S.of(context).about,
|
||||
labelName: S.of(context)!.about,
|
||||
icon: Icon(Icons.info),
|
||||
),
|
||||
];
|
||||
|
@ -104,16 +104,16 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AnimatedBuilder(
|
||||
animation: widget.iconAnimationController,
|
||||
builder: (BuildContext context, Widget child) {
|
||||
animation: widget.iconAnimationController!,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return ScaleTransition(
|
||||
scale: AlwaysStoppedAnimation<double>(
|
||||
1.0 - (widget.iconAnimationController.value) * 0.2),
|
||||
1.0 - (widget.iconAnimationController!.value) * 0.2),
|
||||
child: RotationTransition(
|
||||
turns: AlwaysStoppedAnimation<double>(Tween<double>(
|
||||
begin: 0.0, end: 24.0)
|
||||
.animate(CurvedAnimation(
|
||||
parent: widget.iconAnimationController,
|
||||
parent: widget.iconAnimationController!,
|
||||
curve: Curves.fastOutSlowIn))
|
||||
.value /
|
||||
360),
|
||||
|
@ -128,9 +128,9 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
print("ColorizeAnimatedTextKit Tap Event");
|
||||
},
|
||||
text: [
|
||||
S.of(context).appName,
|
||||
S.of(context).appName,
|
||||
S.of(context).appName,
|
||||
S.of(context)!.appName,
|
||||
S.of(context)!.appName,
|
||||
S.of(context)!.appName,
|
||||
],
|
||||
textStyle: TextStyle(
|
||||
fontSize: 24.0,
|
||||
|
@ -250,7 +250,7 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
? Colors.blue
|
||||
: AppTheme.nearlyBlack),
|
||||
)
|
||||
: Icon(listData.icon.icon,
|
||||
: Icon(listData.icon!.icon,
|
||||
color: widget.screenIndex == listData.index
|
||||
? Colors.blue
|
||||
: AppTheme.nearlyBlack),
|
||||
|
@ -273,13 +273,13 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
),
|
||||
widget.screenIndex == listData.index
|
||||
? AnimatedBuilder(
|
||||
animation: widget.iconAnimationController,
|
||||
builder: (BuildContext context, Widget child) {
|
||||
animation: widget.iconAnimationController!,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return Transform(
|
||||
transform: Matrix4.translationValues(
|
||||
(MediaQuery.of(context).size.width * 0.75 - 64) *
|
||||
(1.0 -
|
||||
widget.iconAnimationController.value -
|
||||
widget.iconAnimationController!.value -
|
||||
1.0),
|
||||
0.0,
|
||||
0.0),
|
||||
|
@ -310,8 +310,8 @@ class _HomeDrawerState extends State<HomeDrawer> {
|
|||
);
|
||||
}
|
||||
|
||||
Future<void> navigationToScreen(DrawerIndex indexScreen) async {
|
||||
widget.callBackIndex(indexScreen);
|
||||
Future<void> navigationToScreen(DrawerIndex? indexScreen) async {
|
||||
widget.callBackIndex!(indexScreen);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,8 +335,8 @@ class DrawerList {
|
|||
});
|
||||
|
||||
String labelName;
|
||||
Icon icon;
|
||||
Icon? icon;
|
||||
bool isAssetsImage;
|
||||
String imageName;
|
||||
DrawerIndex index;
|
||||
DrawerIndex? index;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ class NavigationHomeScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
||||
Widget screenView;
|
||||
DrawerIndex drawerIndex;
|
||||
Widget? screenView;
|
||||
DrawerIndex? drawerIndex;
|
||||
String _version = "";
|
||||
|
||||
@override
|
||||
|
@ -72,7 +72,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
|
||||
drawerIndex = drawerIndexdata;
|
||||
|
||||
var engineType = drawerMap[drawerIndex];
|
||||
var engineType = drawerMap[drawerIndex!];
|
||||
if (engineType != null) {
|
||||
setState(() {
|
||||
Game.shared.setWhoIsAi(engineType);
|
||||
|
@ -136,18 +136,18 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(S.of(context).about + S.of(context).appName + " " + mode,
|
||||
title: Text(S.of(context)!.about + S.of(context)!.appName + " " + mode,
|
||||
style: TextStyle(color: UIColors.primaryColor)),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
SizedBox(height: 5),
|
||||
Text(S.of(context).version + ": $_version",
|
||||
Text(S.of(context)!.version + ": $_version",
|
||||
style: TextStyle(fontFamily: '')),
|
||||
SizedBox(height: 15),
|
||||
InkWell(
|
||||
child: Text(S.of(context).releaseBaseOn,
|
||||
child: Text(S.of(context)!.releaseBaseOn,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -157,7 +157,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
),
|
||||
SizedBox(height: 15),
|
||||
InkWell(
|
||||
child: Text(S.of(context).webSite,
|
||||
child: Text(S.of(context)!.webSite,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -165,7 +165,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
onTap: () => _launchURL('https://github.com/calcitem/Sanmill'),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).whatsNew,
|
||||
child: Text(S.of(context)!.whatsNew,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -174,7 +174,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
'https://github.com/calcitem/Sanmill/commits/master'),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).fastUpdateChannel,
|
||||
child: Text(S.of(context)!.fastUpdateChannel,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -184,13 +184,13 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
),
|
||||
SizedBox(height: 15),
|
||||
InkWell(
|
||||
child: Text(S.of(context).thanks),
|
||||
child: Text(S.of(context)!.thanks),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).thankWho),
|
||||
child: Text(S.of(context)!.thankWho),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).stockfish,
|
||||
child: Text(S.of(context)!.stockfish,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -199,7 +199,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
_launchURL('https://github.com/official-stockfish/Stockfish'),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).chessRoad,
|
||||
child: Text(S.of(context)!.chessRoad,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -207,7 +207,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
onTap: () => _launchURL('https://github.com/hezhaoyun/chessroad'),
|
||||
),
|
||||
InkWell(
|
||||
child: Text(S.of(context).nineChess,
|
||||
child: Text(S.of(context)!.nineChess,
|
||||
style: TextStyle(
|
||||
fontFamily: '',
|
||||
color: Colors.blue,
|
||||
|
@ -218,7 +218,7 @@ class _NavigationHomeScreenState extends State<NavigationHomeScreen> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
child: Text(S.of(context)!.ok),
|
||||
onPressed: () => Navigator.of(context).pop()),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -35,7 +35,7 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
|
||||
setNTotalPiecesEachSide() {
|
||||
//
|
||||
callback(int piecesCount) async {
|
||||
callback(int? piecesCount) async {
|
||||
print("piecesCount = $piecesCount");
|
||||
|
||||
Navigator.of(context).pop();
|
||||
|
@ -185,21 +185,21 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
return Scaffold(
|
||||
backgroundColor: UIColors.lightBackgroundColor,
|
||||
appBar:
|
||||
AppBar(centerTitle: true, title: Text(S.of(context).ruleSettings)),
|
||||
AppBar(centerTitle: true, title: Text(S.of(context)!.ruleSettings)),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const SizedBox(height: 16),
|
||||
Text(S.of(context).rules, style: headerStyle),
|
||||
Text(S.of(context)!.rules, style: headerStyle),
|
||||
Card(
|
||||
color: cardColor,
|
||||
margin: const EdgeInsets.symmetric(vertical: 10),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(S.of(context).piecesCount, style: itemStyle),
|
||||
title: Text(S.of(context)!.piecesCount, style: itemStyle),
|
||||
trailing:
|
||||
Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
|
||||
Text(Config.piecesCount == 6
|
||||
|
@ -217,14 +217,14 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
activeColor: UIColors.primaryColor,
|
||||
value: Config.hasObliqueLines,
|
||||
title:
|
||||
Text(S.of(context).hasObliqueLines, style: itemStyle),
|
||||
Text(S.of(context)!.hasObliqueLines, style: itemStyle),
|
||||
onChanged: setHasObliqueLines,
|
||||
),
|
||||
_buildDivider(),
|
||||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.hasBannedLocations,
|
||||
title: Text(S.of(context).hasBannedLocations,
|
||||
title: Text(S.of(context)!.hasBannedLocations,
|
||||
style: itemStyle),
|
||||
onChanged: setHasBannedLocations,
|
||||
),
|
||||
|
@ -232,7 +232,7 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.isDefenderMoveFirst,
|
||||
title: Text(S.of(context).isDefenderMoveFirst,
|
||||
title: Text(S.of(context)!.isDefenderMoveFirst,
|
||||
style: itemStyle),
|
||||
onChanged: setIsDefenderMoveFirst,
|
||||
),
|
||||
|
@ -241,14 +241,14 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
activeColor: UIColors.primaryColor,
|
||||
value: Config.mayRemoveMultiple,
|
||||
title:
|
||||
Text(S.of(context).mayRemoveMultiple, style: itemStyle),
|
||||
Text(S.of(context)!.mayRemoveMultiple, style: itemStyle),
|
||||
onChanged: setAllowRemoveMultiPiecesWhenCloseMultiMill,
|
||||
),
|
||||
_buildDivider(),
|
||||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.mayRemoveFromMillsAlways,
|
||||
title: Text(S.of(context).mayRemoveFromMillsAlways,
|
||||
title: Text(S.of(context)!.mayRemoveFromMillsAlways,
|
||||
style: itemStyle),
|
||||
onChanged: setAllowRemovePieceInMill,
|
||||
),
|
||||
|
@ -257,7 +257,7 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
activeColor: UIColors.primaryColor,
|
||||
value: Config.isBlackLoseButNotDrawWhenBoardFull,
|
||||
title: Text(
|
||||
S.of(context).isBlackLoseButNotDrawWhenBoardFull,
|
||||
S.of(context)!.isBlackLoseButNotDrawWhenBoardFull,
|
||||
style: itemStyle),
|
||||
onChanged: setIsBlackLoseButNotDrawWhenBoardFull,
|
||||
),
|
||||
|
@ -265,7 +265,7 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.isLoseButNotChangeSideWhenNoWay,
|
||||
title: Text(S.of(context).isLoseButNotChangeSideWhenNoWay,
|
||||
title: Text(S.of(context)!.isLoseButNotChangeSideWhenNoWay,
|
||||
style: itemStyle),
|
||||
onChanged: setIsLoseButNotChangeSideWhenNoWay,
|
||||
),
|
||||
|
@ -273,7 +273,7 @@ class _RuleSettingsPageState extends State<RuleSettingsPage> {
|
|||
SwitchListTile(
|
||||
activeColor: UIColors.primaryColor,
|
||||
value: Config.mayFly,
|
||||
title: Text(S.of(context).mayFly, style: itemStyle),
|
||||
title: Text(S.of(context)!.mayFly, style: itemStyle),
|
||||
onChanged: setAllowFlyingAllowed,
|
||||
),
|
||||
_buildDivider(),
|
||||
|
|
|
@ -4,7 +4,7 @@ description: A new Flutter project.
|
|||
version: 0.19.0+1533
|
||||
|
||||
environment:
|
||||
sdk: '>=2.0.0 <3.0.0'
|
||||
sdk: '>=2.12.0 <3.0.0'
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
|
|
|
@ -23,7 +23,7 @@ import 'package:sanmill/generated/l10n.dart';
|
|||
import 'package:sanmill/widgets/navigation_home_screen.dart';
|
||||
|
||||
void main() {
|
||||
Widget makeTestableWidget({@required Widget child, @required Locale locale}) {
|
||||
Widget makeTestableWidget({required Widget child, required Locale locale}) {
|
||||
return MaterialApp(
|
||||
localizationsDelegates: const <LocalizationsDelegate<dynamic>>[
|
||||
S.delegate,
|
||||
|
|
Loading…
Reference in New Issue