flutter: position 增加代码
This commit is contained in:
parent
76435e9507
commit
0563a41392
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue