Moved CuckooChess project to trunk/

This commit is contained in:
Peter Osterlund 2011-11-12 19:43:59 +00:00
parent f2946fe6c7
commit 0461be164f
16 changed files with 2187 additions and 0 deletions

9
CuckooChess/.classpath Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="test"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
<classpathentry kind="src" path="/CuckooChessEngine"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ant.AntBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.ant.ui.ATTR_TARGETS_UPDATED" value="true"/>
<booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
<booleanAttribute key="org.eclipse.ant.uiSET_INPUTHANDLER" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/CuckooChess/build_jar.xml"/>
</listAttribute>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
<listEntry value="1"/>
</listAttribute>
<booleanAttribute key="org.eclipse.debug.core.capture_output" value="false"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_CONSOLE_OUTPUT_ON" value="false"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="CuckooChess"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;launchConfigurationWorkingSet editPageId=&quot;org.eclipse.ui.resourceWorkingSetPage&quot; factoryID=&quot;org.eclipse.ui.internal.WorkingSetFactory&quot; id=&quot;1277013474529_4&quot; label=&quot;workingSet&quot; name=&quot;workingSet&quot;&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/CuckooChess/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/CuckooChessEngine&quot; type=&quot;4&quot;/&gt;&#10;&lt;/launchConfigurationWorkingSet&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/CuckooChess/build_jar.xml}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/CuckooChess}"/>
</launchConfiguration>

28
CuckooChess/.project Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>CuckooChess</name>
<comment></comment>
<projects>
<project>CuckooChessEngine</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/jar_builder.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,12 @@
#Sat May 08 15:39:56 CEST 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View File

@ -0,0 +1,3 @@
#Sun May 09 18:44:06 CEST 2010
eclipse.preferences.version=1
org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false

33
CuckooChess/build_jar.xml Normal file
View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project CuckooChess">
<!--this file was created by Eclipse Runnable JAR Export Wizard-->
<!--ANT 1.7 is required -->
<target name="create_run_jar">
<jar destfile="deploy/CuckooChess.jar"
filesetmanifest="skip"
update="false" duplicate="fail">
<manifest>
<attribute name="Main-Class" value="tui.Main"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="../CuckooChessEngine/bin">
<include name="**/*"/>
<exclude name="**/*Test.class"/>
</fileset>
<fileset dir="../CuckooChessEngine">
<include name="src/**/*.java"/>
<include name="test/**/*.java"/>
</fileset>
<fileset dir="bin">
<include name="**/*"/>
<exclude name="**/*Test.class"/>
</fileset>
<fileset dir=".">
<include name="src/**/*.java"/>
<include name="test/**/*.java"/>
</fileset>
</jar>
</target>
</project>

View File

