/*
CuckooChess - A java chess program.
Copyright (C) 2011 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.cuckoochess;
import java.util.ArrayList;
import java.util.List;
import guibase.ChessController;
import guibase.GUIInterface;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.graphics.Typeface;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.ClipboardManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import chess.ChessParseError;
import chess.Move;
import chess.Position;
import chess.TextIO;
public class CuckooChess extends Activity implements GUIInterface {
ChessBoard cb;
ChessController ctrl;
boolean mShowThinking;
int mTimeLimit;
boolean playerWhite;
static final int ttLogSize = 16; // Use 2^ttLogSize hash entries.
TextView status;
ScrollView moveListScroll;
TextView moveList;
TextView thinking;
SharedPreferences settings;
private void readPrefs() {
mShowThinking = settings.getBoolean("showThinking", false);
String timeLimitStr = settings.getString("timeLimit", "5000");
mTimeLimit = Integer.parseInt(timeLimitStr);
playerWhite = settings.getBoolean("playerWhite", true);
boolean boardFlipped = settings.getBoolean("boardFlipped", false);
cb.setFlipped(boardFlipped);
ctrl.setTimeLimit();
String fontSizeStr = settings.getString("fontSize", "12");
int fontSize = Integer.parseInt(fontSizeStr);
status.setTextSize(fontSize);
moveList.setTextSize(fontSize);
thinking.setTextSize(fontSize);
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
settings = PreferenceManager.getDefaultSharedPreferences(this);
settings.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
readPrefs();
ctrl.setHumanWhite(playerWhite);
}
});
setContentView(R.layout.main);
status = (TextView)findViewById(R.id.status);
moveListScroll = (ScrollView)findViewById(R.id.scrollView);
moveList = (TextView)findViewById(R.id.moveList);
thinking = (TextView)findViewById(R.id.thinking);
cb = (ChessBoard)findViewById(R.id.chessboard);
status.setFocusable(false);
moveListScroll.setFocusable(false);
moveList.setFocusable(false);
thinking.setFocusable(false);
ctrl = new ChessController(this);
ctrl.setThreadStackSize(32768);
readPrefs();
Typeface chessFont = Typeface.createFromAsset(getAssets(), "casefont.ttf");
cb.setFont(chessFont);
cb.setFocusable(true);
cb.requestFocus();
cb.setClickable(true);
ctrl.newGame(playerWhite, ttLogSize, false);
{
String fen = "";
String moves = "";
String numUndo = "0";
String tmp;
if (savedInstanceState != null) {
tmp = savedInstanceState.getString("startFEN");
if (tmp != null) fen = tmp;
tmp = savedInstanceState.getString("moves");
if (tmp != null) moves = tmp;
tmp = savedInstanceState.getString("numUndo");
if (tmp != null) numUndo = tmp;
} else {
tmp = settings.getString("startFEN", null);
if (tmp != null) fen = tmp;
tmp = settings.getString("moves", null);
if (tmp != null) moves = tmp;
tmp = settings.getString("numUndo", null);
if (tmp != null) numUndo = tmp;
}
List<String> posHistStr = new ArrayList<String>();
posHistStr.add(fen);
posHistStr.add(moves);
posHistStr.add(numUndo);
ctrl.setPosHistory(posHistStr);
}
ctrl.startGame();
cb.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (ctrl.humansTurn() && (event.getAction() == MotionEvent.ACTION_UP)) {
int sq = cb.eventToSquare(event);
Move m = cb.mousePressed(sq);
if (m != null) {
ctrl.humanMove(m);
}
return false;
}
return false;
}
});
cb.setOnTrackballListener(new ChessBoard.OnTrackballListener() {
public void onTrackballEvent(MotionEvent event) {
if (ctrl.humansTurn()) {
Move m = cb.handleTrackballEvent(event);
if (m != null) {
ctrl.humanMove(m);
}
}
}
});
cb.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (!ctrl.computerThinking())
showDialog(CLIPBOARD_DIALOG);
return true;
}
});
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
List<String> posHistStr = ctrl.getPosHistory();
outState.putString("startFEN", posHistStr.get(0));
outState.putString("moves", posHistStr.get(1));
outState.putString("numUndo", posHistStr.get(2));
}
@Override
protected void onPause() {
List<String> posHistStr = ctrl.getPosHistory();
Editor editor = settings.edit();
editor.putString("startFEN", posHistStr.get(0));
editor.putString("moves", posHistStr.get(1));
editor.putString("numUndo", posHistStr.get(2));
editor.commit();
super.onPause();
}
@Override
protected void onDestroy() {
ctrl.stopComputerThinking();
super.onDestroy();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.options_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_new_game:
ctrl.newGame(playerWhite, ttLogSize, false);
ctrl.startGame();
return true;
case R.id.item_undo:
ctrl.takeBackMove();
return true;
case R.id.item_redo:
ctrl.redoMove();
return true;
case R.id.item_settings:
{
Intent i = new Intent(CuckooChess.this, Preferences.class);
startActivityForResult(i, 0);
return true;
}
}
return false;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 0) {
readPrefs();
ctrl.setHumanWhite(playerWhite);
}
}
@Override
public void setPosition(Position pos) {
cb.setPosition(pos);
ctrl.setHumanWhite(playerWhite);
}
@Override
public void setSelection(int sq) {
cb.setSelection(sq);
}
@Override
public void setStatusString(String str) {
status.setText(str);
}
@Override
public void setMoveListString(String str) {
moveList.setText(str);
moveListScroll.fullScroll(ScrollView.FOCUS_DOWN);
}
@Override
public void setThinkingString(String str) {
thinking.setText(str);
}
@Override
public int timeLimit() {
return mTimeLimit;
}
@Override
public boolean randomMode() {
return mTimeLimit == -1;
}
@Override
public boolean showThinking() {
return mShowThinking;
}
static final int PROMOTE_DIALOG = 0;
static final int CLIPBOARD_DIALOG = 1;
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case PROMOTE_DIALOG: {
final CharSequence[] items = {"Queen", "Rook", "Bishop", "Knight"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Promote pawn to?");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
ctrl.reportPromotePiece(item);
}
});
AlertDialog alert = builder.create();
return alert;
}
case CLIPBOARD_DIALOG: {
final CharSequence[] items = {"Copy Game", "Copy Position", "Paste"};
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Clipboard");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
switch (item) {
case 0: {
String pgn = ctrl.getPGN();
ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(pgn);
break;
}
case 1: {
String fen = ctrl.getFEN() + "\n";
ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(fen);
break;
}
case 2: {
ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
if (clipboard.hasText()) {
String fenPgn = clipboard.getText().toString();
try {
ctrl.setFENOrPGN(fenPgn);
} catch (ChessParseError e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
break;
}
}
}
});
AlertDialog alert = builder.create();
return alert;
}
}
return null;
}
@Override
public void requestPromotePiece() {
runOnUIThread(new Runnable() {
public void run() {
showDialog(PROMOTE_DIALOG);
}
});
}
@Override
public void reportInvalidMove(Move m) {
String msg = String.format("Invalid move %s-%s", TextIO.squareToString(m.from), TextIO.squareToString(m.to));
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void runOnUIThread(Runnable runnable) {
runOnUiThread(runnable);
}
}