From 728c43a8605b3a44a535583373893bcb7a6e03d0 Mon Sep 17 00:00:00 2001 From: Calcitem <calcitem@outlook.com> Date: Mon, 17 May 2021 22:18:24 +0800 Subject: [PATCH] flutter: Support taking back --- src/ui/flutter_app/lib/l10n/intl_en.arb | 12 ++++ src/ui/flutter_app/lib/l10n/intl_zh.arb | 3 + src/ui/flutter_app/lib/mill/position.dart | 28 ++++++++++ src/ui/flutter_app/lib/mill/recorder.dart | 5 ++ src/ui/flutter_app/lib/widgets/game_page.dart | 56 +++++++++++++++++++ 5 files changed, 104 insertions(+) diff --git a/src/ui/flutter_app/lib/l10n/intl_en.arb b/src/ui/flutter_app/lib/l10n/intl_en.arb index 33f3789bc..3031c8982 100644 --- a/src/ui/flutter_app/lib/l10n/intl_en.arb +++ b/src/ui/flutter_app/lib/l10n/intl_en.arb @@ -712,6 +712,18 @@ "@undoOption_Detail": { "description": "It is possible to undo a move." }, + "takeBack": "Take back", + "@takeBack": { + "description": "Take back" + }, + "takingBack": "Taking back...", + "@takingBack": { + "description": "Taking back..." + }, + "done": "done.", + "@done": { + "description": "done." + }, "crackMill": "Crack-mill", "@crackMill": { "description": "Crack-mill" diff --git a/src/ui/flutter_app/lib/l10n/intl_zh.arb b/src/ui/flutter_app/lib/l10n/intl_zh.arb index 38884cf22..3af0be294 100644 --- a/src/ui/flutter_app/lib/l10n/intl_zh.arb +++ b/src/ui/flutter_app/lib/l10n/intl_zh.arb @@ -178,6 +178,9 @@ "undo": "悔棋", "undoOption": "悔棋", "undoOption_Detail": "允许悔棋", + "takeBack": "悔棋", + "takingBack": "回退中", + "done": "完成", "crackMill": "不允许吃全三连", "crackMill_Detail": "若对方所有的子都在三连中, 也不允许吃子。", "haveFunPlaying": "祝您玩得愉快!", diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index 37b4d30b5..dd0a194c5 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import 'package:sanmill/engine/engine.dart'; import 'package:sanmill/mill/game.dart'; import 'package:sanmill/mill/recorder.dart'; import 'package:sanmill/mill/rule.dart'; @@ -1034,6 +1035,33 @@ class Position { /////////////////////////////////////////////////////////////////////////////// + void takeBack() async { + print("TODO: Take back"); + + if (recorder == null) { + print("[TakeBack] recorder is null."); + return; + } + + // Backup context + var engineTypeBackup = Game.instance.engineType; + + Game.instance.engineType = EngineType.humanVsHuman; + Game.instance.setWhoIsAi(EngineType.humanVsHuman); + + var history = recorder!.getHistory(); + + await Game.instance.newGame(); + + for (var i = 0; i < history.length - 1; i++) { + Game.instance.doMove(history[i].move); + } + + // Restore context + Game.instance.engineType = engineTypeBackup; + Game.instance.setWhoIsAi(engineTypeBackup); + } + bool regret() { // TODO final lastMove = recorder!.removeLast(); diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index d75866b46..64a799809 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -29,6 +29,7 @@ class GameRecorder { GameRecorder( {this.halfMove = 0, this.fullMove = 0, this.lastPositionWithRemove}); + GameRecorder.fromCounterMarks(String marks) { // var segments = marks.split(' '); @@ -44,6 +45,10 @@ class GameRecorder { } } + List<Move> getHistory() { + return _history; + } + void moveIn(Move move, Position position) { // if (move.type == MoveType.remove) { diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index b79417bcc..8cc71c011 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -35,6 +35,7 @@ import 'package:stack_trace/stack_trace.dart'; import 'board.dart'; import 'game_settings_page.dart'; +import 'list_item_divider.dart'; class GamePage extends StatefulWidget { static double boardMargin = AppTheme.boardMargin; @@ -52,6 +53,7 @@ class GamePage extends StatefulWidget { class _GamePageState extends State<GamePage> with RouteAware { String? _tip = ''; bool isReady = false; + bool isTakingBack = false; late Timer timer; final String tag = "[game_page]"; @@ -472,8 +474,62 @@ class _GamePageState extends State<GamePage> with RouteAware { } onMoveButtonPressed() { + showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + children: <Widget>[ + SimpleDialogOption( + child: Text( + S.of(context).takeBack, + style: AppTheme.simpleDialogOptionTextStyle, + ), + onPressed: onTakeBackButtonPressed, + ), + SizedBox(height: AppTheme.sizedBoxHeight), + ListItemDivider(), + SizedBox(height: AppTheme.sizedBoxHeight), + SimpleDialogOption( + child: Text( + S.of(context).moveList, + style: AppTheme.simpleDialogOptionTextStyle, + ), + onPressed: onMoveListButtonPressed, + ), + ], + ); + }, + ); + } + + onTakeBackButtonPressed() async { + Navigator.of(context).pop(); + + if (mounted) { + showTip(S.of(context).takingBack); + } + + if (isTakingBack) { + print("[TakeBack] Is taking back, ignore Take Back button press."); + return; + } + + isTakingBack = true; + await Game.instance.position.takeBack(); + isTakingBack = false; + + //Audios.playTone(Audios.placeSoundId); + + if (mounted) { + showTip(S.of(context).takeBack + " " + S.of(context).done); + } + } + + onMoveListButtonPressed() { final moveHistoryText = Game.instance.position.moveHistoryText; + Navigator.of(context).pop(); + showDialog( context: context, barrierDismissible: true,