diff --git a/src/ui/flutter_app/lib/engine/native_engine.dart b/src/ui/flutter_app/lib/engine/native_engine.dart index 90f2f273..8cb57d40 100644 --- a/src/ui/flutter_app/lib/engine/native_engine.dart +++ b/src/ui/flutter_app/lib/engine/native_engine.dart @@ -20,7 +20,7 @@ import 'dart:async'; import 'package:flutter/services.dart'; import 'package:sanmill/common/config.dart'; -import 'package:sanmill/mill/mill.dart'; +import 'package:sanmill/mill/types.dart'; import 'package:sanmill/mill/position.dart'; import 'engine.dart'; diff --git a/src/ui/flutter_app/lib/mill/game.dart b/src/ui/flutter_app/lib/mill/game.dart index 853d9e3a..65da98d6 100644 --- a/src/ui/flutter_app/lib/mill/game.dart +++ b/src/ui/flutter_app/lib/mill/game.dart @@ -19,7 +19,6 @@ import 'package:sanmill/common/config.dart'; import 'package:sanmill/engine/engine.dart'; -import 'mill.dart'; import 'position.dart'; import 'types.dart'; diff --git a/src/ui/flutter_app/lib/mill/mill.dart b/src/ui/flutter_app/lib/mill/mill.dart deleted file mode 100644 index 01ccaadc..00000000 --- a/src/ui/flutter_app/lib/mill/mill.dart +++ /dev/null @@ -1,203 +0,0 @@ -/* - This file is part of Sanmill. - Copyright (C) 2019-2021 The Sanmill developers (see AUTHORS file) - - Sanmill is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Sanmill is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -import 'types.dart'; - -Map squareToIndex = { - 8: 17, - 9: 18, - 10: 25, - 11: 32, - 12: 31, - 13: 30, - 14: 23, - 15: 16, - 16: 10, - 17: 12, - 18: 26, - 19: 40, - 20: 38, - 21: 36, - 22: 22, - 23: 8, - 24: 3, - 25: 6, - 26: 27, - 27: 48, - 28: 45, - 29: 42, - 30: 21, - 31: 0 -}; - -Map indexToSquare = squareToIndex.map((k, v) => MapEntry(v, k)); - -int makeSquare(int file, int rank) { - return (file << 3) + rank - 1; -} - -enum GameResult { pending, win, lose, draw, none } - -class PieceColor { - static const none = '*'; - static const black = '@'; - static const white = 'O'; - static const ban = 'X'; - static const nobody = '-'; - static const draw = '='; - - static String of(String piece) { - if (black.contains(piece)) return black; - if (white.contains(piece)) return white; - if (ban.contains(piece)) return ban; - return nobody; - } - - static bool isSameColor(String p1, String p2) { - return of(p1) == of(p2); - } - - 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 { - static const noPiece = PieceColor.none; - static const blackStone = PieceColor.black; - static const whiteStone = PieceColor.white; - static const ban = PieceColor.ban; - - static bool isEmpty(String c) => noPiece.contains(c); - static bool isBlack(String c) => blackStone.contains(c); - static bool isWhite(String c) => whiteStone.contains(c); - static bool isBan(String c) => ban.contains(c); -} - -class Move { - static const invalidMove = -1; - - // Square - int from = 0; - int to = 0; - - // file & rank - int fromFile = 0; - int fromRank = 0; - int toFile = 0; - int toRank = 0; - - // Index - int fromIndex = 0; - int toIndex = 0; - - String removed = Piece.noPiece; - - // 'move' is the UCI engine's move-string - String? move = ""; - - MoveType type = MoveType.none; - - // Used to restore fen step conter when regreting - String counterMarks = ""; - - parse() { - if (!legal(move)) { - throw "Error: Invalid Move: $move"; - } - - 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]); - //captured = Piece.noPiece; - } else if (move!.length == "(1,2)->(3,4)".length) { - type = MoveType.move; - 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]); - removed = Piece.noPiece; - } 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]); - removed = Piece.noPiece; - } else if (move == "draw") { - // TODO - print("Computer request draw"); - } else { - assert(false); - } - - to = makeSquare(toFile, toRank); - toIndex = squareToIndex[to] ?? invalidMove; - } - - Move(this.move) { - parse(); - } - - /// Format: - /// Place: (1,2) - /// Remove: -(1,2) - /// Move: (3,1)->(2,1) - - Move.set(String move) { - this.move = move; - parse(); - } - - static bool legal(String? move) { - if (move == "draw") { - return true; // TODO - } - - if (move == null || move.length > "(3,1)->(2,1)".length) return false; - - String range = "0123456789(,)->"; - - if (!(move[0] == '(' || move[0] == '-')) { - return false; - } - - if (move[move.length - 1] != ')') { - return false; - } - - for (int i = 0; i < move.length; i++) { - if (!range.contains(move[i])) return false; - } - - if (move.length == "(3,1)->(2,1)".length) { - if (move.substring(0, 4) == move.substring(7, 11)) { - return false; - } - } - - return true; - } -} diff --git a/src/ui/flutter_app/lib/mill/position.dart b/src/ui/flutter_app/lib/mill/position.dart index 04b07d8d..843e22dc 100644 --- a/src/ui/flutter_app/lib/mill/position.dart +++ b/src/ui/flutter_app/lib/mill/position.dart @@ -17,7 +17,7 @@ */ import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/mill/mill.dart'; +import 'package:sanmill/mill/types.dart'; import 'package:sanmill/mill/recorder.dart'; import 'package:sanmill/mill/rule.dart'; import 'package:sanmill/services/audios.dart'; diff --git a/src/ui/flutter_app/lib/mill/recorder.dart b/src/ui/flutter_app/lib/mill/recorder.dart index 8578358a..080f0c17 100644 --- a/src/ui/flutter_app/lib/mill/recorder.dart +++ b/src/ui/flutter_app/lib/mill/recorder.dart @@ -16,7 +16,6 @@ along with this program. If not, see . */ -import 'mill.dart'; import 'position.dart'; import 'types.dart'; diff --git a/src/ui/flutter_app/lib/mill/types.dart b/src/ui/flutter_app/lib/mill/types.dart index 2658cbcb..2064fa0e 100644 --- a/src/ui/flutter_app/lib/mill/types.dart +++ b/src/ui/flutter_app/lib/mill/types.dart @@ -18,8 +18,143 @@ abs(value) => value > 0 ? value : -value; +class Move { + static const invalidMove = -1; + + // Square + int from = 0; + int to = 0; + + // file & rank + int fromFile = 0; + int fromRank = 0; + int toFile = 0; + int toRank = 0; + + // Index + int fromIndex = 0; + int toIndex = 0; + + String removed = Piece.noPiece; + + // 'move' is the UCI engine's move-string + String? move = ""; + + MoveType type = MoveType.none; + + // Used to restore fen step conter when regreting + String counterMarks = ""; + + parse() { + if (!legal(move)) { + throw "Error: Invalid Move: $move"; + } + + 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]); + //captured = Piece.noPiece; + } else if (move!.length == "(1,2)->(3,4)".length) { + type = MoveType.move; + 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]); + removed = Piece.noPiece; + } 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]); + removed = Piece.noPiece; + } else if (move == "draw") { + // TODO + print("Computer request draw"); + } else { + assert(false); + } + + to = makeSquare(toFile, toRank); + toIndex = squareToIndex[to] ?? invalidMove; + } + + Move(this.move) { + parse(); + } + + /// Format: + /// Place: (1,2) + /// Remove: -(1,2) + /// Move: (3,1)->(2,1) + + Move.set(String move) { + this.move = move; + parse(); + } + + static bool legal(String? move) { + if (move == "draw") { + return true; // TODO + } + + if (move == null || move.length > "(3,1)->(2,1)".length) return false; + + String range = "0123456789(,)->"; + + if (!(move[0] == '(' || move[0] == '-')) { + return false; + } + + if (move[move.length - 1] != ')') { + return false; + } + + for (int i = 0; i < move.length; i++) { + if (!range.contains(move[i])) return false; + } + + if (move.length == "(3,1)->(2,1)".length) { + if (move.substring(0, 4) == move.substring(7, 11)) { + return false; + } + } + + return true; + } +} + enum MoveType { place, move, remove, none } +class PieceColor { + static const none = '*'; + static const black = '@'; + static const white = 'O'; + static const ban = 'X'; + static const nobody = '-'; + static const draw = '='; + + static String of(String piece) { + if (black.contains(piece)) return black; + if (white.contains(piece)) return white; + if (ban.contains(piece)) return ban; + return nobody; + } + + static bool isSameColor(String p1, String p2) => of(p1) == of(p2); + + static String opponent(String color) { + if (color == white) return black; + if (color == black) return white; + return color; + } + + String operator -(String c) => opponent(c); +} + enum Phase { none, ready, placing, moving, gameOver } enum Act { none, select, place, remove } @@ -38,6 +173,18 @@ enum GameOverReason { enum PieceType { none, blackStone, whiteStone, ban, count, stone } +class Piece { + static const noPiece = PieceColor.none; + static const blackStone = PieceColor.black; + static const whiteStone = PieceColor.white; + static const ban = PieceColor.ban; + + static bool isEmpty(String c) => noPiece.contains(c); + static bool isBlack(String c) => blackStone.contains(c); + static bool isWhite(String c) => whiteStone.contains(c); + static bool isBan(String c) => ban.contains(c); +} + enum Square { SQ_0, SQ_1, @@ -96,7 +243,9 @@ enum Rank { rank_1, rank_2, rank_3, rank_4, rank_5, rank_6, rank_7, rank_8 } const rankNumber = 8; -const invalidIndex = -1; +int makeSquare(int file, int rank) { + return (file << 3) + rank - 1; +} bool isOk(int sq) { bool ret = (sq == 0 || (sq >= sqBegin && sq < sqEnd)); @@ -129,3 +278,36 @@ int toSq(int move) { int makeMove(int from, int to) { return (from << 8) + to; } + +const invalidIndex = -1; + +Map squareToIndex = { + 8: 17, + 9: 18, + 10: 25, + 11: 32, + 12: 31, + 13: 30, + 14: 23, + 15: 16, + 16: 10, + 17: 12, + 18: 26, + 19: 40, + 20: 38, + 21: 36, + 22: 22, + 23: 8, + 24: 3, + 25: 6, + 26: 27, + 27: 48, + 28: 45, + 29: 42, + 30: 21, + 31: 0 +}; + +Map indexToSquare = squareToIndex.map((k, v) => MapEntry(v, k)); + +enum GameResult { pending, win, lose, draw, none } diff --git a/src/ui/flutter_app/lib/painting/board_painter.dart b/src/ui/flutter_app/lib/painting/board_painter.dart index 7ac54e5f..4b3bc7b9 100644 --- a/src/ui/flutter_app/lib/painting/board_painter.dart +++ b/src/ui/flutter_app/lib/painting/board_painter.dart @@ -19,7 +19,6 @@ import 'package:flutter/material.dart'; import 'package:sanmill/common/config.dart'; import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/mill/mill.dart'; import 'package:sanmill/mill/types.dart'; import 'package:sanmill/style/app_theme.dart'; diff --git a/src/ui/flutter_app/lib/painting/pieces_painter.dart b/src/ui/flutter_app/lib/painting/pieces_painter.dart index 9732fd24..82d112d0 100644 --- a/src/ui/flutter_app/lib/painting/pieces_painter.dart +++ b/src/ui/flutter_app/lib/painting/pieces_painter.dart @@ -18,7 +18,6 @@ import 'package:flutter/material.dart'; import 'package:sanmill/common/config.dart'; -import 'package:sanmill/mill/mill.dart'; import 'package:sanmill/mill/position.dart'; import 'package:sanmill/mill/types.dart'; import 'package:sanmill/style/app_theme.dart'; diff --git a/src/ui/flutter_app/lib/widgets/game_page.dart b/src/ui/flutter_app/lib/widgets/game_page.dart index 12700c57..89b401fc 100644 --- a/src/ui/flutter_app/lib/widgets/game_page.dart +++ b/src/ui/flutter_app/lib/widgets/game_page.dart @@ -26,7 +26,6 @@ import 'package:sanmill/engine/native_engine.dart'; import 'package:sanmill/generated/l10n.dart'; import 'package:sanmill/main.dart'; import 'package:sanmill/mill/game.dart'; -import 'package:sanmill/mill/mill.dart'; import 'package:sanmill/mill/types.dart'; import 'package:sanmill/services/audios.dart'; import 'package:sanmill/style/app_theme.dart';