@ -0,0 +1,309 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JAppletFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="PlayerColor">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="MainPanel" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="MainPanel" alignment="1" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="MainPanel">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="ChessBoardPanel" pref="502" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jPanel1" alignment="0" max="32767" attributes="0"/>
<Component id="ChessBoardPanel" alignment="0" pref="502" max="32767" attributes="1"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="ChessBoardPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.LineBorderInfo">
<LineBorder/>
</Border>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[500, 500]"/>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ChessBoard" alignment="0" pref="500" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ChessBoard" alignment="0" pref="500" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="ChessBoard">
<Events>
<EventHandler event="mousePressed" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="ChessBoardMousePressed"/>
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="ChessBoardMouseReleased"/>
<EventHandler event="mouseDragged" listener="java.awt.event.MouseMotionListener" parameters="java.awt.event.MouseEvent" handler="ChessBoardMouseDragged"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ChessBoardPainter()"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="319" max="32767" attributes="1"/>
<Component id="StatusLine" alignment="0" pref="319" max="32767" attributes="1"/>
<Group type="103" alignment="0" groupAlignment="0" max="-2" attributes="0">
<Group type="102" alignment="0" attributes="1">
<Component id="NewGame" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="Backward" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="Forward" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="SettingsPanel" alignment="0" max="32767" attributes="1"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="SettingsPanel" min="-2" max="-2" attributes="1"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="NewGame" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="Forward" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="Backward" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="283" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="StatusLine" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="NewGame">
<Properties>
<Property name="text" type="java.lang.String" value="New Game"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="NewGameActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JPanel" name="SettingsPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="Settings"/>
</Border>
</Property>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ShowThinking" alignment="0" min="-2" pref="157" max="-2" attributes="1"/>
<Group type="102" alignment="0" attributes="0">
<Component id="PlayerWhite" min="-2" max="-2" attributes="1"/>
<EmptySpace pref="104" max="32767" attributes="0"/>
<Component id="FlipBoard" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="TimeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="TimeSlider" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="PlayerBlack" alignment="0" min="-2" max="-2" attributes="1"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="3" attributes="0">
<Component id="PlayerWhite" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="FlipBoard" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="PlayerBlack" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="TimeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="TimeSlider" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="ShowThinking" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JRadioButton" name="PlayerWhite">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="PlayerColor"/>
</Property>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" value="Play White"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="PlayerBlack">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="PlayerColor"/>
</Property>
<Property name="text" type="java.lang.String" value="Play Black"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="TimeLabel">
<Properties>
<Property name="text" type="java.lang.String" value="Thinking Time"/>
</Properties>
</Component>
<Component class="javax.swing.JSlider" name="TimeSlider">
<Properties>
<Property name="majorTickSpacing" type="int" value="15"/>
<Property name="maximum" type="int" value="60"/>
<Property name="minorTickSpacing" type="int" value="5"/>
<Property name="paintLabels" type="boolean" value="true"/>
<Property name="paintTicks" type="boolean" value="true"/>
<Property name="value" type="int" value="10"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="TimeSliderStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="ShowThinking">
<Properties>
<Property name="text" type="java.lang.String" value="Show Thinking"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="ShowThinkingStateChanged"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="FlipBoard">
<Properties>
<Property name="text" type="java.lang.String" value="Flip Board"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="FlipBoardStateChanged"/>
</Events>
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="LogTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="verifyInputWhenFocusTarget" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JTextField" name="StatusLine">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="Forward">
<Properties>
<Property name="text" type="java.lang.String" value="-&gt;"/>
<Property name="defaultCapable" type="boolean" value="false"/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="ForwardActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="Backward">
<Properties>
<Property name="text" type="java.lang.String" value="&lt;-"/>
<Property name="defaultCapable" type="boolean" value="false"/>
<Property name="focusPainted" type="boolean" value="false"/>
<Property name="focusable" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="BackwardActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,440 @@
/*
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 gui;
import guibase.ChessController;
import guibase.GUIInterface;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import chess.ComputerPlayer;
import chess.Move;
import chess.Position;
/**
* The main class for the chess GUI.
* @author petero
*/
public class AppletGUI extends javax.swing.JApplet implements GUIInterface {
private static final long serialVersionUID = 7357610346389734323L;
ChessBoardPainter cbp;
ChessController ctrl;
final static int ttLogSize = 19; // Use 2^19 hash entries.
String moveListStr = "";
String thinkingStr = "";
/** Initializes the applet AppletGUI */
@Override
public void init() {
ctrl = new ChessController(this);
try {
java.awt.EventQueue.invokeAndWait(new Runnable() {
public void run() {
initComponents();
cbp = (ChessBoardPainter)ChessBoard;
ctrl.newGame(PlayerWhite.isSelected(), ttLogSize, true);
ctrl.startGame();
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Entry point for the GUI version of the chess program.
*/
public static void main(String[] args) {
javax.swing.JApplet theApplet = new AppletGUI();
theApplet.init();
javax.swing.JFrame window = new javax.swing.JFrame(ComputerPlayer.engineName);
window.setContentPane(theApplet);
window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
}
/** This method is called from within the init() method to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
private void initComponents() {
PlayerColor = new javax.swing.ButtonGroup();
MainPanel = new javax.swing.JPanel();
ChessBoardPanel = new javax.swing.JPanel();
ChessBoard = new ChessBoardPainter();
jPanel1 = new javax.swing.JPanel();
NewGame = new javax.swing.JButton();
SettingsPanel = new javax.swing.JPanel();
PlayerWhite = new javax.swing.JRadioButton();
PlayerBlack = new javax.swing.JRadioButton();
TimeLabel = new javax.swing.JLabel();
TimeSlider = new javax.swing.JSlider();
ShowThinking = new javax.swing.JCheckBox();
FlipBoard = new javax.swing.JCheckBox();
jScrollPane1 = new javax.swing.JScrollPane();
LogTextArea = new javax.swing.JTextPane();
StatusLine = new javax.swing.JTextField();
Forward = new javax.swing.JButton();
Backward = new javax.swing.JButton();
ChessBoardPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
ChessBoardPanel.setPreferredSize(new java.awt.Dimension(500, 500));
ChessBoard.addMouseListener(new java.awt.event.MouseAdapter() {
public void mousePressed(java.awt.event.MouseEvent evt) {
ChessBoardMousePressed(evt);
}
public void mouseReleased(java.awt.event.MouseEvent evt) {
ChessBoardMouseReleased(evt);
}
});
ChessBoard.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
public void mouseDragged(java.awt.event.MouseEvent evt) {
ChessBoardMouseDragged(evt);
}
});
javax.swing.GroupLayout ChessBoardPanelLayout = new javax.swing.GroupLayout(ChessBoardPanel);
ChessBoardPanel.setLayout(ChessBoardPanelLayout);
ChessBoardPanelLayout.setHorizontalGroup(
ChessBoardPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ChessBoard, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
);
ChessBoardPanelLayout.setVerticalGroup(
ChessBoardPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ChessBoard, javax.swing.GroupLayout.DEFAULT_SIZE, 500, Short.MAX_VALUE)
);
jPanel1.setFocusable(false);
NewGame.setText("New Game");
NewGame.setFocusable(false);
NewGame.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
NewGameActionPerformed(evt);
}
});
SettingsPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Settings"));
SettingsPanel.setFocusable(false);
PlayerColor.add(PlayerWhite);
PlayerWhite.setSelected(true);
PlayerWhite.setText("Play White");
PlayerWhite.setFocusable(false);
PlayerColor.add(PlayerBlack);
PlayerBlack.setText("Play Black");
PlayerBlack.setFocusable(false);
TimeLabel.setText("Thinking Time");
TimeSlider.setMajorTickSpacing(15);
TimeSlider.setMaximum(60);
TimeSlider.setMinorTickSpacing(5);
TimeSlider.setPaintLabels(true);
TimeSlider.setPaintTicks(true);
TimeSlider.setValue(5);
TimeSlider.setFocusable(false);
TimeSlider.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
TimeSliderStateChanged(evt);
}
});
ShowThinking.setText("Show Thinking");
ShowThinking.setFocusable(false);
ShowThinking.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
ShowThinkingStateChanged(evt);
}
});
FlipBoard.setText("Flip Board");
FlipBoard.setFocusable(false);
FlipBoard.addChangeListener(new javax.swing.event.ChangeListener() {
public void stateChanged(javax.swing.event.ChangeEvent evt) {
FlipBoardStateChanged(evt);
}
});
javax.swing.GroupLayout SettingsPanelLayout = new javax.swing.GroupLayout(SettingsPanel);
SettingsPanel.setLayout(SettingsPanelLayout);
SettingsPanelLayout.setHorizontalGroup(
SettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ShowThinking, javax.swing.GroupLayout.PREFERRED_SIZE, 157, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(SettingsPanelLayout.createSequentialGroup()
.addComponent(PlayerWhite)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE)
.addComponent(FlipBoard)
.addContainerGap())
.addGroup(SettingsPanelLayout.createSequentialGroup()
.addComponent(TimeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(TimeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(PlayerBlack)
);
SettingsPanelLayout.setVerticalGroup(
SettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(SettingsPanelLayout.createSequentialGroup()
.addGroup(SettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(PlayerWhite)
.addComponent(FlipBoard))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(PlayerBlack)
.addGap(18, 18, 18)
.addGroup(SettingsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(TimeLabel)
.addComponent(TimeSlider, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ShowThinking)
.addContainerGap())
);
LogTextArea.setEditable(false);
LogTextArea.setVerifyInputWhenFocusTarget(false);
jScrollPane1.setViewportView(LogTextArea);
StatusLine.setEditable(false);
StatusLine.setFocusable(false);
Forward.setText("->");
Forward.setDefaultCapable(false);
Forward.setFocusPainted(false);
Forward.setFocusable(false);
Forward.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
ForwardActionPerformed(evt);
}
});
Backward.setText("<-");
Backward.setDefaultCapable(false);
Backward.setFocusPainted(false);
Backward.setFocusable(false);
Backward.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
BackwardActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 319, Short.MAX_VALUE)
.addComponent(StatusLine, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 319, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(NewGame)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(Backward)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(Forward))
.addComponent(SettingsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(SettingsPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(NewGame)
.addComponent(Forward)
.addComponent(Backward))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 283, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(StatusLine, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
javax.swing.GroupLayout MainPanelLayout = new javax.swing.GroupLayout(MainPanel);
MainPanel.setLayout(MainPanelLayout);
MainPanelLayout.setHorizontalGroup(
MainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(MainPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(ChessBoardPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 502, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
MainPanelLayout.setVerticalGroup(
MainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, MainPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(MainPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(ChessBoardPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 502, Short.MAX_VALUE))
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(MainPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(MainPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
private void ChessBoardMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ChessBoardMousePressed
if (ctrl.humansTurn()) {
int sq = cbp.eventToSquare(evt);
Move m = cbp.mousePressed(sq);
if (m != null) {
ctrl.humanMove(m);
}
}
}//GEN-LAST:event_ChessBoardMousePressed
private void FlipBoardStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_FlipBoardStateChanged
cbp.setFlipped(FlipBoard.isSelected());
}//GEN-LAST:event_FlipBoardStateChanged
private void NewGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_NewGameActionPerformed
ctrl.newGame(PlayerWhite.isSelected(), ttLogSize, true);
ctrl.startGame();
}//GEN-LAST:event_NewGameActionPerformed
private void ShowThinkingStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_ShowThinkingStateChanged
ctrl.setMoveList();
}//GEN-LAST:event_ShowThinkingStateChanged
private void BackwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_BackwardActionPerformed
ctrl.takeBackMove();
}//GEN-LAST:event_BackwardActionPerformed
private void ForwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ForwardActionPerformed
ctrl.redoMove();
}//GEN-LAST:event_ForwardActionPerformed
private void TimeSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_TimeSliderStateChanged
ctrl.setTimeLimit();
}//GEN-LAST:event_TimeSliderStateChanged
private void ChessBoardMouseDragged(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ChessBoardMouseDragged
if (ctrl.humansTurn()) {
cbp.mouseDragged(evt);
}
}//GEN-LAST:event_ChessBoardMouseDragged
private void ChessBoardMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_ChessBoardMouseReleased
if (ctrl.humansTurn()) {
int sq = cbp.eventToSquare(evt);
Move m = cbp.mouseReleased(sq);
if (m != null) {
ctrl.humanMove(m);
}
}
}//GEN-LAST:event_ChessBoardMouseReleased
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton Backward;
private javax.swing.JLabel ChessBoard;
private javax.swing.JPanel ChessBoardPanel;
private javax.swing.JCheckBox FlipBoard;
private javax.swing.JButton Forward;
private javax.swing.JTextPane LogTextArea;
private javax.swing.JPanel MainPanel;
private javax.swing.JButton NewGame;
private javax.swing.JRadioButton PlayerBlack;
private javax.swing.ButtonGroup PlayerColor;
private javax.swing.JRadioButton PlayerWhite;
private javax.swing.JPanel SettingsPanel;
private javax.swing.JCheckBox ShowThinking;
private javax.swing.JTextField StatusLine;
private javax.swing.JLabel TimeLabel;
private javax.swing.JSlider TimeSlider;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
// End of variables declaration//GEN-END:variables
public void setPosition(Position pos) {
cbp.setPosition(pos);
}
public void setSelection(int sq) {
cbp.setSelection(sq);
}
public void setStatusString(String str) {
StatusLine.setText(str);
}
public void setMoveListString(String str) {
moveListStr = str;
str = moveListStr + "\n" + thinkingStr;
if (!str.equals(LogTextArea.getText())) {
LogTextArea.setText(str);
}
}
public void setThinkingString(String str) {
thinkingStr = str;
str = moveListStr + "\n" + thinkingStr;
if (!str.equals(LogTextArea.getText())) {
LogTextArea.setText(str);
}
}
public final int timeLimit() {
return Math.max(25, TimeSlider.getValue() * 1000);
}
public final boolean showThinking() {
return ShowThinking.isSelected();
}
public void requestPromotePiece() {
runOnUIThread(new Runnable() {
public void run() {
Object[] options = { "Queen", "Rook", "Bishop", "Knight" };
int choice = JOptionPane.showOptionDialog(
cbp, "Promote pawn to?", "Pawn Promotion",
0, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
ctrl.reportPromotePiece(choice);
}
});
}
public void runOnUIThread(Runnable runnable) {
SwingUtilities.invokeLater(runnable);
}
@Override
public boolean randomMode() {
return false;
}
@Override
public void reportInvalidMove(Move m) {
}
}

View File

@ -0,0 +1,292 @@
/*
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 gui;
import chess.Move;
import chess.Piece;
import chess.Position;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.InputStream;
import javax.swing.JLabel;
/**
* Draws a graphical chess board. Also handles user interaction.
* @author petero
*/
public class ChessBoardPainter extends JLabel {
private static final long serialVersionUID = -1319250011487017825L;
private Position pos;
private int selectedSquare;
private int x0, y0, sqSize;
private boolean flipped;
private Font chessFont;
// For piece animation during dragging
private int activeSquare;
private boolean dragging;
private int dragX;
private int dragY;
private boolean cancelSelection;
ChessBoardPainter() {
pos = new Position();
selectedSquare = -1;
x0 = y0 = sqSize = 0;
flipped = false;
activeSquare = -1;
}
/**
* Set the board to a given state.
* @param pos
*/
final public void setPosition(Position pos) {
this.pos = pos;
repaint();
}
/**
* Set/clear the board flipped status.
* @param flipped
*/
final public void setFlipped(boolean flipped) {
this.flipped = flipped;
repaint();
}
/**
* Set/clear the selected square.
* @param square The square to select, or -1 to clear selection.
*/
final public void setSelection(int square) {
if (square != this.selectedSquare) {
this.selectedSquare = square;
repaint();
}
}
@Override
public void paint(Graphics g0) {
Graphics2D g = (Graphics2D)g0;
Dimension size = getSize();
sqSize = (Math.min(size.width, size.height) - 4) / 8;
x0 = (size.width - sqSize * 8) / 2;
y0 = (size.height - sqSize * 8) / 2;
boolean doDrag = (activeSquare >= 0) && dragging;
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
final int xCrd = getXCrd(x);
final int yCrd = getYCrd(y);
g.setColor(Position.darkSquare(x, y) ? Color.GRAY : new Color(190, 190, 90));
g.fillRect(xCrd, yCrd, sqSize, sqSize);
int sq = Position.getSquare(x, y);
int p = pos.getPiece(sq);
if (doDrag && (sq == activeSquare)) {
// Skip this piece. It will be drawn later at (dragX,dragY)
} else {
drawPiece(g, xCrd + sqSize / 2, yCrd + sqSize / 2, p);
}
}
}
if (selectedSquare >= 0) {
int selX = Position.getX(selectedSquare);
int selY = Position.getY(selectedSquare);
g.setColor(Color.RED);
g.setStroke(new BasicStroke(3));
g.drawRect(getXCrd(selX), getYCrd(selY), sqSize, sqSize);
}
if (doDrag) {
int p = pos.getPiece(activeSquare);
drawPiece(g, dragX, dragY, p);
}
}
private final void drawPiece(Graphics2D g, int xCrd, int yCrd, int p) {
g.setColor(Piece.isWhite(p) ? Color.WHITE : Color.BLACK);
String ps;
switch (p) {
case Piece.EMPTY:
ps = "";
break;
case Piece.WKING:
ps = "k";
break;
case Piece.WQUEEN:
ps = "q";
break;
case Piece.WROOK:
ps = "r";
break;
case Piece.WBISHOP:
ps = "b";
break;
case Piece.WKNIGHT:
ps = "n";
break;
case Piece.WPAWN:
ps = "p";
break;
case Piece.BKING:
ps = "l";
break;
case Piece.BQUEEN:
ps = "w";
break;
case Piece.BROOK:
ps = "t";
break;
case Piece.BBISHOP:
ps = "v";
break;
case Piece.BKNIGHT:
ps = "m";
break;
case Piece.BPAWN:
ps = "o";
break;
default:
ps = "?";
break;
}
if (ps.length() > 0) {
FontRenderContext frc = g.getFontRenderContext();
if ((chessFont == null) || (chessFont.getSize() != sqSize)) {
InputStream inStream = getClass().getResourceAsStream("/gui/casefont.ttf");
try {
Font font = Font.createFont(Font.TRUETYPE_FONT, inStream);
chessFont = font.deriveFont((float)sqSize);
} catch (FontFormatException ex) {
throw new RuntimeException();
} catch (IOException ex) {
throw new RuntimeException();
}
}
g.setFont(chessFont);
Rectangle2D textRect = g.getFont().getStringBounds(ps, frc);
int xCent = (int)textRect.getCenterX();
int yCent = (int)textRect.getCenterY();
g.drawString(ps, xCrd - xCent, yCrd - yCent);
}
}
private final int getXCrd(int x) {
return x0 + sqSize * (flipped ? 7 - x : x);
}
private final int getYCrd(int y) {
return y0 + sqSize * (flipped ? y : (7 - y));
}
/**
* Compute the square corresponding to the coordinates of a mouse event.
* @param evt Details about the mouse event.
* @return The square corresponding to the mouse event, or -1 if outside board.
*/
final int eventToSquare(MouseEvent evt) {
int xCrd = evt.getX();
int yCrd = evt.getY();
int sq = -1;
if ((xCrd >= x0) && (yCrd >= y0) && (sqSize > 0)) {
int x = (xCrd - x0) / sqSize;
int y = 7 - (yCrd - y0) / sqSize;
if ((x >= 0) && (x < 8) && (y >= 0) && (y < 8)) {
if (flipped) {
x = 7 - x;
y = 7 - y;
}
sq = Position.getSquare(x, y);
}
}
return sq;
}
final Move mousePressed(int sq) {
Move m = null;
cancelSelection = false;
int p = pos.getPiece(sq);
if ((selectedSquare >= 0) && (sq == selectedSquare)) {
int fromPiece = pos.getPiece(selectedSquare);
if ((fromPiece == Piece.EMPTY) || (Piece.isWhite(fromPiece) != pos.whiteMove)) {
return m; // Can't move the piece the oppenent just moved.
}
}
if ((selectedSquare < 0) &&
((p == Piece.EMPTY) || (Piece.isWhite(p) != pos.whiteMove))) {
return m; // You must click on one of your own pieces.
}
activeSquare = sq;
dragging = false;
dragX = dragY = -1;
if (selectedSquare >= 0) {
if (sq == selectedSquare) {
cancelSelection = true;
} else {
if ((p == Piece.EMPTY) || (Piece.isWhite(p) != pos.whiteMove)) {
m = new Move(selectedSquare, sq, Piece.EMPTY);
activeSquare = -1;
setSelection(sq);
}
}
}
if (m == null) {
setSelection(-1);
}
return m;
}
final void mouseDragged(MouseEvent evt) {
final int xCrd = evt.getX();
final int yCrd = evt.getY();
if (!dragging || (dragX != xCrd) || (dragY != yCrd)) {
dragging = true;
dragX = xCrd;
dragY = yCrd;
repaint();
}
}
final Move mouseReleased(int sq) {
Move m = null;
if (activeSquare >= 0) {
if (sq != activeSquare) {
m = new Move(activeSquare, sq, Piece.EMPTY);
setSelection(sq);
} else if (!cancelSelection) {
setSelection(sq);
}
activeSquare = -1;
repaint();
}
return m;
}
}

Binary file not shown.

View File

@ -0,0 +1,52 @@
/*
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 tui;
import java.io.IOException;
import chess.ComputerPlayer;
import chess.HumanPlayer;
import chess.Player;
import chess.TreeLogger;
/**
*
* @author petero
*/
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) throws IOException {
if ((args.length == 1) && args[0].equals("gui")) {
gui.AppletGUI.main(args);
} else if ((args.length == 1) && args[0].equals("txt")) {
Player whitePlayer = new HumanPlayer();
ComputerPlayer blackPlayer = new ComputerPlayer();
blackPlayer.setTTLogSize(21);
TUIGame game = new TUIGame(whitePlayer, blackPlayer);
game.play();
} else if ((args.length == 2) && args[0].equals("tree")) {
TreeLogger.main(new String[]{args[1]});
} else {
uci.UCIProtocol.main(false);
}
}
}

View File

@ -0,0 +1,216 @@
/*
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 tui;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import uci.UCIProtocol;
import chess.ChessParseError;
import chess.ComputerPlayer;
import chess.Evaluate;
import chess.Game;
import chess.Move;
import chess.Player;
import chess.Position;
import chess.TextIO;
import chess.TwoReturnValues;
public class TUIGame extends Game {
public TUIGame(Player whitePlayer, Player blackPlayer) {
super(whitePlayer, blackPlayer);
}
protected boolean handleCommand(String moveStr) {
if (super.handleCommand(moveStr))
return true;
if (moveStr.startsWith("testsuite ")) {
String testSuiteCmd = moveStr.substring(moveStr.indexOf(" ") + 1);
return handleTestSuite(testSuiteCmd);
} else if (moveStr.equals("uci")) {
whitePlayer = null;
blackPlayer = null;
UCIProtocol.main(true);
System.exit(0);
return false;
} else if (moveStr.equals("help")) {
showHelp();
return true;
}
return false;
}
private void showHelp() {
System.out.println("Enter a move, or one of the following special commands:");
System.out.println(" new - Start a new game");
System.out.println(" undo - Undo last half-move");
System.out.println(" redo - Redo next half-move");
System.out.println(" swap - Swap sides");
System.out.println(" go - Same as swap");
System.out.println(" list - List all moves in current game");
System.out.println(" setpos FEN - Set a position using a FEN string");
System.out.println(" getpos - Print current position in FEN notation");
System.out.println(" draw rep [move] - Claim draw by repetition");
System.out.println(" draw 50 [move] - Claim draw by 50-move rule");
System.out.println(" draw offer move - Play move and offer draw");
System.out.println(" draw accept - Accept a draw offer");
System.out.println(" resign - Resign the current game");
System.out.println(" testsuite filename maxtime");
System.out.println(" book on|off - Turn opening book on/off");
System.out.println(" time t - Set computer thinking time, ms");
System.out.println(" perft d - Run perft test to depth d");
System.out.println(" uci - Switch to uci protocol.");
System.out.println(" help - Show this help");
System.out.println(" quit - Terminate program");
}
private boolean handleTestSuite(String cmd) {
LineNumberReader fr = null;
try {
int idx = cmd.indexOf(" ");
String filename = cmd.substring(0, idx);
String timeStr = cmd.substring(idx + 1, cmd.length());
int timeLimit = Integer.parseInt(timeStr);
// System.out.printf("file:%s time:%s (%d)\n", filename, timeStr, timeLimit);
fr = new LineNumberReader(new FileReader(filename));
String line;
Player pl = whitePlayer.isHumanPlayer() ? blackPlayer : whitePlayer;
if (pl.isHumanPlayer()) {
System.out.printf("No computer player available");
return false;
}
ComputerPlayer cp = (ComputerPlayer)pl;
int numRight = 0;
int numTotal = 0;
while ((line = fr.readLine()) != null) {
if (line.startsWith("#") || (line.length() == 0)) {
continue;
}
int idx1 = line.indexOf(" bm ");
String fen = line.substring(0, idx1);
int idx2 = line.indexOf(";", idx1);
String bm = line.substring(idx1 + 4, idx2);
// System.out.printf("Line %3d: fen:%s bm:%s\n", fr.getLineNumber(), fen, bm);
Position testPos = TextIO.readFEN(fen);
cp.clearTT();
TwoReturnValues<Move, String> ret = cp.searchPosition(testPos, timeLimit);
Move sm = ret.first;
String PV = ret.second;
Move m = new Move(sm);
String[] answers = bm.split(" ");
boolean correct = false;
for (String a : answers) {
Move am = TextIO.stringToMove(testPos, a);
if (am == null) {
throw new ChessParseError("Invalid move " + a);
}
if (am.equals(m)) {
correct = true;
break;
}
}
if (correct) {
numRight++;
}
numTotal++;
System.out.printf("%3d : %6s %6d %d %03d/%03d %s : %s\n", fr.getLineNumber(),
TextIO.moveToString(testPos, sm, false), sm.score, correct ? 1 : 0,
numRight, numTotal, bm, PV);
}
fr.close();
} catch (NumberFormatException nfe) {
System.out.printf("Number format exception: %s\n", nfe.getMessage());
return false;
} catch (FileNotFoundException fnfe) {
System.out.printf("File not found: %s\n", fnfe.getMessage());
return false;
} catch (IOException ex) {
System.out.printf("IO error: %s\n", ex.getMessage());
} catch (ChessParseError cpe) {
int lineNo = (fr == null) ? -1 : fr.getLineNumber();
System.out.printf("Parse error, line %d: %s\n", lineNo, cpe.getMessage());
} catch (StringIndexOutOfBoundsException e) {
int lineNo = (fr == null) ? -1 : fr.getLineNumber();
System.out.printf("Parse error, line %d: %s\n", lineNo, e.getMessage());
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException ex) {
// Stupid FileReader class forces me to catch this meaningless exception
}
}
}
return true;
}
/**
* Administrate a game between two players, human or computer.
*/
public void play() throws IOException {
handleCommand("new");
while (true) {
// Print last move
if (currentMove > 0) {
Position prevPos = new Position(pos);
prevPos.unMakeMove(moveList.get(currentMove - 1), uiInfoList.get(currentMove - 1));
String moveStr= TextIO.moveToString(prevPos, moveList.get(currentMove - 1), false);
if (haveDrawOffer()) {
moveStr += " (offer draw)";
}
String msg = String.format("Last move: %d%s %s",
prevPos.fullMoveCounter, prevPos.whiteMove ? "." : "...",
moveStr);
System.out.println(msg);
}
// System.out.printf("Hash: %016x\n", pos.zobristHash());
{
Evaluate eval = new Evaluate();
int evScore = eval.evalPos(pos) * (pos.whiteMove ? 1 : -1);
System.out.printf("Eval: %.2f%n", evScore / 100.0);
}
// Check game state
System.out.print(TextIO.asciiBoard(pos));
String stateStr = getGameStateString();
if (stateStr.length() > 0) {
System.out.printf("%s%n", stateStr);
}
if (getGameState() != GameState.ALIVE) {
activateHumanPlayer();
}
// Get command from current player and act on it
Player pl = pos.whiteMove ? whitePlayer : blackPlayer;
String moveStr = pl.getCommand(new Position(pos), haveDrawOffer(), getHistory());
if (moveStr.equals("quit")) {
return;
} else {
boolean ok = processString(moveStr);
if (!ok) {
System.out.printf("Invalid move: %s\n", moveStr);
}
}
}
}
}

View File

@ -0,0 +1,435 @@
/*
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 uci;
import chess.Book;
import chess.ComputerPlayer;
import chess.Move;
import chess.MoveGen;
import chess.Parameters;
import chess.Piece;
import chess.Position;
import chess.Search;
import chess.TextIO;
import chess.TranspositionTable;
import chess.Parameters.CheckParam;
import chess.Parameters.ComboParam;
import chess.Parameters.ParamBase;
import chess.Parameters.SpinParam;
import chess.Parameters.StringParam;
import chess.TranspositionTable.TTEntry;
import chess.UndoInfo;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* Control the search thread.
* @author petero
*/
public class EngineControl {
PrintStream os;
Thread engineThread;
private final Object threadMutex;
Search sc;
TranspositionTable tt;
MoveGen moveGen;
Position pos;
long[] posHashList;
int posHashListSize;
boolean ponder; // True if currently doing pondering
boolean onePossibleMove;
boolean infinite;
int minTimeLimit;
int maxTimeLimit;
int maxDepth;
int maxNodes;
List<Move> searchMoves;
// Options
int hashSizeMB = 16;
boolean ownBook = false;
boolean analyseMode = false;
boolean ponderMode = true;
// Reduced strength variables
int strength = 1000;
long randomSeed = 0;
/**
* This class is responsible for sending "info" strings during search.
*/
private static class SearchListener implements Search.Listener {
PrintStream os;
SearchListener(PrintStream os) {
this.os = os;
}
public void notifyDepth(int depth) {
os.printf("info depth %d%n", depth);
}
public void notifyCurrMove(Move m, int moveNr) {
os.printf("info currmove %s currmovenumber %d%n", moveToString(m), moveNr);
}
public void notifyPV(int depth, int score, int time, int nodes, int nps, boolean isMate,
boolean upperBound, boolean lowerBound, ArrayList<Move> pv) {
StringBuilder pvBuf = new StringBuilder();
for (Move m : pv) {
pvBuf.append(" ");
pvBuf.append(moveToString(m));
}
String bound = "";
if (upperBound) {
bound = " upperbound";
} else if (lowerBound) {
bound = " lowerbound";
}
os.printf("info depth %d score %s %d%s time %d nodes %d nps %d pv%s%n",
depth, isMate ? "mate" : "cp", score, bound, time, nodes, nps, pvBuf.toString());
}
public void notifyStats(int nodes, int nps, int time) {
os.printf("info nodes %d nps %d time %d%n", nodes, nps, time);
}
}
public EngineControl(PrintStream os) {
this.os = os;
threadMutex = new Object();
setupTT();
moveGen = new MoveGen();
}
final public void startSearch(Position pos, ArrayList<Move> moves, SearchParams sPar) {
setupPosition(new Position(pos), moves);
computeTimeLimit(sPar);
ponder = false;
infinite = (maxTimeLimit < 0) && (maxDepth < 0) && (maxNodes < 0);
startThread(minTimeLimit, maxTimeLimit, maxDepth, maxNodes);
searchMoves = sPar.searchMoves;
}
final public void startPonder(Position pos, List<Move> moves, SearchParams sPar) {
setupPosition(new Position(pos), moves);
computeTimeLimit(sPar);
ponder = true;
infinite = false;
startThread(-1, -1, -1, -1);
}
final public void ponderHit() {
Search mySearch;
synchronized (threadMutex) {
mySearch = sc;
}
if (mySearch != null) {
if (onePossibleMove) {
if (minTimeLimit > 1) minTimeLimit = 1;
if (maxTimeLimit > 1) maxTimeLimit = 1;
}
mySearch.timeLimit(minTimeLimit, maxTimeLimit);
}
infinite = (maxTimeLimit < 0) && (maxDepth < 0) && (maxNodes < 0);
ponder = false;
}
final public void stopSearch() {
stopThread();
}
final public void newGame() {
randomSeed = new Random().nextLong();
tt.clear();
}
/**
* Compute thinking time for current search.
*/
final public void computeTimeLimit(SearchParams sPar) {
minTimeLimit = -1;
maxTimeLimit = -1;
maxDepth = -1;
maxNodes = -1;
if (sPar.infinite) {
minTimeLimit = -1;
maxTimeLimit = -1;
maxDepth = -1;
} else if (sPar.depth > 0) {
maxDepth = sPar.depth;
} else if (sPar.mate > 0) {
maxDepth = sPar.mate * 2 - 1;
} else if (sPar.moveTime > 0) {
minTimeLimit = maxTimeLimit = sPar.moveTime;
} else if (sPar.nodes > 0) {
maxNodes = sPar.nodes;
} else {
int moves = sPar.movesToGo;
if (moves == 0) {
moves = 999;
}
moves = Math.min(moves, 45); // Assume 45 more moves until end of game
if (ponderMode) {
final double ponderHitRate = 0.35;
moves = (int)Math.ceil(moves * (1 - ponderHitRate));
}
boolean white = pos.whiteMove;
int time = white ? sPar.wTime : sPar.bTime;
int inc = white ? sPar.wInc : sPar.bInc;
final int margin = Math.min(1000, time * 9 / 10);
int timeLimit = (time + inc * (moves - 1) - margin) / moves;
minTimeLimit = (int)(timeLimit * 0.85);
maxTimeLimit = (int)(minTimeLimit * (Math.max(2.5, Math.min(4.0, moves / 2))));
// Leave at least 1s on the clock, but can't use negative time
minTimeLimit = clamp(minTimeLimit, 1, time - margin);
maxTimeLimit = clamp(maxTimeLimit, 1, time - margin);
}
}
private static final int clamp(int val, int min, int max) {
if (val < min) {
return min;
} else if (val > max) {
return max;
} else {
return val;
}
}
final private void startThread(final int minTimeLimit, final int maxTimeLimit,
int maxDepth, final int maxNodes) {
synchronized (threadMutex) {} // Must not start new search until old search is finished
sc = new Search(pos, posHashList, posHashListSize, tt);
sc.timeLimit(minTimeLimit, maxTimeLimit);
sc.setListener(new SearchListener(os));
sc.setStrength(strength, randomSeed);
MoveGen.MoveList moves = moveGen.pseudoLegalMoves(pos);
MoveGen.removeIllegal(pos, moves);
if ((searchMoves != null) && (searchMoves.size() > 0)) {
Arrays.asList(moves.m).retainAll(searchMoves);
}
final MoveGen.MoveList srchMoves = moves;
onePossibleMove = false;
if ((srchMoves.size < 2) && !infinite) {
onePossibleMove = true;
if (!ponder) {
if ((maxDepth < 0) || (maxDepth > 2)) maxDepth = 2;
}
}
tt.nextGeneration();
final int srchmaxDepth = maxDepth;
engineThread = new Thread(new Runnable() {
public void run() {
Move m = null;
if (ownBook && !analyseMode) {
Book book = new Book(false);
m = book.getBookMove(pos);
}
if (m == null) {
m = sc.iterativeDeepening(srchMoves, srchmaxDepth, maxNodes, false);
}
while (ponder || infinite) {
// We should not respond until told to do so. Just wait until
// we are allowed to respond.
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
break;
}
}
Move ponderMove = getPonderMove(pos, m);
synchronized (threadMutex) {
if (ponderMove != null) {
os.printf("bestmove %s ponder %s%n", moveToString(m), moveToString(ponderMove));
} else {
os.printf("bestmove %s%n", moveToString(m));
}
engineThread = null;
sc = null;
}
}
});
engineThread.start();
}
private final void stopThread() {
Thread myThread;
Search mySearch;
synchronized (threadMutex) {
myThread = engineThread;
mySearch = sc;
}
if (myThread != null) {
mySearch.timeLimit(0, 0);
infinite = false;
ponder = false;
try {
myThread.join();
} catch (InterruptedException ex) {
throw new RuntimeException();
}
}
}
private final void setupTT() {
int nEntries = hashSizeMB > 0 ? hashSizeMB * (1 << 20) / 24 : 1024;
int logSize = (int) Math.floor(Math.log(nEntries) / Math.log(2));
tt = new TranspositionTable(logSize);
}
private final void setupPosition(Position pos, List<Move> moves) {
UndoInfo ui = new UndoInfo();
posHashList = new long[200 + moves.size()];
posHashListSize = 0;
for (Move m : moves) {
posHashList[posHashListSize++] = pos.zobristHash();
pos.makeMove(m, ui);
}
this.pos = pos;
}
/**
* Try to find a move to ponder from the transposition table.
*/
private final Move getPonderMove(Position pos, Move m) {
if (m == null) return null;
Move ret = null;
UndoInfo ui = new UndoInfo();
pos.makeMove(m, ui);
TTEntry ent = tt.probe(pos.historyHash());
if (ent.type != TTEntry.T_EMPTY) {
ret = new Move(0, 0, 0);
ent.getMove(ret);
MoveGen.MoveList moves = moveGen.pseudoLegalMoves(pos);
MoveGen.removeIllegal(pos, moves);
boolean contains = false;
for (int mi = 0; mi < moves.size; mi++)
if (moves.m[mi].equals(ret)) {
contains = true;
break;
}
if (!contains)
ret = null;
}
pos.unMakeMove(m, ui);
return ret;
}
private static final String moveToString(Move m) {
if (m == null)
return "0000";
String ret = TextIO.squareToString(m.from);
ret += TextIO.squareToString(m.to);
switch (m.promoteTo) {
case Piece.WQUEEN:
case Piece.BQUEEN:
ret += "q";
break;
case Piece.WROOK:
case Piece.BROOK:
ret += "r";
break;
case Piece.WBISHOP:
case Piece.BBISHOP:
ret += "b";
break;
case Piece.WKNIGHT:
case Piece.BKNIGHT:
ret += "n";
break;
default:
break;
}
return ret;
}
static void printOptions(PrintStream os) {
os.printf("option name Hash type spin default 16 min 1 max 2048%n");
os.printf("option name OwnBook type check default false%n");
os.printf("option name Ponder type check default true%n");
os.printf("option name UCI_AnalyseMode type check default false%n");
os.printf("option name UCI_EngineAbout type string default %s by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html%n",
ComputerPlayer.engineName);
os.printf("option name Strength type spin default 1000 min 0 max 1000\n");
for (String pName : Parameters.instance().getParamNames()) {
ParamBase p = Parameters.instance().getParam(pName);
switch (p.type) {
case CHECK: {
CheckParam cp = (CheckParam)p;
os.printf("optionn name %s type check default %s\n",
p.name, cp.defaultValue?"true":"false");
break;
}
case SPIN: {
SpinParam sp = (SpinParam)p;
os.printf("option name %s type spin default %d min %d max %d\n",
p.name, sp.defaultValue, sp.minValue, sp.maxValue);
break;
}
case COMBO: {
ComboParam cp = (ComboParam)p;
os.printf("option name %s type combo default %s ", cp.name, cp.defaultValue);
for (String s : cp.allowedValues)
os.printf(" var %s", s);
os.printf("\n");
break;
}
case BUTTON:
os.printf("option name %s type button\n", p.name);
break;
case STRING: {
StringParam sp = (StringParam)p;
os.printf("option name %s type string default %s\n",
p.name, sp.defaultValue);
break;
}
}
}
}
final void setOption(String optionName, String optionValue) {
try {
if (optionName.equals("hash")) {
hashSizeMB = Integer.parseInt(optionValue);
setupTT();
} else if (optionName.equals("ownbook")) {
ownBook = Boolean.parseBoolean(optionValue);
} else if (optionName.equals("ponder")) {
ponderMode = Boolean.parseBoolean(optionValue);
} else if (optionName.equals("uci_analysemode")) {
analyseMode = Boolean.parseBoolean(optionValue);
} else if (optionName.equals("strength")) {
strength = Integer.parseInt(optionValue);
} else {
Parameters.instance().set(optionName, optionValue);
}
} catch (NumberFormatException nfe) {
}
}
}

