flutter: Support Step forward & Take back all & Step forward all
This commit is contained in:
parent
8c1e8c2ba0
commit
8677f9f322
|
@ -720,9 +720,29 @@
|
|||
"@takingBack": {
|
||||
"description": "Taking back..."
|
||||
},
|
||||
"done": "done.",
|
||||
"waiting": "Waiting...",
|
||||
"@waiting": {
|
||||
"description": "Waiting..."
|
||||
},
|
||||
"stepForward": "Step forward",
|
||||
"@stepForward": {
|
||||
"description": "Step forward"
|
||||
},
|
||||
"takeBackAll": "Take back all",
|
||||
"@takeBackAll": {
|
||||
"description": "Take back all"
|
||||
},
|
||||
"stepForwardAll": "Step forward all",
|
||||
"@stepForwardAll": {
|
||||
"description": "Step forward all"
|
||||
},
|
||||
"moveNow": "Move now",
|
||||
"@moveNow": {
|
||||
"description": "Move now"
|
||||
},
|
||||
"done": "Done.",
|
||||
"@done": {
|
||||
"description": "done."
|
||||
"description": "Done."
|
||||
},
|
||||
"crackMill": "Crack-mill",
|
||||
"@crackMill": {
|
||||
|
|
|
@ -178,8 +178,13 @@
|
|||
"undo": "悔棋",
|
||||
"undoOption": "悔棋",
|
||||
"undoOption_Detail": "允许悔棋",
|
||||
"takeBack": "悔棋",
|
||||
"takeBack": "回退",
|
||||
"takingBack": "回退中",
|
||||
"waiting": "请稍等",
|
||||
"stepForward": "前进",
|
||||
"takeBackAll": "回退到底",
|
||||
"stepForwardAll": "前进到底",
|
||||
"moveNow": "立即行棋",
|
||||
"done": "完成",
|
||||
"crackMill": "不允许吃全三连",
|
||||
"crackMill_Detail": "若对方所有的子都在三连中, 也不允许吃子。",
|
||||
|
|
|
@ -1035,11 +1035,15 @@ class Position {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void takeBack() async {
|
||||
print("TODO: Take back");
|
||||
|
||||
void _gotoHistory(int moveIndex) async {
|
||||
if (recorder == null) {
|
||||
print("[TakeBack] recorder is null.");
|
||||
print("[goto] recorder is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
var history = recorder!.getHistory();
|
||||
if (moveIndex < -1 || history.length <= moveIndex) {
|
||||
print("[goto] moveIndex is out of range.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1049,17 +1053,35 @@ class Position {
|
|||
Game.instance.engineType = EngineType.humanVsHuman;
|
||||
Game.instance.setWhoIsAi(EngineType.humanVsHuman);
|
||||
|
||||
var history = recorder!.getHistory();
|
||||
var historyBack = history;
|
||||
|
||||
await Game.instance.newGame();
|
||||
|
||||
for (var i = 0; i < history.length - 1; i++) {
|
||||
for (var i = 0; i <= moveIndex; i++) {
|
||||
Game.instance.doMove(history[i].move);
|
||||
}
|
||||
|
||||
// Restore context
|
||||
Game.instance.engineType = engineTypeBackup;
|
||||
Game.instance.setWhoIsAi(engineTypeBackup);
|
||||
recorder!.setHistory(historyBack);
|
||||
recorder!.cur = moveIndex;
|
||||
}
|
||||
|
||||
void takeBack() async {
|
||||
_gotoHistory(recorder!.cur - 1);
|
||||
}
|
||||
|
||||
void stepForward() async {
|
||||
_gotoHistory(recorder!.cur + 1);
|
||||
}
|
||||
|
||||
void takeBackAll() async {
|
||||
_gotoHistory(-1);
|
||||
}
|
||||
|
||||
void stepForwardAll() async {
|
||||
_gotoHistory(recorder!.getHistory().length - 1);
|
||||
}
|
||||
|
||||
String movesSinceLastRemove() {
|
||||
|
@ -1099,10 +1121,6 @@ class Position {
|
|||
|
||||
get side => _sideToMove;
|
||||
|
||||
get halfMove => recorder!.halfMove;
|
||||
|
||||
get fullMove => recorder!.fullMove;
|
||||
|
||||
get lastMove => recorder!.last;
|
||||
|
||||
get lastPositionWithRemove => recorder!.lastPositionWithRemove;
|
||||
|
|
|
@ -23,46 +23,42 @@ import 'types.dart';
|
|||
|
||||
// TODO
|
||||
class GameRecorder {
|
||||
int? halfMove, fullMove;
|
||||
int cur = -1;
|
||||
String? lastPositionWithRemove = "";
|
||||
final _history = <Move>[];
|
||||
var _history = <Move>[];
|
||||
|
||||
GameRecorder(
|
||||
{this.halfMove = 0, this.fullMove = 0, this.lastPositionWithRemove});
|
||||
|
||||
GameRecorder.fromCounterMarks(String marks) {
|
||||
//
|
||||
var segments = marks.split(' ');
|
||||
if (segments.length != 2) {
|
||||
throw 'Error: Invalid Counter Marks: $marks';
|
||||
}
|
||||
|
||||
halfMove = int.parse(segments[0]);
|
||||
fullMove = int.parse(segments[1]);
|
||||
|
||||
if (halfMove == null || fullMove == null) {
|
||||
throw 'Error: Invalid Counter Marks: $marks';
|
||||
}
|
||||
}
|
||||
GameRecorder({this.cur = -1, this.lastPositionWithRemove});
|
||||
|
||||
List<Move> getHistory() {
|
||||
return _history;
|
||||
}
|
||||
|
||||
void setHistory(List<Move> newHistory) {
|
||||
_history = newHistory;
|
||||
}
|
||||
|
||||
void jumpToHead() {
|
||||
cur = 0;
|
||||
}
|
||||
|
||||
void jumpToTail() {
|
||||
cur = _history.length - 1;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_history.clear();
|
||||
cur = 0;
|
||||
}
|
||||
|
||||
void prune() {
|
||||
if (cur == _history.length - 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
_history.removeRange(cur + 1, _history.length);
|
||||
}
|
||||
|
||||
void moveIn(Move move, Position position) {
|
||||
//
|
||||
if (move.type == MoveType.remove) {
|
||||
halfMove = 0;
|
||||
} else {
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
}
|
||||
|
||||
if (fullMove == 0) {
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
} else if (position.side != PieceColor.white) {
|
||||
if (halfMove != null) halfMove = halfMove! + 1;
|
||||
}
|
||||
|
||||
if (_history.length > 0) {
|
||||
if (_history[_history.length - 1].move == move.move) {
|
||||
//assert(false);
|
||||
|
@ -72,6 +68,7 @@ class GameRecorder {
|
|||
}
|
||||
|
||||
_history.add(move);
|
||||
cur++;
|
||||
|
||||
if (move.type == MoveType.remove) {
|
||||
lastPositionWithRemove = position.fen();
|
||||
|
@ -85,24 +82,16 @@ class GameRecorder {
|
|||
|
||||
get last => _history.isEmpty ? null : _history.last;
|
||||
|
||||
List<Move> reverseMovesToPrevRemove() {
|
||||
//
|
||||
List<Move> moves = [];
|
||||
Move moveAt(int index) => _history[index];
|
||||
|
||||
for (var i = _history.length - 1; i >= 0; i--) {
|
||||
if (_history[i].type == MoveType.remove) break;
|
||||
moves.add(_history[i]);
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
get movesCount => _history.length;
|
||||
|
||||
String buildMoveHistoryText({cols = 2}) {
|
||||
var moveHistoryText = '';
|
||||
int k = 1;
|
||||
String num = "";
|
||||
|
||||
for (var i = 0; i < _history.length; i++) {
|
||||
for (var i = 0; i <= cur; i++) {
|
||||
if (Config.standardNotationEnabled) {
|
||||
if (k % cols == 1) {
|
||||
num = "${(k + 1) ~/ 2}. ";
|
||||
|
@ -112,8 +101,7 @@ class GameRecorder {
|
|||
} else {
|
||||
num = "";
|
||||
}
|
||||
if (i + 1 < _history.length &&
|
||||
_history[i + 1].type == MoveType.remove) {
|
||||
if (i + 1 <= cur && _history[i + 1].type == MoveType.remove) {
|
||||
moveHistoryText +=
|
||||
'$num${_history[i].notation}${_history[i + 1].notation} ';
|
||||
i++;
|
||||
|
@ -138,13 +126,4 @@ class GameRecorder {
|
|||
|
||||
return moveHistoryText;
|
||||
}
|
||||
|
||||
Move moveAt(int index) => _history[index];
|
||||
|
||||
get movesCount => _history.length;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$halfMove $fullMove';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ class GamePage extends StatefulWidget {
|
|||
class _GamePageState extends State<GamePage> with RouteAware {
|
||||
String? _tip = '';
|
||||
bool isReady = false;
|
||||
bool isTakingBack = false;
|
||||
bool isGoingToHistory = false;
|
||||
late Timer timer;
|
||||
final String tag = "[game_page]";
|
||||
|
||||
|
@ -357,6 +357,7 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
//position.move = m;
|
||||
|
||||
Move m = Move(position.record);
|
||||
position.recorder.prune();
|
||||
position.recorder.moveIn(m, position);
|
||||
|
||||
setState(() {});
|
||||
|
@ -491,6 +492,36 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
ListItemDivider(),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).stepForward,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
),
|
||||
onPressed: onStepForwardButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
ListItemDivider(),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).takeBackAll,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
),
|
||||
onPressed: onTakeBackAllButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
ListItemDivider(),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).stepForwardAll,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
),
|
||||
onPressed: onStepForwardAllButtonPressed,
|
||||
),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
ListItemDivider(),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).moveList,
|
||||
|
@ -498,27 +529,72 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
),
|
||||
onPressed: onMoveListButtonPressed,
|
||||
),
|
||||
/*
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
ListItemDivider(),
|
||||
SizedBox(height: AppTheme.sizedBoxHeight),
|
||||
SimpleDialogOption(
|
||||
child: Text(
|
||||
S.of(context).moveNow,
|
||||
style: AppTheme.simpleDialogOptionTextStyle,
|
||||
),
|
||||
onPressed: onMoveNowButtonPressed,
|
||||
),
|
||||
*/
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
onGotoHistoryButtonsPressed(var func) async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
if (mounted) {
|
||||
showTip(S.of(context).waiting);
|
||||
}
|
||||
|
||||
if (isGoingToHistory) {
|
||||
print("[TakeBack] Is going to history, ignore Take Back button press.");
|
||||
return;
|
||||
}
|
||||
|
||||
isGoingToHistory = true;
|
||||
await func;
|
||||
isGoingToHistory = false;
|
||||
|
||||
if (mounted) {
|
||||
showTip(S.of(context).done);
|
||||
}
|
||||
}
|
||||
|
||||
onTakeBackButtonPressed() async {
|
||||
onGotoHistoryButtonsPressed(Game.instance.position.takeBack());
|
||||
}
|
||||
|
||||
onStepForwardButtonPressed() async {
|
||||
onGotoHistoryButtonsPressed(Game.instance.position.stepForward());
|
||||
}
|
||||
|
||||
onTakeBackAllButtonPressed() async {
|
||||
onGotoHistoryButtonsPressed(Game.instance.position.takeBackAll());
|
||||
}
|
||||
|
||||
onStepForwardAllButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
|
||||
if (mounted) {
|
||||
showTip(S.of(context).takingBack);
|
||||
}
|
||||
|
||||
if (isTakingBack) {
|
||||
if (isGoingToHistory) {
|
||||
print("[TakeBack] Is taking back, ignore Take Back button press.");
|
||||
return;
|
||||
}
|
||||
|
||||
isTakingBack = true;
|
||||
await Game.instance.position.takeBack();
|
||||
isTakingBack = false;
|
||||
isGoingToHistory = true;
|
||||
await Game.instance.position.stepForwardAll();
|
||||
isGoingToHistory = false;
|
||||
|
||||
//Audios.playTone(Audios.placeSoundId);
|
||||
|
||||
|
@ -564,6 +640,11 @@ class _GamePageState extends State<GamePage> with RouteAware {
|
|||
);
|
||||
}
|
||||
|
||||
onMoveNowButtonPressed() async {
|
||||
Navigator.of(context).pop();
|
||||
/* Not implement */
|
||||
}
|
||||
|
||||
onInfoButtonPressed() {
|
||||
final analyzeText = getInfoText();
|
||||
|
||||
|
|
Loading…
Reference in New Issue