flutter: refactor: Move mill.dart to types.dart

This commit is contained in:
Calcitem 2021-04-17 00:01:02 +08:00
parent 0b6d58da36
commit 210149bb60
9 changed files with 185 additions and 211 deletions

View File

@ -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';

View File

@ -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';

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
import 'types.dart';
Map<int, int> 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<int, int> 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;
}
}

View File

@ -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';

View File

@ -16,7 +16,6 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'mill.dart';
import 'position.dart';
import 'types.dart';

View File

@ -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<int, int> 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<int, int> indexToSquare = squareToIndex.map((k, v) => MapEntry(v, k));
enum GameResult { pending, win, lose, draw, none }

View File

@ -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';

View File

@ -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';

View File

@ -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';