/*
DroidFish - An Android chess program.
Copyright (C) 2012 Peter Ă–sterlund, peterosterlund2@gmail.com
This program 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.
This program 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/>.
*/
package org.petero.droidfish;
import java.util.ArrayList;
import org.petero.droidfish.gamelogic.Move;
import org.petero.droidfish.gamelogic.MoveGen;
import org.petero.droidfish.gamelogic.Pair;
import org.petero.droidfish.gamelogic.Piece;
import org.petero.droidfish.gamelogic.Position;
import org.petero.droidfish.gamelogic.TextIO;
import org.petero.droidfish.view.ChessBoard;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.Toast;
/** Chess board widget suitable for play mode. */
public class ChessBoardPlay extends ChessBoard {
private PGNOptions pgnOptions = null;
boolean oneTouchMoves;
public ChessBoardPlay(Context context, AttributeSet attrs) {
super(context, attrs);
oneTouchMoves = false;
}
public void setPgnOptions(PGNOptions pgnOptions) {
this.pgnOptions = pgnOptions;
}
@Override
protected XYCoord sqToPix(int x, int y) {
int xPix = x0 + sqSize * (flipped ? 7 - x : x);
int yPix = y0 + sqSize * (flipped ? y : 7 - y);
return new XYCoord(xPix, yPix);
}
@Override
protected XYCoord pixToSq(int xCrd, int yCrd) {
int x = (xCrd - x0) / sqSize; if (flipped) x = 7 - x;
int y = (yCrd - y0) / sqSize; if (!flipped) y = 7 - y;
return new XYCoord(x, y);
}
@Override
protected int getWidth(int sqSize) { return sqSize * 8; }
@Override
protected int getHeight(int sqSize) { return sqSize * 8; }
@Override
protected int getSqSizeW(int width) { return (width) / 8; }
@Override
protected int getSqSizeH(int height) { return (height) / 8; }
@Override
protected int getMaxHeightPercentage() { return 75; }
@Override
protected int getMaxWidthPercentage() { return 65; }
@Override
protected void computeOrigin(int width, int height) {
x0 = (width - sqSize * 8) / 2;
Configuration config = getResources().getConfiguration();
boolean landScape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE);
y0 = landScape ? 0 : (height - sqSize * 8) / 2;
}
@Override
protected int getXFromSq(int sq) { return Position.getX(sq); }
@Override
protected int getYFromSq(int sq) { return Position.getY(sq); }
@Override
protected int minValidY() { return 0; }
@Override
protected int maxValidX() { return 7; }
@Override
protected int getSquare(int x, int y) { return Position.getSquare(x, y); }
@Override
protected void drawExtraSquares(Canvas canvas) {
}
private final boolean myColor(int piece) {
return (piece != Piece.EMPTY) && (Piece.isWhite(piece) == pos.whiteMove);
}
public Move mousePressed(int sq) {
if (sq < 0)
return null;
cursorVisible = false;
if ((selectedSquare != -1) && !userSelectedSquare)
setSelection(-1); // Remove selection of opponents last moving piece
if (!oneTouchMoves) {
int p = pos.getPiece(sq);
if (selectedSquare != -1) {
if (sq == selectedSquare) {
if (toggleSelection)
setSelection(-1);
return null;
}
if (!myColor(p)) {
Move m = new Move(selectedSquare, sq, Piece.EMPTY);
setSelection(highlightLastMove ? sq : -1);
userSelectedSquare = false;
return m;
} else
setSelection(sq);
} else {
if (myColor(p))
setSelection(sq);
}
} else {
int prevSq = userSelectedSquare ? selectedSquare : -1;
if (prevSq == sq) {
if (toggleSelection)
setSelection(-1);
return null;
}
ArrayList<Move> moves = new MoveGen().legalMoves(pos);
Move matchingMove = null;
if (prevSq >= 0)
matchingMove = matchingMove(prevSq, sq, moves).first;
boolean anyMatch = false;
if (matchingMove == null) {
Pair<Move, Boolean> match = matchingMove(-1, sq, moves);
matchingMove = match.first;
anyMatch = match.second;
}
if (matchingMove != null) {
setSelection(highlightLastMove ? matchingMove.to : -1);
userSelectedSquare = false;
return matchingMove;
}
if (!anyMatch && (sq >= 0)) {
int p = pos.getPiece(sq);
if (myColor(p)) {
String msg = getContext().getString(R.string.piece_can_not_be_moved);
int pieceType = (pgnOptions == null) ? PGNOptions.PT_LOCAL
: pgnOptions.view.pieceType;
msg += ": " + TextIO.pieceAndSquareToString(pieceType, p, sq);
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
}
}
setSelection(anyMatch ? sq : -1);
}
return null;
}
/**
* Determine if there is a unique legal move corresponding to one or two selected squares.
* @param sq1 First square, or -1.
* @param sq2 Second square.
* @param moves List of legal moves.
* @return Matching move if unique.
* Boolean indicating if there was at least one match.
*/
private final Pair<Move, Boolean> matchingMove(int sq1, int sq2, ArrayList<Move> moves) {
Move matchingMove = null;
boolean anyMatch = false;
for (Move m : moves) {
boolean match;
if (sq1 == -1)
match = (m.from == sq2) || (m.to == sq2);
else
match = (m.from == sq1) && (m.to == sq2) ||
(m.from == sq2) && (m.to == sq1);
if (match) {
if (matchingMove == null) {
matchingMove = m;
anyMatch = true;
} else {
if ((matchingMove.from == m.from) &&
(matchingMove.to == m.to)) {
matchingMove.promoteTo = Piece.EMPTY;
} else {
matchingMove = null;
break;
}
}
}
}
return new Pair<Move, Boolean>(matchingMove, anyMatch);
}
}