diff --git a/src/ui/flutter/lib/common/types.dart b/src/ui/flutter/lib/common/types.dart index 4f4ce381..8b137891 100644 --- a/src/ui/flutter/lib/common/types.dart +++ b/src/ui/flutter/lib/common/types.dart @@ -1,77 +1 @@ -enum Move { none } -enum MoveType { place, move, remove } - -enum Color { noColor, black, white, count, draw, nobody } - -enum Phase { none, ready, placing, moving, gameOver } - -enum Action { none, select, place, remove } - -enum GameOverReason { - loseReasonNoReason, - loseReasonlessThanThree, - loseReasonNoWay, - loseReasonBoardIsFull, - loseReasonResign, - loseReasonTimeOver, - drawReasonThreefoldRepetition, - drawReasonRule50, - drawReasonBoardIsFull -} - -enum PieceType { none, blackStone, whiteStone, ban, count, stone } - -enum Piece { none, blackStone, whiteStone, ban } - -enum Square { - SQ_0, - SQ_1, - SQ_2, - SQ_3, - SQ_4, - SQ_5, - SQ_6, - SQ_7, - SQ_8, - SQ_9, - SQ_10, - SQ_11, - SQ_12, - SQ_13, - SQ_14, - SQ_15, - SQ_16, - SQ_17, - SQ_18, - SQ_19, - SQ_20, - SQ_21, - SQ_22, - SQ_23, - SQ_24, - SQ_25, - SQ_26, - SQ_27, - SQ_28, - SQ_29, - SQ_30, - SQ_31, -} - -const sqBegin = Square.SQ_8; -const sqEnd = 32; -const sqNumber = 40; -const effectiveSqNumber = 24; - -enum MoveDirection { clockwise, anticlockwise, inward, outward } - -enum LineDirection { horizontal, vertical, slash } - -enum File { A, B, C } - -const fileNumber = 3; - -enum Rank { rank_1, rank_2, rank_3, rank_4, rank_5, rank_6, rank_7, rank_8 } - -const rankNumber = 8; diff --git a/src/ui/flutter/lib/game/battle.dart b/src/ui/flutter/lib/game/battle.dart index ec1e6a84..0cd573e1 100644 --- a/src/ui/flutter/lib/game/battle.dart +++ b/src/ui/flutter/lib/game/battle.dart @@ -14,7 +14,7 @@ class Battle { } init() { - _position = Position.defaultPosition(); + _position = Position.init(); _focusIndex = _blurIndex = Move.invalidIndex; } @@ -47,7 +47,7 @@ class Battle { bool regret({steps = 2}) { // // 轮到自己走棋的时候,才能悔棋 - if (_position.side != Side.white) { + if (_position.side != Color.white) { //Audios.playTone('invalid.mp3'); return false; } @@ -88,18 +88,16 @@ class Battle { _blurIndex = _focusIndex = Move.invalidIndex; } - BattleResult scanBattleResult() { + GameResult scanBattleResult() { // - final forPerson = (_position.side == Side.white); + final forPerson = (_position.side == Color.white); if (scanLongCatch()) { // born 'repeat' position by oppo - return forPerson ? BattleResult.win : BattleResult.lose; + return forPerson ? GameResult.win : GameResult.lose; } - return (_position.halfMove > 120) - ? BattleResult.draw - : BattleResult.pending; + return (_position.halfMove > 120) ? GameResult.draw : GameResult.pending; } scanLongCatch() { diff --git a/src/ui/flutter/lib/mill/mill.dart b/src/ui/flutter/lib/mill/mill.dart index 0df4b27b..ced81f93 100644 --- a/src/ui/flutter/lib/mill/mill.dart +++ b/src/ui/flutter/lib/mill/mill.dart @@ -1,7 +1,79 @@ -/// 对战结果:未决、赢、输、和 -enum BattleResult { pending, win, lose, draw } +enum MoveType { place, move, remove } -class Side { +enum Phase { none, ready, placing, moving, gameOver } + +enum Action { none, select, place, remove } + +enum GameOverReason { + loseReasonNoReason, + loseReasonlessThanThree, + loseReasonNoWay, + loseReasonBoardIsFull, + loseReasonResign, + loseReasonTimeOver, + drawReasonThreefoldRepetition, + drawReasonRule50, + drawReasonBoardIsFull +} + +enum PieceType { none, blackStone, whiteStone, ban, count, stone } + +enum Square { + SQ_0, + SQ_1, + SQ_2, + SQ_3, + SQ_4, + SQ_5, + SQ_6, + SQ_7, + SQ_8, + SQ_9, + SQ_10, + SQ_11, + SQ_12, + SQ_13, + SQ_14, + SQ_15, + SQ_16, + SQ_17, + SQ_18, + SQ_19, + SQ_20, + SQ_21, + SQ_22, + SQ_23, + SQ_24, + SQ_25, + SQ_26, + SQ_27, + SQ_28, + SQ_29, + SQ_30, + SQ_31, +} + +const sqBegin = Square.SQ_8; +const sqEnd = 32; +const sqNumber = 40; +const effectiveSqNumber = 24; + +enum MoveDirection { clockwise, anticlockwise, inward, outward } + +enum LineDirection { horizontal, vertical, slash } + +enum File { A, B, C } + +const fileNumber = 3; + +enum Rank { rank_1, rank_2, rank_3, rank_4, rank_5, rank_6, rank_7, rank_8 } + +const rankNumber = 8; + +/// 对战结果:未决、赢、输、和 +enum GameResult { pending, win, lose, draw } + +class Color { // static const unknown = '-'; static const black = 'b'; @@ -15,15 +87,17 @@ class Side { return unknown; } - static bool sameSide(String p1, String p2) { + static bool isSameColor(String p1, String p2) { return of(p1) == of(p2); } - static String opponent(String side) { - if (side == white) return black; - if (side == black) return white; - return side; + static String opponent(String color) { + if (color == white) return black; + if (color == black) return white; + return color; } + + String operator -(String c) => opponent(c); } class Piece { @@ -34,14 +108,6 @@ class Piece { static const whiteStone = 'w'; static const ban = 'x'; - static const Names = { - noPiece: '', - // - blackStone: 'b', - whiteStone: 'w', - ban: 'x', - }; - static bool isBlack(String c) => 'b'.contains(c); static bool isWhite(String c) => 'w'.contains(c); diff --git a/src/ui/flutter/lib/mill/position.dart b/src/ui/flutter/lib/mill/position.dart index 9027039b..2ea093af 100644 --- a/src/ui/flutter/lib/mill/position.dart +++ b/src/ui/flutter/lib/mill/position.dart @@ -28,130 +28,33 @@ Map sqToLoc = { 31: 0 }; -Map locToSq; +Map locToSq = sqToLoc.map((k, v) => MapEntry(v, k)); class Position { - // - BattleResult result = BattleResult.pending; - - String _sideToMove; - List _board; // 8 * 3 + GameResult result = GameResult.pending; + String _sideToMove = Color.black; + List _board = List(49); // 7 * 7 MillRecorder _recorder; - Position.defaultPosition() { - initDefaultPosition(); - } - - void initDefaultPosition() { - // - locToSq = sqToLoc.map((k, v) => MapEntry(v, k)); - - _sideToMove = Side.black; - _board = List(64); // 7 * 7 - for (var i = 0; i < 64; i++) { + Position.init() { + for (var i = 0; i < _board.length; i++) { _board[i] ??= Piece.noPiece; } - // Debugging - _board[sqToLoc[8]] = Piece.blackStone; - //_board[7] = Piece.ban; - //_board[8] = Piece.whiteStone; + // Example + //_board[sqToLoc[8]] = Piece.blackStone; - _recorder = MillRecorder(lastCapturedPosition: toFen()); + _recorder = MillRecorder(lastCapturedPosition: fen()); } Position.clone(Position other) { - // _board = List(); - other._board.forEach((piece) => _board.add(piece)); - _sideToMove = other._sideToMove; - _recorder = other._recorder; } - void putPiece(var pt, int index) { - _board[index] = pt; - } - - String move(int from, int to) { - // - if (!validateMove(from, to)) return null; - - final captured = _board[to]; - - final move = Move(from, to, captured: captured); - //StepName.translate(this, move); - _recorder.stepIn(move, this); - - // 修改棋盘 - _board[to] = _board[from]; - _board[from] = Piece.noPiece; - - // 交换走棋方 - _sideToMove = Side.opponent(_sideToMove); - - return captured; - } - - // 验证移动棋子的着法是否合法 - bool validateMove(int from, int to) { - // 移动的棋子的选手,应该是当前方 - if (Side.of(_board[from]) != _sideToMove) return false; - return true; - //(StepValidate.validate(this, Move(from, to))); - } - - // 在判断行棋合法性等环节,要在克隆的棋盘上进行行棋假设,然后检查效果 - // 这种情况下不验证、不记录、不翻译 - void moveTest(Move move, {turnSide = false}) { - // - // 修改棋盘 - _board[move.to] = _board[move.from]; - _board[move.from] = Piece.noPiece; - - // 交换走棋方 - if (turnSide) _sideToMove = Side.opponent(_sideToMove); - } - - bool regret() { - // - final lastMove = _recorder.removeLast(); - if (lastMove == null) return false; - - _board[lastMove.from] = _board[lastMove.to]; - _board[lastMove.to] = lastMove.captured; - - _sideToMove = Side.opponent(_sideToMove); - - final counterMarks = MillRecorder.fromCounterMarks(lastMove.counterMarks); - _recorder.halfMove = counterMarks.halfMove; - _recorder.fullMove = counterMarks.fullMove; - - if (lastMove.captured != Piece.noPiece) { - // - // 查找上一个吃子局面(或开局),NativeEngine 需要 - final tempPosition = Position.clone(this); - - final moves = _recorder.reverseMovesToPrevCapture(); - moves.forEach((move) { - // - tempPosition._board[move.from] = tempPosition._board[move.to]; - tempPosition._board[move.to] = move.captured; - - tempPosition._sideToMove = Side.opponent(tempPosition._sideToMove); - }); - - _recorder.lastCapturedPosition = tempPosition.toFen(); - } - - result = BattleResult.pending; - - return true; - } - - String toFen() { + String fen() { // TODO var fen = ''; @@ -191,6 +94,86 @@ class Position { return fen; } + void putPiece(var pt, int index) { + _board[index] = pt; + } + + String move(int from, int to) { + // + if (!validateMove(from, to)) return null; + + final captured = _board[to]; + + final move = Move(from, to, captured: captured); + //StepName.translate(this, move); + _recorder.stepIn(move, this); + + // 修改棋盘 + _board[to] = _board[from]; + _board[from] = Piece.noPiece; + + // 交换走棋方 + _sideToMove = Color.opponent(_sideToMove); + + return captured; + } + + // 验证移动棋子的着法是否合法 + bool validateMove(int from, int to) { + // 移动的棋子的选手,应该是当前方 + //if (Color.of(_board[from]) != _sideToMove) return false; + return true; + //(StepValidate.validate(this, Move(from, to))); + } + + // 在判断行棋合法性等环节,要在克隆的棋盘上进行行棋假设,然后检查效果 + // 这种情况下不验证、不记录、不翻译 + void moveTest(Move move, {turnSide = false}) { + // + // 修改棋盘 + _board[move.to] = _board[move.from]; + _board[move.from] = Piece.noPiece; + + // 交换走棋方 + if (turnSide) _sideToMove = Color.opponent(_sideToMove); + } + + bool regret() { + // + final lastMove = _recorder.removeLast(); + if (lastMove == null) return false; + + _board[lastMove.from] = _board[lastMove.to]; + _board[lastMove.to] = lastMove.captured; + + _sideToMove = Color.opponent(_sideToMove); + + final counterMarks = MillRecorder.fromCounterMarks(lastMove.counterMarks); + _recorder.halfMove = counterMarks.halfMove; + _recorder.fullMove = counterMarks.fullMove; + + if (lastMove.captured != Piece.noPiece) { + // + // 查找上一个吃子局面(或开局),NativeEngine 需要 + final tempPosition = Position.clone(this); + + final moves = _recorder.reverseMovesToPrevCapture(); + moves.forEach((move) { + // + tempPosition._board[move.from] = tempPosition._board[move.to]; + tempPosition._board[move.to] = move.captured; + + tempPosition._sideToMove = Color.opponent(tempPosition._sideToMove); + }); + + _recorder.lastCapturedPosition = tempPosition.fen(); + } + + result = GameResult.pending; + + return true; + } + String movesSinceLastCaptured() { // var steps = '', posAfterLastCaptured = 0; @@ -211,7 +194,7 @@ class Position { get side => _sideToMove; - changeSideToMove() => _sideToMove = Side.opponent(_sideToMove); + changeSideToMove() => _sideToMove = Color.opponent(_sideToMove); String pieceAt(int index) => _board[index]; diff --git a/src/ui/flutter/lib/mill/recorder.dart b/src/ui/flutter/lib/mill/recorder.dart index 0b9f5187..da84d934 100644 --- a/src/ui/flutter/lib/mill/recorder.dart +++ b/src/ui/flutter/lib/mill/recorder.dart @@ -34,14 +34,14 @@ class MillRecorder { if (fullMove == 0) { fullMove++; - } else if (position.side != Side.black) { + } else if (position.side != Color.black) { fullMove++; } _history.add(move); if (move.captured != Piece.noPiece) { - lastCapturedPosition = position.toFen(); + lastCapturedPosition = position.fen(); } } diff --git a/src/ui/flutter/lib/routes/battle_page.dart b/src/ui/flutter/lib/routes/battle_page.dart index 6307210c..2593d437 100644 --- a/src/ui/flutter/lib/routes/battle_page.dart +++ b/src/ui/flutter/lib/routes/battle_page.dart @@ -57,14 +57,14 @@ class _BattlePageState extends State { position.putPiece(flag % 2 == 0 ? 'b' : 'w', index); // 仅 Position 中的 side 指示一方能动棋 - if (position.side != Side.black) return; + if (position.side != Color.black) return; final tapedPiece = position.pieceAt(index); print("Tap piece $tapedPiece at <$index>"); // 之前已经有棋子被选中了 if (Battle.shared.focusIndex != Move.invalidIndex && - Side.of(position.pieceAt(Battle.shared.focusIndex)) == Side.black) { + Color.of(position.pieceAt(Battle.shared.focusIndex)) == Color.black) { // // 当前点击的棋子和之前已经选择的是同一个位置 if (Battle.shared.focusIndex == index) return; @@ -72,7 +72,7 @@ class _BattlePageState extends State { // 之前已经选择的棋子和现在点击的棋子是同一边的,说明是选择另外一个棋子 final focusPiece = position.pieceAt(Battle.shared.focusIndex); - if (Side.sameSide(focusPiece, tapedPiece)) { + if (Color.isSameColor(focusPiece, tapedPiece)) { // Battle.shared.select(index); // @@ -81,16 +81,16 @@ class _BattlePageState extends State { final result = Battle.shared.scanBattleResult(); switch (result) { - case BattleResult.pending: + case GameResult.pending: engineToGo(); break; - case BattleResult.win: + case GameResult.win: gotWin(); break; - case BattleResult.lose: + case GameResult.lose: gotLose(); break; - case BattleResult.draw: + case GameResult.draw: gotDraw(); break; } @@ -118,16 +118,16 @@ class _BattlePageState extends State { final result = Battle.shared.scanBattleResult(); switch (result) { - case BattleResult.pending: + case GameResult.pending: changeStatus('请走棋...'); break; - case BattleResult.win: + case GameResult.win: gotWin(); break; - case BattleResult.lose: + case GameResult.lose: gotLose(); break; - case BattleResult.draw: + case GameResult.draw: gotDraw(); break; } @@ -211,7 +211,7 @@ class _BattlePageState extends State { void gotWin() { // - Battle.shared.position.result = BattleResult.win; + Battle.shared.position.result = GameResult.win; //Audios.playTone('win.mp3'); showDialog( @@ -239,7 +239,7 @@ class _BattlePageState extends State { void gotLose() { // - Battle.shared.position.result = BattleResult.lose; + Battle.shared.position.result = GameResult.lose; //Audios.playTone('lose.mp3'); showDialog( @@ -262,7 +262,7 @@ class _BattlePageState extends State { void gotDraw() { // - Battle.shared.position.result = BattleResult.draw; + Battle.shared.position.result = GameResult.draw; showDialog( context: context,