View File

@ -0,0 +1,45 @@
/*
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 uci;
import chess.Move;
import java.util.ArrayList;
import java.util.List;
/**
* Store search parameters (times, increments, max depth, etc).
* @author petero
*/
public class SearchParams {
List<Move> searchMoves; // If non-empty, search only these moves
int wTime; // White remaining time, ms
int bTime; // Black remaining time, ms
int wInc; // White increment per move, ms
int bInc; // Black increment per move, ms
int movesToGo; // Moves to next time control
int depth; // If >0, don't search deeper than this
int nodes; // If >0, don't search more nodes than this
int mate; // If >0, search for mate-in-x
int moveTime; // If >0, search for exactly this amount of time, ms
boolean infinite;
public SearchParams() {
searchMoves = new ArrayList<Move>();
}
}

View File

@ -0,0 +1,222 @@
/*
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 uci;
import chess.ChessParseError;
import chess.ComputerPlayer;
import chess.Move;
import chess.Position;
import chess.TextIO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.util.ArrayList;
/**
* Handle the UCI protocol mode.
* @author petero
*/
public class UCIProtocol {
// Data set by the "position" command.
Position pos;
ArrayList<Move> moves;
// Engine data
EngineControl engine;
// Set to true to break out of main loop
boolean quit;
public static void main(boolean autoStart) {
UCIProtocol uciProt = new UCIProtocol();
uciProt.mainLoop(System.in, System.out, autoStart);
}
public UCIProtocol() {
pos = null;
moves = new ArrayList<Move>();
quit = false;
}
final public void mainLoop(InputStream is, PrintStream os, boolean autoStart) {
try {
if (autoStart) {
handleCommand("uci", os);
}
InputStreamReader inStrRead = new InputStreamReader(is);
BufferedReader inBuf = new BufferedReader(inStrRead);
String line;
while ((line = inBuf.readLine()) != null) {
handleCommand(line, os);
if (quit) {
break;
}
}
} catch (IOException ex) {
// If stream closed or other I/O error, terminate program
}
}
final void handleCommand(String cmdLine, PrintStream os) {
String[] tokens = tokenize(cmdLine);
try {
String cmd = tokens[0];
if (cmd.equals("uci")) {
os.printf("id name %s%n", ComputerPlayer.engineName);
os.printf("id author Peter Osterlund%n");
EngineControl.printOptions(os);
os.printf("uciok%n");
} else if (cmd.equals("isready")) {
initEngine(os);
os.printf("readyok%n");
} else if (cmd.equals("setoption")) {
initEngine(os);
StringBuilder optionName = new StringBuilder();
StringBuilder optionValue = new StringBuilder();
if (tokens[1].endsWith("name")) {
int idx = 2;
while ((idx < tokens.length) && !tokens[idx].equals("value")) {
optionName.append(tokens[idx++].toLowerCase());
optionName.append(' ');
}
if ((idx < tokens.length) && tokens[idx++].equals("value")) {
while ((idx < tokens.length)) {
optionValue.append(tokens[idx++].toLowerCase());
optionValue.append(' ');
}
}
engine.setOption(optionName.toString().trim(), optionValue.toString().trim());
}
} else if (cmd.equals("ucinewgame")) {
if (engine != null) {
engine.newGame();
}
} else if (cmd.equals("position")) {
String fen = null;
int idx = 1;
if (tokens[idx].equals("startpos")) {
idx++;
fen = TextIO.startPosFEN;
} else if (tokens[idx].equals("fen")) {
idx++;
StringBuilder sb = new StringBuilder();
while ((idx < tokens.length) && !tokens[idx].equals("moves")) {
sb.append(tokens[idx++]);
sb.append(' ');
}
fen = sb.toString().trim();
}
if (fen != null) {
pos = TextIO.readFEN(fen);
moves.clear();
if ((idx < tokens.length) && tokens[idx++].equals("moves")) {
for (int i = idx; i < tokens.length; i++) {
Move m = TextIO.uciStringToMove(tokens[i]);
if (m != null) {
moves.add(m);
} else {
break;
}
}
}
}
} else if (cmd.equals("go")) {
if (pos == null) {
try {
pos = TextIO.readFEN(TextIO.startPosFEN);
} catch (ChessParseError ex) {
throw new RuntimeException();
}
}
initEngine(os);
int idx = 1;
SearchParams sPar = new SearchParams();
boolean ponder = false;
while (idx < tokens.length) {
String subCmd = tokens[idx++];
if (subCmd.equals("searchmoves")) {
while (idx < tokens.length) {
Move m = TextIO.uciStringToMove(tokens[idx]);
if (m != null) {
sPar.searchMoves.add(m);
idx++;
} else {
break;
}
}
} else if (subCmd.equals("ponder")) {
ponder = true;
} else if (subCmd.equals("wtime")) {
sPar.wTime = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("btime")) {
sPar.bTime = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("winc")) {
sPar.wInc = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("binc")) {
sPar.bInc = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("movestogo")) {
sPar.movesToGo = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("depth")) {
sPar.depth = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("nodes")) {
sPar.nodes = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("mate")) {
sPar.mate = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("movetime")) {
sPar.moveTime = Integer.parseInt(tokens[idx++]);
} else if (subCmd.equals("infinite")) {
sPar.infinite = true;
}
}
if (ponder) {
engine.startPonder(pos, moves, sPar);
} else {
engine.startSearch(pos, moves, sPar);
}
} else if (cmd.equals("stop")) {
engine.stopSearch();
} else if (cmd.equals("ponderhit")) {
engine.ponderHit();
} else if (cmd.equals("quit")) {
if (engine != null) {
engine.stopSearch();
}
quit = true;
}
} catch (ChessParseError ex) {
} catch (ArrayIndexOutOfBoundsException e) {
} catch (NumberFormatException nfe) {
}
}
final private void initEngine(PrintStream os) {
if (engine == null) {
engine = new EngineControl(os);
}
}
/** Convert a string to tokens by splitting at whitespace characters. */
final String[] tokenize(String cmdLine) {
cmdLine = cmdLine.trim();
return cmdLine.split("\\s+");
}
}

View File

@ -0,0 +1,68 @@
/*
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 uci;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
/**
*
* @author petero
*/
public class UCIProtocolTest {
public UCIProtocolTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of tokenize method, of class UCIProtocol.
*/
@Test
public void testTokenize() {
System.out.println("tokenize");
UCIProtocol uci = new UCIProtocol();
String[] result = uci.tokenize(" a b c de \t \t fgh");
assertEquals(5, result.length);
assertEquals("a", result[0]);
assertEquals("b", result[1]);
assertEquals("c", result[2]);
assertEquals("de", result[3]);
assertEquals("fgh", result[4]);
}
}