flutter: position 增加代码

This commit is contained in:
Calcitem 2020-11-08 23:31:23 +08:00
parent 76435e9507
commit 0563a41392
2 changed files with 421 additions and 9 deletions

View File

@ -23,7 +23,7 @@ enum MoveType { place, move, remove }
enum Phase { none, ready, placing, moving, gameOver }
enum Action { none, select, place, remove }
enum Act { none, select, place, remove }
enum GameOverReason {
noReason,

View File

@ -17,9 +17,12 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/cupertino.dart';
import '../common/types.dart';
import '../mill/mill.dart';
import '../mill/recorder.dart';
import '../mill/rule.dart';
class StateInfo {
/*
@ -63,7 +66,7 @@ class Position {
GameOverReason gameOverReason = GameOverReason.noReason;
Phase phase = Phase.none;
Action action = Action.none;
Act action = Act.none;
int scoreBlack = 0;
int scoreWhite = 0;
@ -72,7 +75,9 @@ class Position {
int currentSquare;
int nPlayed = 0;
//Move move;
String cmdline;
//int _move;
Position.init() {
for (var i = 0; i < _grid.length; i++) {
@ -145,6 +150,112 @@ class Position {
bool empty(int sq) => pieceOn(sq) == Piece.noPiece;
void updateScore() {}
void setSideToMove(String color) {
_sideToMove = color;
}
String movedPiece(int move) {
return pieceOn(fromSq(move));
}
bool selectPieceFR(int file, int rank) {
return selectPieceSQ(makeSquare(file, rank));
}
void putPiece(var pt, int index) {
_grid[index] = pt;
_board[indexToSquare[index]] = pt;
}
bool putPieceFR(int file, int rank) {
bool ret = putPieceSQ(makeSquare(file, rank));
if (ret) {
updateScore();
}
return ret;
}
bool movePieceFR(int file1, int rank1, int file2, int rank2) {
return movePieceSQ(makeSquare(file1, rank1), makeSquare(file2, rank2));
}
bool removePieceFR(int file, int rank) {
bool ret = removePieceSQ(makeSquare(file, rank));
if (ret) {
updateScore();
}
return ret;
}
bool selectPieceSQ(int sq) {
// TODO
return false;
}
bool putPieceSQ(int sq) {
// TODO
return false;
}
bool movePieceSQ(int fromSq, int toSq) {
// TODO
return false;
}
bool removePieceSQ(int sq) {
// TODO
return false;
}
bool movePiece(int fromSq, int toSq) {
if (selectPieceSQ(fromSq)) {
return putPieceSQ(toSq);
}
return false;
}
void set(String fenStr) {
/*
A FEN string defines a particular position using only the ASCII character set.
A FEN string contains six fields separated by a space. The fields are:
1) Piece placement. Each rank is described, starting
with rank 1 and ending with rank 8. Within each rank, the contents of each
square are described from file A through file C. Following the Standard
Algebraic Notation (SAN), each piece is identified by a single letter taken
from the standard English names. White pieces are designated using "O"
whilst Black uses "@". Blank uses "*". Banned uses "X".
noted using digits 1 through 8 (the number of blank squares), and "/"
separates ranks.
2) Active color. "w" means white moves next, "b" means black.
3) Phrase.
4) Action.
5) Black on board/Black in hand/White on board/White in hand/need to remove
6) Halfmove clock. This is the number of halfmoves since the last
capture. This is used to determine if a draw can be claimed under the
fifty-move rule.
7) Fullmove number. The number of the full move. It starts at 1, and is
incremented after Black's move.
*/
// TODO
return;
}
/// fen() returns a FEN representation of the position.
String fen() {
@ -195,13 +306,13 @@ class Position {
// Action
switch (action) {
case Action.place:
case Act.place:
ss += "p";
break;
case Action.select:
case Act.select:
ss += "s";
break;
case Action.remove:
case Act.remove:
ss += "r";
break;
default:
@ -235,11 +346,79 @@ class Position {
return ss;
}
void putPiece(var pt, int index) {
_grid[index] = pt;
_board[indexToSquare[index]] = pt;
/// Position::legal() tests whether a pseudo-legal move is legal
bool legal(int move) {
assert(isOk(move));
String us = _sideToMove;
int fromSQ = fromSq(move);
int toSQ = toSq(move);
if (fromSQ == toSQ) {
return false; // TODO: Same with is_ok(m)
}
if (phase == Phase.moving && typeOf(move) != MoveType.remove) {
if (movedPiece(move) != us) {
return false;
}
}
// TODO: Add more
return true;
}
/// Position::pseudo_legal() takes a random move and tests whether the move is
/// pseudo legal. It is used to validate moves from TT that can be corrupted
/// due to SMP concurrent access or hash position key aliasing.
bool pseudoLegal(int move) {
// TODO
return legal(move);
}
/*
/// Position::do_move() makes a move, and saves all information necessary
/// to a StateInfo object. The move is assumed to be legal. Pseudo-legal
/// moves should be filtered out before this function is called.
void doMove(int move) {
bool ret = false;
MoveType mt = typeOf(move);
switch (mt) {
case MoveType.remove:
// Reset rule 50 counter
rule50 = 0;
ret = removePiece(toSq(move));
break;
case MoveType.move:
ret = movePiece(fromSq(move), toSq(move));
break;
case MoveType.place:
ret = putPieceSQ(toSq(move));
break;
default:
break;
}
if (!ret) {
return;
}
// Increment ply counters. In particular, rule50 will be reset to zero later on
// in case of a capture.
++gamePly;
++rule50;
++pliesFromNull;
_move = move;
}
*/
String doMove(int from, int to) {
//
if (!validateMove(from, to)) return null;
@ -351,4 +530,237 @@ class Position {
get lastMove => _recorder.last;
get lastCapturedPosition => _recorder.lastCapturedPosition;
///////////////////////////////////////////////////////////////////////////////
int piecesOnBoardCount() {
pieceCountOnBoardBlack = pieceCountOnBoardWhite = 0;
for (int f = 1; f < 3 + 2; f++) {
for (int r = 0; r < 8; r++) {
int s = f * 8 + r;
if (_board[s] == Piece.blackStone) {
pieceCountOnBoardBlack++;
} else if (_board[s] == Piece.whiteStone) {
pieceCountOnBoardBlack++;
}
}
}
if (pieceCountOnBoardBlack > rule.nTotalPiecesEachSide ||
pieceCountOnBoardWhite > rule.nTotalPiecesEachSide) {
return -1;
}
return pieceCountOnBoardBlack + pieceCountOnBoardWhite;
}
int piecesInHandCount() {
pieceCountInHandBlack = rule.nTotalPiecesEachSide - pieceCountOnBoardBlack;
pieceCountInHandWhite = rule.nTotalPiecesEachSide - pieceCountOnBoardWhite;
return pieceCountOnBoardBlack + pieceCountOnBoardWhite;
}
int setPosition(Rule newRule) {
rule = newRule;
gamePly = 0;
rule50 = 0;
phase = Phase.ready;
setSideToMove(Color.black);
action = Act.place;
for (int i = 0; i < _grid.length; i++) _grid[i] = Piece.noPiece;
for (int i = 0; i < _board.length; i++) _board[i] = Piece.noPiece;
if (piecesOnBoardCount() == -1) {
return -1;
}
piecesInHandCount();
pieceCountNeedRemove = 0;
winner = Color.unknown;
currentSquare = 0;
return -1;
}
bool reset() {
gamePly = 0;
rule50 = 0;
phase = Phase.ready;
setSideToMove(Color.black);
action = Act.place;
winner = Color.unknown;
gameOverReason = GameOverReason.noReason;
for (int i = 0; i < _grid.length; i++) _grid[i] = Piece.noPiece;
for (int i = 0; i < _board.length; i++) _board[i] = Piece.noPiece;
pieceCountOnBoardBlack = pieceCountOnBoardWhite = 0;
pieceCountInHandBlack = pieceCountInHandWhite = rule.nTotalPiecesEachSide;
pieceCountNeedRemove = 0;
currentSquare = 0;
int i = 0; // TODO: rule
cmdline = "r" +
(i + 1).toString() +
" " +
"s" +
rule.maxStepsLedToDraw.toString() +
" t" +
0.toString();
return false;
}
bool start() {
gameOverReason = GameOverReason.noReason;
switch (phase) {
case Phase.placing:
case Phase.moving:
return false;
case Phase.gameOver:
reset();
continue ready;
ready:
case Phase.ready:
phase = Phase.placing;
return true;
default:
return false;
}
}
/*
bool putPiece(int sq)
{
String piece = Piece.noPiece;
String us = _sideToMove;
if (phase == Phase.gameOver ||
action != Act.place ||
sq < 0 || sq >= 31 || _board[sq] != Piece.noPiece) {
return false;
}
if (phase == Phase.ready) {
start();
}
if (phase == Phase.placing) {
piece = _sideToMove;
if (_sideToMove == Color.black) {
pieceCountInHandBlack--;
pieceCountOnBoardBlack++;
}
else if (_sideToMove == Color.white) {
pieceCountInHandWhite--;
pieceCountOnBoardWhite++;
}
_board[sq]= piece;
_grid[squareToIndex[sq]] = piece;
cmdline = "(" + fileOf(sq).toString() + "," + rankOf(sq).toString() + ")";
currentSquare = sq;
int n = addMills(currentSquare);
if (n == 0) {
assert(pieceCountInHandBlack >= 0 && pieceCountInHandWhite >= 0);
if (pieceCountInHandBlack == 0 && pieceCountInHandWhite == 0) {
if (checkGameOverCondition()) {
return true;
}
phase = Phase.moving;
action = Act.select;
if (rule.hasBannedLocations) {
removeBanStones();
}
if (!rule.isDefenderMoveFirst) {
changeSideToMove();
}
if (checkGameOverCondition()) {
return true;
}
} else {
changeSideToMove();
}
} else {
pieceCountNeedRemove = rule.allowRemoveMultiPiecesWhenCloseMultiMill ? n : 1;
action = Act.remove;
}
} else if (phase == Phase.moving) {
if (checkGameOverCondition()) {
return true;
}
// if illegal
if (pieceCountOnBoard[sideToMove] > rule->nPiecesAtLeast ||
!rule->allowFlyWhenRemainThreePieces) {
int md;
for (md = 0; md < MD_NB; md++) {
if (s == MoveList<LEGAL>::moveTable[currentSquare][md])
break;
}
// not in moveTable
if (md == MD_NB) {
return false;
}
}
if (updateCmdlist) {
sprintf(cmdline, "(%1u,%1u)->(%1u,%1u)",
file_of(currentSquare), rank_of(currentSquare),
file_of(s), rank_of(s));
st.rule50++;
}
board[s] = board[currentSquare];
board[currentSquare] = NO_PIECE;
currentSquare = s;
int n = add_mills(currentSquare);
// midgame
if (n == 0) {
action = ACTION_SELECT;
change_side_to_move();
if (check_gameover_condition()) {
return true;
}
} else {
pieceCountNeedRemove = rule->allowRemoveMultiPiecesWhenCloseMultiMill ? n : 1;
update_key_misc();
action = ACTION_REMOVE;
}
} else {
assert(0);
}
return true;
}
*/
}