diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 09b0d05..0000000 --- a/.gitignore +++ /dev/null @@ -1,15 +0,0 @@ -*.class - -# Package Files # -*.jar -*.war -*.ear - -# Eclipse # -target/ -bin/ -.settings/ -.classpath -.project -.idea/ -*.iml diff --git a/README.md b/README.md deleted file mode 100644 index 5004404..0000000 --- a/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Minimax4j - -Minimax4j is a JAVA implementation of the [minimax algorithm](http://en.wikipedia.org/wiki/Minimax). -It is a simple but complete abstract API that let you concentrate on the evaluation function. - -```xml - - fr.avianey - minimax4j - 1.0.0 - -``` - -## Samples - -Samples are available in the minimax-sample project and provide basic implementations for the following IA : -* Tic-Tac-Toe - -## Documentation - -The [Minimax4j javadoc](http://avianey.github.com/minimax4j/) is available on the github project page. - -## Licence - -``` -The MIT License (MIT) - -Copyright (c) 2015 Antoine Vianey - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -``` - -## Contribute - -Feel free to contribute by sending pull requests. -Abstract mechanism that would likely fit into the API are : -* Transposition table (to optimize & test) -* Quiescence search -* Opening table -* Best-First Search - -## Contributors - -* [@avianey](https://github.com/avianey) : creator - -## Who's using it ? - -List of projects using minimax4j : -* [Reversi](https://play.google.com/store/apps/details?id=net.androgames.reversi) for Android on Google play ([@avianey](https://github.com/avianey)) - -Fork the project and send a pull request to add your application in this list. diff --git a/allclasses-frame.html b/allclasses-frame.html new file mode 100644 index 0000000..cd901a9 --- /dev/null +++ b/allclasses-frame.html @@ -0,0 +1,22 @@ + + + + + + +All Classes (minimax4j 1.0.0 API) + + + + +

All Classes

+
+ +
+ + diff --git a/allclasses-noframe.html b/allclasses-noframe.html new file mode 100644 index 0000000..0986e71 --- /dev/null +++ b/allclasses-noframe.html @@ -0,0 +1,22 @@ + + + + + + +All Classes (minimax4j 1.0.0 API) + + + + +

All Classes

+
+ +
+ + diff --git a/constant-values.html b/constant-values.html new file mode 100644 index 0000000..113f870 --- /dev/null +++ b/constant-values.html @@ -0,0 +1,115 @@ + + + + + + +Constant Field Values (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Constant Field Values

+

Contents

+
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/deprecated-list.html b/deprecated-list.html new file mode 100644 index 0000000..e0bcde7 --- /dev/null +++ b/deprecated-list.html @@ -0,0 +1,115 @@ + + + + + + +Deprecated List (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Deprecated API

+

Contents

+
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/1.0.0/_maven.repositories b/fr/pixelprose/minimax4j/1.0.0/_maven.repositories new file mode 100644 index 0000000..f2d1792 --- /dev/null +++ b/fr/pixelprose/minimax4j/1.0.0/_maven.repositories @@ -0,0 +1,4 @@ +#NOTE: This is an internal implementation file, its format can be changed without prior notice. +#Thu Feb 28 13:42:40 CET 2013 +minimax4j-1.0.0.jar>= +minimax4j-1.0.0.pom>= diff --git a/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.jar b/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.jar new file mode 100644 index 0000000..4389f53 Binary files /dev/null and b/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.jar differ diff --git a/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.pom b/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.pom new file mode 100644 index 0000000..84f28ff --- /dev/null +++ b/fr/pixelprose/minimax4j/1.0.0/minimax4j-1.0.0.pom @@ -0,0 +1,55 @@ + + + 4.0.0 + minimax4j + fr.pixelprose + minimax4j + 1.0.0 + + Minimax4j is a pure java implementation of the minimax algorithm. + It provides implementation of standard minimax but also provides alpha-beta pruning, negamax or negascout. + This project can be use to implement two-person zero-sum games of perfect information such as chess, reversi, connect four, ... + + + + Antoine Vianey + + developer + + http://avianey.blogspot.com + + + + + + GNU Lesser General Public License version 3 + http://www.gnu.org/licenses/lgpl.html + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.5.1 + + 1.6 + 1.6 + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + + + + + + \ No newline at end of file diff --git a/fr/pixelprose/minimax4j/Difficulty.html b/fr/pixelprose/minimax4j/Difficulty.html new file mode 100644 index 0000000..7f3d9eb --- /dev/null +++ b/fr/pixelprose/minimax4j/Difficulty.html @@ -0,0 +1,214 @@ + + + + + + +Difficulty (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + + +
+
fr.pixelprose.minimax4j
+

Interface Difficulty

+
+
+
+ +
+
+ +
+
+ +
+
+ + +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/IA.Algorithm.html b/fr/pixelprose/minimax4j/IA.Algorithm.html new file mode 100644 index 0000000..2fe87e8 --- /dev/null +++ b/fr/pixelprose/minimax4j/IA.Algorithm.html @@ -0,0 +1,364 @@ + + + + + + +IA.Algorithm (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + + +
+
fr.pixelprose.minimax4j
+

Enum IA.Algorithm

+
+
+ +
+ +
+
+ +
+
+ +
+
+ + +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/IA.html b/fr/pixelprose/minimax4j/IA.html new file mode 100644 index 0000000..e3c6975 --- /dev/null +++ b/fr/pixelprose/minimax4j/IA.html @@ -0,0 +1,483 @@ + + + + + + +IA (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + + +
+
fr.pixelprose.minimax4j
+

Class IA<M extends Move>

+
+
+ +
+ +
+
+ +
+
+ +
+
+ + +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/Move.html b/fr/pixelprose/minimax4j/Move.html new file mode 100644 index 0000000..6e2332c --- /dev/null +++ b/fr/pixelprose/minimax4j/Move.html @@ -0,0 +1,174 @@ + + + + + + +Move (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + + +
+
fr.pixelprose.minimax4j
+

Interface Move

+
+
+
+ +
+
+ + +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/class-use/Difficulty.html b/fr/pixelprose/minimax4j/class-use/Difficulty.html new file mode 100644 index 0000000..b570276 --- /dev/null +++ b/fr/pixelprose/minimax4j/class-use/Difficulty.html @@ -0,0 +1,142 @@ + + + + + + +Uses of Interface fr.pixelprose.minimax4j.Difficulty (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Uses of Interface
fr.pixelprose.minimax4j.Difficulty

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/class-use/IA.Algorithm.html b/fr/pixelprose/minimax4j/class-use/IA.Algorithm.html new file mode 100644 index 0000000..32d01ad --- /dev/null +++ b/fr/pixelprose/minimax4j/class-use/IA.Algorithm.html @@ -0,0 +1,162 @@ + + + + + + +Uses of Class fr.pixelprose.minimax4j.IA.Algorithm (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Uses of Class
fr.pixelprose.minimax4j.IA.Algorithm

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/class-use/IA.html b/fr/pixelprose/minimax4j/class-use/IA.html new file mode 100644 index 0000000..a36a5c9 --- /dev/null +++ b/fr/pixelprose/minimax4j/class-use/IA.html @@ -0,0 +1,115 @@ + + + + + + +Uses of Class fr.pixelprose.minimax4j.IA (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Uses of Class
fr.pixelprose.minimax4j.IA

+
+
No usage of fr.pixelprose.minimax4j.IA
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/class-use/Move.html b/fr/pixelprose/minimax4j/class-use/Move.html new file mode 100644 index 0000000..983c2d2 --- /dev/null +++ b/fr/pixelprose/minimax4j/class-use/Move.html @@ -0,0 +1,142 @@ + + + + + + +Uses of Interface fr.pixelprose.minimax4j.Move (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Uses of Interface
fr.pixelprose.minimax4j.Move

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/maven-metadata-local.xml b/fr/pixelprose/minimax4j/maven-metadata-local.xml new file mode 100644 index 0000000..b0e7756 --- /dev/null +++ b/fr/pixelprose/minimax4j/maven-metadata-local.xml @@ -0,0 +1,12 @@ + + + fr.pixelprose + minimax4j + + 1.0.0 + + 1.0.0 + + 20130228124240 + + diff --git a/fr/pixelprose/minimax4j/package-frame.html b/fr/pixelprose/minimax4j/package-frame.html new file mode 100644 index 0000000..af1d98a --- /dev/null +++ b/fr/pixelprose/minimax4j/package-frame.html @@ -0,0 +1,29 @@ + + + + + + +fr.pixelprose.minimax4j (minimax4j 1.0.0 API) + + + + +

fr.pixelprose.minimax4j

+
+

Interfaces

+ +

Classes

+ +

Enums

+ +
+ + diff --git a/fr/pixelprose/minimax4j/package-summary.html b/fr/pixelprose/minimax4j/package-summary.html new file mode 100644 index 0000000..117f0fb --- /dev/null +++ b/fr/pixelprose/minimax4j/package-summary.html @@ -0,0 +1,175 @@ + + + + + + +fr.pixelprose.minimax4j (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Package fr.pixelprose.minimax4j

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/package-tree.html b/fr/pixelprose/minimax4j/package-tree.html new file mode 100644 index 0000000..40e9a32 --- /dev/null +++ b/fr/pixelprose/minimax4j/package-tree.html @@ -0,0 +1,141 @@ + + + + + + +fr.pixelprose.minimax4j Class Hierarchy (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For Package fr.pixelprose.minimax4j

+
+
+

Class Hierarchy

+ +

Interface Hierarchy

+ +

Enum Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/fr/pixelprose/minimax4j/package-use.html b/fr/pixelprose/minimax4j/package-use.html new file mode 100644 index 0000000..ae389a0 --- /dev/null +++ b/fr/pixelprose/minimax4j/package-use.html @@ -0,0 +1,145 @@ + + + + + + +Uses of Package fr.pixelprose.minimax4j (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Uses of Package
fr.pixelprose.minimax4j

+
+
+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/help-doc.html b/help-doc.html new file mode 100644 index 0000000..d3332e6 --- /dev/null +++ b/help-doc.html @@ -0,0 +1,216 @@ + + + + + + +API Help (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

How This API Document Is Organized

+
This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.
+
+
+ +This help file applies to API documentation generated using the standard doclet.
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/index-all.html b/index-all.html new file mode 100644 index 0000000..223b3a3 --- /dev/null +++ b/index-all.html @@ -0,0 +1,250 @@ + + + + + + +Index (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
D E F G I M N P U V  + + +

D

+
+
Difficulty - Interface in fr.pixelprose.minimax4j
+
+
Implement this interface to provide several difficulties for your IA implementation.
+
+
+ + + +

E

+
+
evaluate() - Method in class fr.pixelprose.minimax4j.IA
+
+
Evaluate the state of the game for the current player after a move.
+
+
+ + + +

F

+
+
fr.pixelprose.minimax4j - package fr.pixelprose.minimax4j
+
 
+
+ + + +

G

+
+
getBestMove() - Method in class fr.pixelprose.minimax4j.IA
+
 
+
getDepth() - Method in interface fr.pixelprose.minimax4j.Difficulty
+
+
The thinking depth for the decision rule used by the IA.
+
+
getDifficulty() - Method in class fr.pixelprose.minimax4j.IA
+
+
Get the IA difficulty level for the current player
+
+
getPossibleMoves() - Method in class fr.pixelprose.minimax4j.IA
+
+
List every valid moves for the current player.
+
+
+ + + +

I

+
+
IA<M extends Move> - Class in fr.pixelprose.minimax4j
+
+
Abstract class implementing minimax and derivated decision rules for two-person zero-sum games of perfect information.
+
+
IA() - Constructor for class fr.pixelprose.minimax4j.IA
+
+
Creates a new IA using the IA.Algorithm.NEGAMAX algorithm
+ IA.Algorithm.NEGASCOUT performs slowly on several tests at the moment...
+
+
IA(IA.Algorithm) - Constructor for class fr.pixelprose.minimax4j.IA
+
+
Creates a new IA using the provided algorithm
+
+
IA.Algorithm - Enum in fr.pixelprose.minimax4j
+
+
Available decision rules
+
+
isOver() - Method in class fr.pixelprose.minimax4j.IA
+
+
Tell weather or not the game is over.
+
+
+ + + +

M

+
+
makeMove(M) - Method in class fr.pixelprose.minimax4j.IA
+
+
Play the given move and modify the state of the game.
+
+
maxEvaluateValue() - Method in class fr.pixelprose.minimax4j.IA
+
+
The absolute maximal value for the evaluate function.
+
+
Move - Interface in fr.pixelprose.minimax4j
+
+
Implement this interface to describe a Move in your game.
+
+
+ + + +

N

+
+
next() - Method in class fr.pixelprose.minimax4j.IA
+
+
Change current turn to the next player.
+
+
+ + + +

P

+
+
previous() - Method in class fr.pixelprose.minimax4j.IA
+
+
Change current turn to the previous player.
+
+
+ + + +

U

+
+
unmakeMove(M) - Method in class fr.pixelprose.minimax4j.IA
+
+
Undo the given move and restore the state of the game.
+
+
+ + + +

V

+
+
valueOf(String) - Static method in enum fr.pixelprose.minimax4j.IA.Algorithm
+
+
Returns the enum constant of this type with the specified name.
+
+
values() - Static method in enum fr.pixelprose.minimax4j.IA.Algorithm
+
+
Returns an array containing the constants of this enum type, in +the order they are declared.
+
+
+D E F G I M N P U V 
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/index.html b/index.html new file mode 100644 index 0000000..8987122 --- /dev/null +++ b/index.html @@ -0,0 +1,31 @@ + + + + + + +minimax4j 1.0.0 API + + + + + + +<noscript> +<div>JavaScript is disabled on your browser.</div> +</noscript> +<h2>Frame Alert</h2> +<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="fr/pixelprose/minimax4j/package-summary.html">Non-frame version</a>.</p> + + + diff --git a/minimax4j-sample/pom.xml b/minimax4j-sample/pom.xml deleted file mode 100644 index 965326c..0000000 --- a/minimax4j-sample/pom.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - 4.0.0 - minimax4j-sample - fr.avianey - minimax4j-sample - 1.0.1-SNAPSHOT - - Minimax4j is a pure java implementation of the minimax algorithm. - It provides implementation of standard minimax but also provides alpha-beta pruning, negamax or negascout. - This project can be use to implement two-person zero-sum games of perfect information such as chess, reversi, connect four, ... - - - - Antoine Vianey - - developer - - http://avianey.blogspot.com - - - - - - fr.avianey - minimax4j - 1.0.1-SNAPSHOT - - - junit - junit - 4.8.2 - test - - - - - - GNU General Public License version 3 - http://www.gnu.org/licenses/ - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.7 - 1.7 - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.8.1 - - - - - - - \ No newline at end of file diff --git a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMinimax.java b/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMinimax.java deleted file mode 100644 index 975315a..0000000 --- a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMinimax.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.sample.tictactoe; - -import java.util.ArrayList; -import java.util.List; - -import fr.avianey.minimax4j.BasicMinimax; -import fr.avianey.minimax4j.Minimax; - -/** - * Simple TicTacToe IA to showcase the API. - * - * @author antoine vianey - */ -public class TicTacToeMinimax extends BasicMinimax { - - static final int FREE = 0; - static final int PLAYER_X = 1; // X - static final int PLAYER_O = 2; // O - - private static final int GRID_SIZE = 3; - - /** The grid */ - private final int[][] grid; - - private int currentPlayer; - private int turn = 0; - - public TicTacToeMinimax(Algorithm algo) { - super(algo); - this.grid = new int[GRID_SIZE][GRID_SIZE]; - newGame(); - } - - public void newGame() { - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - grid[i][j] = FREE; - } - } - // X start to play - currentPlayer = PLAYER_X; - turn = 0; - } - - @Override - public boolean isOver() { - return hasWon(PLAYER_O) || hasWon(PLAYER_X) || turn == 9; - } - - private boolean hasWon(int player) { - return - (player == grid[0][1] && player == grid[0][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[1][2] && player == grid[1][0]) - || - (player == grid[2][1] && player == grid[2][2] && player == grid[2][0]) - || - (player == grid[1][0] && player == grid[2][0] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][1] && player == grid[0][1]) - || - (player == grid[1][2] && player == grid[2][2] && player == grid[0][2]) - || - (player == grid[1][1] && player == grid[2][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][0] && player == grid[0][2]); - } - - @Override - public void makeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = currentPlayer; - turn++; - next(); - } - - @Override - public void unmakeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = FREE; - turn--; - previous(); - } - - @Override - public List getPossibleMoves() { - List moves = new ArrayList<>(9); - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - if (grid[i][j] == FREE) { - moves.add(new TicTacToeMove(i, j, currentPlayer)); - } - } - } - // moves can be sorted to optimize alpha-beta pruning - // {1,1} is always the best move when available - return moves; - } - - @Override - public double evaluate() { - int eval = 0; - if (hasWon(currentPlayer)) { - // 2 for the win - eval = 2; - } else if (hasWon(3 - currentPlayer)) { - // -2 for loosing - eval = -2; - } else if (grid[1][1] == currentPlayer) { - // 1 for {1,1} - eval = 1; - } else if (grid[1][1] == 3 - currentPlayer) { - // -1 for opponent {1,1} - eval = -1; - } - return eval; - } - - @Override - public double maxEvaluateValue() { - // evaluate return either -2, -1, 0, 1 or 2 - return 3; - } - - @Override - public void next() { - currentPlayer = 3 - currentPlayer; - } - - @Override - public void previous() { - currentPlayer = 3 - currentPlayer; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(grid[0][0] == FREE ? " " : (grid[0][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][0] == FREE ? " " : (grid[1][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][0] == FREE ? " " : (grid[2][0] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][1] == FREE ? " " : (grid[0][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][1] == FREE ? " " : (grid[1][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][1] == FREE ? " " : (grid[2][1] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][2] == FREE ? " " : (grid[0][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][2] == FREE ? " " : (grid[1][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][2] == FREE ? " " : (grid[2][2] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - return sb.toString(); - } - -} diff --git a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMove.java b/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMove.java deleted file mode 100644 index ce3c4b3..0000000 --- a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeMove.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) -* - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.sample.tictactoe; - -import fr.avianey.minimax4j.Move; - -/** - * A basic move implementation : who and where... - * - * @author antoine vianey - */ -public class TicTacToeMove implements Move { - - /** The player owning the move */ - private int player; - - /** x coordinate of the move */ - private int x; - /** y coordinate of the move */ - private int y; - - public TicTacToeMove(int x, int y, int player) { - this.x = x; - this.y = y; - this.player = player; - } - - public int getX() { - return x; - } - - public void setX(int x) { - this.x = x; - } - - public int getY() { - return y; - } - - public void setY(int y) { - this.y = y; - } - - public int getPlayer() { - return player; - } - - public void setPlayer(int player) { - this.player = player; - } - - public String toString() { - return (player == TicTacToeMinimax.PLAYER_O ? "O" : "X") + " (" + x + ";" + y + ")"; - } - -} diff --git a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeParallelMinimax.java b/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeParallelMinimax.java deleted file mode 100644 index f68b5d8..0000000 --- a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeParallelMinimax.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.sample.tictactoe; - -import java.util.ArrayList; -import java.util.List; - -import fr.avianey.minimax4j.ParallelMinimax; - -/** - * Simple TicTacToe IA to showcase the API. - * - * @author antoine vianey - */ -public class TicTacToeParallelMinimax extends ParallelMinimax { - - static final int FREE = 0; - static final int PLAYER_X = 1; // X - static final int PLAYER_O = 2; // O - - private static final int GRID_SIZE = 3; - - /** The grid */ - private final int[][] grid; - - private int currentPlayer; - private int turn = 0; - - public TicTacToeParallelMinimax(Algorithm algo) { - super(algo); - this.grid = new int[GRID_SIZE][GRID_SIZE]; - newGame(); - } - - private TicTacToeParallelMinimax(Algorithm algo, int[][] grid, int turn, int currentPlayer) { - this(algo); - this.currentPlayer = currentPlayer; - this.turn = turn; - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - this.grid[i][j] = grid[i][j]; - } - } - } - - public void newGame() { - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - grid[i][j] = FREE; - } - } - // X start to play - currentPlayer = PLAYER_X; - turn = 0; - } - - @Override - public boolean isOver() { - return hasWon(PLAYER_O) || hasWon(PLAYER_X) || turn == 9; - } - - private boolean hasWon(int player) { - return - (player == grid[0][1] && player == grid[0][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[1][2] && player == grid[1][0]) - || - (player == grid[2][1] && player == grid[2][2] && player == grid[2][0]) - || - (player == grid[1][0] && player == grid[2][0] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][1] && player == grid[0][1]) - || - (player == grid[1][2] && player == grid[2][2] && player == grid[0][2]) - || - (player == grid[1][1] && player == grid[2][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][0] && player == grid[0][2]); - } - - @Override - public void makeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = currentPlayer; - turn++; - next(); - } - - @Override - public void unmakeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = FREE; - turn--; - previous(); - } - - @Override - public List getPossibleMoves() { - List moves = new ArrayList<>(9); - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - if (grid[i][j] == FREE) { - moves.add(new TicTacToeMove(i, j, currentPlayer)); - } - } - } - // moves can be sorted to optimize alpha-beta pruning - // {1,1} is always the best move when available - return moves; - } - - @Override - public double evaluate() { - int eval = 0; - if (hasWon(currentPlayer)) { - // 2 for the win - eval = 2; - } else if (hasWon(3 - currentPlayer)) { - // -2 for loosing - eval = -2; - } else if (grid[1][1] == currentPlayer) { - // 1 for {1,1} - eval = 1; - } else if (grid[1][1] == 3 - currentPlayer) { - // -1 for opponent {1,1} - eval = -1; - } - return eval; - } - - @Override - public double maxEvaluateValue() { - // evaluate return either -2, -1, 0, 1 or 2 - return 3; - } - - @Override - public void next() { - currentPlayer = 3 - currentPlayer; - } - - @Override - public void previous() { - currentPlayer = 3 - currentPlayer; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(grid[0][0] == FREE ? " " : (grid[0][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][0] == FREE ? " " : (grid[1][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][0] == FREE ? " " : (grid[2][0] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][1] == FREE ? " " : (grid[0][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][1] == FREE ? " " : (grid[1][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][1] == FREE ? " " : (grid[2][1] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][2] == FREE ? " " : (grid[0][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][2] == FREE ? " " : (grid[1][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][2] == FREE ? " " : (grid[2][2] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - return sb.toString(); - } - - @Override - public ParallelMinimax clone() { - return new TicTacToeParallelMinimax(getAlgorithm(), grid, turn, currentPlayer); - } - -} diff --git a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeTranspositionMinimax.java b/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeTranspositionMinimax.java deleted file mode 100644 index c5da733..0000000 --- a/minimax4j-sample/src/main/java/fr/avianey/minimax4j/sample/tictactoe/TicTacToeTranspositionMinimax.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.sample.tictactoe; - -import java.util.ArrayList; -import java.util.List; - -import fr.avianey.minimax4j.TranspositionMinimax; - -/** - * Simple TicTacToe IA to showcase the API. - * - * @author antoine vianey - */ -public class TicTacToeTranspositionMinimax extends TranspositionMinimax { - - static final int FREE = 0; - static final int PLAYER_X = 1; // X : 01 - static final int PLAYER_O = 2; // O : 10 - - private static final int GRID_SIZE = 3; - private static final int MAX_TURN = GRID_SIZE * GRID_SIZE; - - /** The grid */ - private final int[][] grid; - - private int currentPlayer; - private int turn = 0; - private int hash = 0; - - public TicTacToeTranspositionMinimax(Algorithm algo) { - super(algo); - this.grid = new int[GRID_SIZE][GRID_SIZE]; - newGame(); - } - - public void newGame() { - hash = 0; - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - grid[i][j] = FREE; - } - } - // X start to play - currentPlayer = PLAYER_X; - turn = 0; - } - - @Override - public boolean isOver() { - return hasWon(PLAYER_O) || hasWon(PLAYER_X) || turn == 9; - } - - private boolean hasWon(int player) { - return - (player == grid[0][1] && player == grid[0][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[1][2] && player == grid[1][0]) - || - (player == grid[2][1] && player == grid[2][2] && player == grid[2][0]) - || - (player == grid[1][0] && player == grid[2][0] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][1] && player == grid[0][1]) - || - (player == grid[1][2] && player == grid[2][2] && player == grid[0][2]) - || - (player == grid[1][1] && player == grid[2][2] && player == grid[0][0]) - || - (player == grid[1][1] && player == grid[2][0] && player == grid[0][2]); - } - - @Override - public void makeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = move.getPlayer(); - hash = hash ^ (move.getPlayer() << ((move.getX() + GRID_SIZE * move.getY()) * 2)); - turn++; - next(); - } - - @Override - public void unmakeMove(TicTacToeMove move) { - grid[move.getX()][move.getY()] = FREE; - hash = hash ^ (move.getPlayer() << ((move.getX() + GRID_SIZE * move.getY()) * 2)); - turn--; - previous(); - } - - @Override - public List getPossibleMoves() { - List moves = new ArrayList<>(9); - for (int i = 0; i < GRID_SIZE; i++) { - for (int j = 0; j < GRID_SIZE; j++) { - if (grid[i][j] == FREE) { - moves.add(new TicTacToeMove(i, j, currentPlayer)); - } - } - } - // moves can be sorted to optimize alpha-beta pruning - // {1,1} is always the best move when available - return moves; - } - - @Override - public double evaluate() { - int eval = 0; - if (hasWon(currentPlayer)) { - // 2 for the win - eval = 2; - } else if (hasWon(3 - currentPlayer)) { - // -2 for loosing - eval = -2; - } else if (grid[1][1] == currentPlayer) { - // 1 for {1,1} - eval = 1; - } else if (grid[1][1] == 3 - currentPlayer) { - // -1 for opponent {1,1} - eval = -1; - } - return eval; - } - - @Override - public double maxEvaluateValue() { - // evaluate return either -2, -1, 0, 1 or 2 - return 3; - } - - @Override - public void next() { - currentPlayer = 3 - currentPlayer; - } - - @Override - public void previous() { - currentPlayer = 3 - currentPlayer; - } - - /*===============================* - * TRANSPOSITION TABLE BACKED IA * - *===============================*/ - - @Override - public Integer getTransposition() { - return hash; - } - - @Override - public Integer getGroup() { - // as moves increase over turns - // we don't need to keep transposition from previous turns - return turn; - } - - @Override - public boolean clearGroupsAfterSearch() { - // remove useless transposition after search - // groups reflect turns and as players can't - // go back on a move in the next turn, - // transpositions from previous turns are useless - return true; - } - - @Override - public TicTacToeMove getBestMove(int depth) { - TicTacToeMove move = super.getBestMove(depth); - // clear the content of the transposition table - // unless it reached the max depth... if not - // using a known transposition value will lead to a loss - // of search depth as we will use the result of an evaluation - // with a lower depth of prediction ! - // we may have used informations from the transposition table - // to order available moves as an optimization for alpha-beta cut-off - if (turn + depth < MAX_TURN) { - // use with caution - super.clearTranspositionTable(); - } -// super.clearTranspositionTable(); - return move; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(grid[0][0] == FREE ? " " : (grid[0][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][0] == FREE ? " " : (grid[1][0] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][0] == FREE ? " " : (grid[2][0] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][1] == FREE ? " " : (grid[0][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][1] == FREE ? " " : (grid[1][1] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][1] == FREE ? " " : (grid[2][1] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - sb.append(grid[0][2] == FREE ? " " : (grid[0][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[1][2] == FREE ? " " : (grid[1][2] == PLAYER_O ? "O" : "X")); - sb.append(grid[2][2] == FREE ? " " : (grid[2][2] == PLAYER_O ? "O" : "X")); - sb.append("\n"); - return sb.toString(); - } - -} diff --git a/minimax4j/pom.xml b/minimax4j/pom.xml deleted file mode 100644 index 7f9c314..0000000 --- a/minimax4j/pom.xml +++ /dev/null @@ -1,187 +0,0 @@ - - - 4.0.0 - minimax4j - fr.avianey - minimax4j - jar - 1.0.1-SNAPSHOT - - Minimax4j is a pure java implementation of the IA algorithm. - It provides implementation of standard IA but also provides alpha-beta pruning, negamax or negascout. - This project can be use to implement two-person zero-sum games of perfect information such as chess, reversi, connect four, ... - - - - Antoine Vianey - - developer - - http://avianey.github.com - - - - - org.sonatype.oss - oss-parent - 7 - - - - - The MIT License - https://opensource.org/licenses/MIT - repo - - - - - https://github.com/avianey/minimax4j - scm:git:git@github.com/avianey/minimax4j.git - scm:git:git://github.com/avianey/minimax4j.git - HEAD - - - - - - - - org.apache.maven.plugins - maven-release-plugin - 2.4.2 - - forked-path - false - -Psonatype-oss-release - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - ${javadoc.additionalparam} - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - ${project.build.directory} - true - - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-release-plugin - - false - - - - - - - - com.google.guava - guava - 18.0 - test - - - fr.avianey - bitboard4j - 1.0.0 - test - - - junit - junit - 4.12 - test - - - - - - - release-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.4 - - - sign-artifacts - verify - - sign - - - - - - - - - sonatype-nexus-staging - https://oss.sonatype.org/service/local/staging/deploy/maven2 - - - - - javadoc-8 - - 1.8 - - - -Xdoclint:none - - - - - \ No newline at end of file diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/IA.java b/minimax4j/src/main/java/fr/avianey/minimax4j/IA.java deleted file mode 100644 index 4b3fb30..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/IA.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import java.util.Collection; -import java.util.List; - -/** - * Base interface for minimax and derivated decision rules for two-person - * zero-sum games of perfect information. - * Extend this class to implement IA for several games, such as : - *
    - *
  • Chess
  • - *
  • Reversi
  • - *
  • Checkers
  • - *
  • Go
  • - *
  • Connect Four
  • - *
  • Tic Tac Toe
  • - *
  • ...
  • - *
- * - * @author antoine vianey - * - * @param Implementation of the Move interface to use - */ -public interface IA { - - /** - * Get {@link Move} static evaluations at the given search depth
- * This methods iterates over {@link #getPossibleMoves()} to evaluate each. - * @param depth The search depth (must be > 0) - * @return The list of possible moves in descending evaluation order (best first) - * @see #evaluate() - */ - default List getBestMoves(final int depth) { - return this.getBestMoves(depth, getPossibleMoves()); - } - - /** - * Get {@link Move} static evaluations at the given search depth
- * This methods iterates over provided ordered moves to evaluate each and maximize cutoff. - * @param depth The search depth (must be > 0) - * @param possibleMoves The list of possible moves - * @return The list of possible moves in descending evaluation order (best first) - * @see #evaluate() - */ - List getBestMoves(final int depth, Iterable possibleMoves); - - /** - * Tell weather or not the game is over. - * @return - * True if the game is over - */ - boolean isOver(); - - /** - * Play the given move and modify the state of the game.
- * This function MUST set correctly the turn of the next player - * ... by calling the next() method for example. - * @param move - * The move to play - * @see #next() - */ - void makeMove(M move); - - /** - * Undo the given move and restore the state of the game.
- * This function MUST restore correctly the turn of the previous player - * ... by calling the previous() method for example. - * @param move - * The move to cancel - * @see #previous() - */ - void unmakeMove(M move); - - /** - * List every valid moves for the current player.

- * "Improvement (of the alpha beta pruning) can be achieved without - * sacrificing accuracy, by using ordering heuristics to search parts - * of the tree that are likely to force alpha-beta cutoffs early." - *
- Alpha-beta pruning on Wikipedia - * @return - * The list of the current player possible moves - */ - Iterable getPossibleMoves(); - - /** - * Evaluate the state of the game for the current player after a move. - * The greatest the value is, the better the position of the current player is. - * @return - * The evaluation of the position for the current player - * @see #maxEvaluateValue() - */ - double evaluate(); - - /** - * The absolute maximal value for the evaluate function. - * This value must not be equal to a possible return value of the evaluation function. - * @return - * The non inclusive maximal value - * @see #evaluate() - */ - double maxEvaluateValue(); - - /** - * Change current turn to the next player. - * This method must not be used in conjunction with the makeMove() method. - * Use it to implement a pass functionality. - * @see #makeMove(Move) - */ - void next(); - - /** - * Change current turn to the previous player. - * This method must not be used in conjunction with the unmakeMove() method. - * Use it to implement an undo functionality. - * @see #unmakeMove(Move) - */ - void previous(); - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/IADecorator.java b/minimax4j/src/main/java/fr/avianey/minimax4j/IADecorator.java deleted file mode 100644 index 7936b91..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/IADecorator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import java.util.List; - -public abstract class IADecorator implements IA { - - protected final IA ia; - - public IADecorator(IA ia) { - this.ia = ia; - } - - @Override - public List getBestMoves(int depth) { - return ia.getBestMoves(depth); - } - - @Override - public boolean isOver() { - return ia.isOver(); - } - - @Override - public void makeMove(M move) { - ia.makeMove(move); - } - - @Override - public void unmakeMove(M move) { - ia.unmakeMove(move); - } - - @Override - public Iterable getPossibleMoves() { - return ia.getPossibleMoves(); - } - - @Override - public double evaluate() { - return ia.evaluate(); - } - - @Override - public double maxEvaluateValue() { - return ia.maxEvaluateValue(); - } - - @Override - public void next() { - ia.next(); - } - - @Override - public void previous() { - ia.previous(); - } -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/IAUtils.java b/minimax4j/src/main/java/fr/avianey/minimax4j/IAUtils.java deleted file mode 100644 index 51df854..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/IAUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package fr.avianey.minimax4j; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public final class IAUtils { - - private IAUtils() {} - - public static List iterableToSortedList(Iterable iterable) { - if (iterable instanceof Collection) { - return new ArrayList<>((Collection) iterable); - } - List list = new ArrayList<>(); - for (M m : iterable) { - list.add(m); - } - return list; - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/Move.java b/minimax4j/src/main/java/fr/avianey/minimax4j/Move.java deleted file mode 100644 index 76bab22..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/Move.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import static java.lang.Double.isNaN; -import static java.lang.Math.signum; - -/** - * - * Implement this interface to describe a Move in your game.
- * A typical implementation for a Chess game would be : - *
    - *
  • The color of the piece
  • - *
  • The type of the piece (king, queen, pawn, ...)
  • - *
  • The position before the move
  • - *
  • The position after the move
  • - *
- * Additional information might be necessary to implement the abstract {@link IA#unmakeMove(Move)} method of the {@link IA} class : - *
    - *
  • Taken pieces
  • - *
  • ...
  • - *
- * - * @author antoine vianey - * @see IA#unmakeMove(Move) - * @see IA#makeMove(Move) - * - */ -public abstract class Move implements Comparable { - - public double value = Double.NaN; - - @Override - public int compareTo(Move move) { - if (isNaN(value) && isNaN(move.value)) { - return 0; - } else if (isNaN(value)) { - return -1; - } else if (isNaN(move.value)) { - return 1; - } - return (int) signum(move.value - value); - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/AlphaBeta.java b/minimax4j/src/main/java/fr/avianey/minimax4j/impl/AlphaBeta.java deleted file mode 100644 index 12289f4..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/AlphaBeta.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.impl; - -import fr.avianey.minimax4j.IA; -import fr.avianey.minimax4j.Move; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import static fr.avianey.minimax4j.IAUtils.iterableToSortedList; - -/** - * AlphaBeta based implementation. - * - *
- * function alphabeta(node, depth, α, β, maximizingPlayer)
- *     if depth = 0 or node is a terminal node
- *         return the heuristic value of node
- *     if maximizingPlayer
- *         for each child of node
- *             α := max(α, alphabeta(child, depth - 1, α, β, FALSE))
- *             if β <= α
- *                 break (* β cut-off *)
- *         return a
- *     else
- *         for each child of node
- *             β := min(β, alphabeta(child, depth - 1, α, β, TRUE))
- *             if β <= α
- *                 break (* α cut-off *)
- *         return β
- * 
- * - * Initial call for maximizing player - *
alphabeta(origin, depth, -8, +8, TRUE)
- * - * @author antoine vianey - * - * @param Implementation of the Move interface to use - * @deprecated For testing and documentation purpose only, the preferred way to implement IA is to use {@link Negamax}. - */ -@Deprecated -public abstract class AlphaBeta implements IA { - - @Override - public List getBestMoves(final int depth, Iterable possibleMoves) { - if (depth <= 0) { - throw new IllegalArgumentException("Search depth MUST be > 0"); - } - List orderedMoves = iterableToSortedList(possibleMoves); - alphabeta(orderedMoves, depth, 1, -maxEvaluateValue(), maxEvaluateValue()); - Collections.sort(orderedMoves); - return orderedMoves; - } - - private double alphabeta(final Iterable initialMoves, final int depth, final int who, double alpha, double beta) { - if (depth == 0 || isOver()) { - return who * evaluate(); - } - double score; - Iterator moves = (initialMoves != null ? initialMoves : getPossibleMoves()).iterator(); - if (!moves.hasNext()) { - next(); - score = alphabetaScore(depth, who, alpha, beta); - previous(); - return score; - } - if (who > 0) { - while (moves.hasNext()) { - M move = moves.next(); - makeMove(move); - score = alphabetaScore(depth, who, alpha, beta); - unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score > alpha) { - alpha = score; - if (alpha >= beta) { - break; - } - } - } - return alpha; - } else { - while (moves.hasNext()) { - M move = moves.next(); - makeMove(move); - score = alphabetaScore(depth, who, alpha, beta); - unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score < beta) { - beta = score; - if (alpha >= beta) { - break; - } - } - } - return beta; - } - } - - protected double alphabetaScore(final int depth, final int who, final double alpha, final double beta) { - return alphabeta(null, depth - 1, -who, alpha, beta); - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Minimax.java b/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Minimax.java deleted file mode 100644 index 2ef05ca..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Minimax.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.impl; - -import fr.avianey.minimax4j.IA; -import fr.avianey.minimax4j.Move; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import static fr.avianey.minimax4j.IAUtils.iterableToSortedList; - -/** - * Minimax based implementation. - * - *
- * function minimax(node, depth, maximizingPlayer)
- *     if depth = 0 or node is a terminal node
- *         return the heuristic value of node
- *     if maximizingPlayer
- *         bestValue := -∞
- *         for each child of node
- *             val := minimax(child, depth - 1, FALSE)
- *             bestValue := max(bestValue, val)
- *         return bestValue
- *     else
- *         bestValue := +∞
- *         for each child of node
- *             val := minimax(child, depth - 1, TRUE)
- *             bestValue := min(bestValue, val)
- *         return bestValue
- * 
- * - * Initial call for maximizing player - *
minimax(origin, depth, TRUE)
- * - * @author antoine vianey - * - * @param Implementation of the Move interface to use - * @deprecated For testing and documentation purpose only, the preferred way to implement IA is to use {@link Negamax}. - */ -@Deprecated -public abstract class Minimax implements IA { - - @Override - public List getBestMoves(final int depth, Iterable possibleMoves) { - if (depth <= 0) { - throw new IllegalArgumentException("Search depth MUST be > 0"); - } - List orderedMoves = iterableToSortedList(possibleMoves); - minimax(orderedMoves, depth, 1); - Collections.sort(orderedMoves); - return orderedMoves; - } - - private double minimax(Iterable initialMoves, final int depth, final int who) { - if (depth == 0 || isOver()) { - return who * evaluate(); - } - Iterator moves = (initialMoves != null ? initialMoves : getPossibleMoves()).iterator(); - if (!moves.hasNext()) { - next(); - double score = minimaxScore(depth, who); - previous(); - return score; - } - if (who > 0) { - // max - double score; - double bestScore = -maxEvaluateValue(); - while (moves.hasNext()) { - M move = moves.next(); - makeMove(move); - score = minimaxScore(depth, who); - unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score > bestScore) { - bestScore = score; - } - } - return bestScore; - } else { - // min - double score; - double bestScore = maxEvaluateValue(); - while (moves.hasNext()) { - M move = moves.next(); - makeMove(move); - score = minimaxScore(depth, who); - unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score < bestScore) { - bestScore = score; - } - } - return bestScore; - } - } - - protected double minimaxScore(final int depth, final int who) { - return minimax(null, depth - 1, -who); - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Negamax.java b/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Negamax.java deleted file mode 100644 index 22a6088..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/Negamax.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.impl; - -import fr.avianey.minimax4j.IA; -import fr.avianey.minimax4j.Move; - -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import static fr.avianey.minimax4j.IAUtils.iterableToSortedList; - -/** - * Negamax based implementation. - * - *
- * function negamax(node, depth, color)
- *     if depth = 0 or node is a terminal node
- *         return color * the heuristic value of node
- *     bestValue := -∞
- *     foreach child of node
- *         val := -negamax(child, depth - 1, -color)
- *         bestValue := max( bestValue, val )
- *     return bestValue
- * 
- * - * Initial call for Player A's root node - *
- * rootNegamaxValue := negamax( rootNode, depth, 1)
- * rootMinimaxValue := rootNegamaxValue
- * 
- * - * Initial call for Player B's root node - *
- * rootNegamaxValue := negamax( rootNode, depth, -1)
- * rootMinimaxValue := -rootNegamaxValue
- * 
- * - * This implementation use alpha-beta cut-offs. - * - * @author antoine vianey - * - * @param Implementation of the Move interface to use - */ -public abstract class Negamax implements IA { - - public List getBestMoves(final int depth, Iterable possibleMoves) { - if (depth <= 0) { - throw new IllegalArgumentException("Search depth MUST be > 0"); - } - List orderedMoves = iterableToSortedList(possibleMoves); - negamax(orderedMoves, depth, -maxEvaluateValue(), maxEvaluateValue()); - Collections.sort(orderedMoves); - return orderedMoves; - } - - protected double negamax(Iterable initialMoves, final int depth, double alpha, double beta) { - if (depth == 0 || isOver()) { - return evaluate(); - } - Iterator moves = (initialMoves != null ? initialMoves : getPossibleMoves()).iterator(); - if (!moves.hasNext()) { - next(); - double score = -negamax(null, depth - 1, -beta, -alpha); - previous(); - return score; - } - double score; - while (moves.hasNext()) { - M move = moves.next(); - makeMove(move); - score = -negamax(null, depth - 1, -beta, -alpha); - unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score > alpha) { - alpha = score; - if (alpha >= beta) { - break; - } - } - } - return alpha; - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/ParallelNegamax.java b/minimax4j/src/main/java/fr/avianey/minimax4j/impl/ParallelNegamax.java deleted file mode 100644 index dcbb9ab..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/ParallelNegamax.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.impl; - -import fr.avianey.minimax4j.IA; -import fr.avianey.minimax4j.Move; - -import java.util.*; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.RecursiveTask; - -import static fr.avianey.minimax4j.IAUtils.iterableToSortedList; -import static java.lang.Runtime.getRuntime; - -/** - * A {@link IA} implementation that distribute the tree exploration across processors.
- * - * @param Implementation of the Move interface to use - * @author antoine vianey - */ -public abstract class ParallelNegamax implements IA, Cloneable { - - private ForkJoinPool pool; - - /** - * Creates a new ParallelNegamax using {@link Runtime#availableProcessors()} for parallelism. - */ - public ParallelNegamax() { - this(getRuntime().availableProcessors()); - } - - /** - * Creates a new ParallelNegamax using the given parallelism. - * @param parallelism how many workers should be used for computation - */ - public ParallelNegamax(int parallelism) { - if (parallelism <= 0) { - throw new IllegalArgumentException(this.getClass().getSimpleName() + " MUST use at least one processor."); - } - this.pool = new ForkJoinPool(parallelism); - } - - /** - * Creates a new IA with the same parallelism as the given instance.
- * This constructor SHOULD be used when creating clones as it skip {@link ForkJoinPool} configuration. - * @param from - */ - protected ParallelNegamax(ParallelNegamax from) { - this(from.pool.getParallelism()); - } - - /** - * Get the best {@link Move} for the given search depth
- * This method SHOULD be called from one thread at the time. - * @param depth The search depth (must be > 0) - * @return The best possible move - */ - public List getBestMoves(final int depth, Iterable possibleMoves) { - if (depth <= 0) { - throw new IllegalArgumentException("Search depth MUST be > 0"); - } - List orderedMoves = iterableToSortedList(possibleMoves); - pool.invoke(new NegamaxAction<>(this, orderedMoves, null, depth, -maxEvaluateValue(), maxEvaluateValue())); - Collections.sort(orderedMoves); - return orderedMoves; - } - - @Override - public abstract ParallelNegamax clone(); - - private static final class NegamaxAction extends RecursiveTask { - - private static final long serialVersionUID = 1L; - - private final List initialMoves; - private final ParallelNegamax minimax; - private final M move; - private final int depth; - private final double alpha; - private final double beta; - - NegamaxAction(ParallelNegamax minimax, List initialMoves, M move, int depth, double alpha, double beta) { - this.initialMoves = initialMoves; - this.move = move; - this.depth = depth; - this.minimax = minimax; - this.alpha = alpha; - this.beta = beta; - } - - @Override - protected Double compute() { - return negamax(initialMoves, depth, alpha, beta); - } - - private double negamax(final Iterable initialMoves, final int depth, double alpha, double beta) { - if (depth == 0 || minimax.isOver()) { - return minimax.evaluate(); - } - Iterator moves = (initialMoves != null ? initialMoves : minimax.getPossibleMoves()).iterator(); - if (moves.hasNext()) { - // young brother wait - // reduce alpha beta window - // assume its the best possible move - M move = moves.next(); - minimax.makeMove(move); - double score = -negamax(null, depth - 1, -beta, -alpha); - minimax.unmakeMove(move); - if (initialMoves != null) { - move.value = score; - } - if (score > alpha) { - alpha = score; - if (alpha >= beta) { - // cutoff - return alpha; - } - } - if (moves.hasNext()) { - Collection> tasks = new LinkedList<>(); - do { - // create sub tree exploration tasks - move = moves.next(); - ParallelNegamax clone = minimax.clone(); - clone.makeMove(move); - tasks.add(new NegamaxAction<>(clone, null, move, depth - 1, -beta, -alpha)); - } while (moves.hasNext()); - // dispatch tasks across workers - // and wait for completion... - invokeAll(tasks); - // await termination of all brothers - // once all done alpha == best score - for (NegamaxAction task : tasks) { - score = -task.getRawResult(); - if (initialMoves != null) { - task.move.value = score; - } - if (score > alpha) { - alpha = score; - if (alpha >= beta) { - // task lead to a cutoff... - // we don't care of other brothers - break; - } - } - } - } - } else { - minimax.next(); - alpha = -negamax(null, depth - 1, -beta, -alpha); - minimax.previous(); - } - // sub tree done ! - return alpha; - } - - } - -} diff --git a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/TranspositionNegamax.java b/minimax4j/src/main/java/fr/avianey/minimax4j/impl/TranspositionNegamax.java deleted file mode 100644 index 1e2f1b4..0000000 --- a/minimax4j/src/main/java/fr/avianey/minimax4j/impl/TranspositionNegamax.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.impl; - -import fr.avianey.minimax4j.Move; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.*; - -import static fr.avianey.minimax4j.IAUtils.iterableToSortedList; - -/** - * Negamax based with transposition table implementation. - * - * @author antoine vianey - * - * @param Implementation of the Move interface to use - * @param The key used for the transposition table - * @param An optional {@link Comparable} use to group transpositions - */ -public abstract class TranspositionNegamax extends Negamax { - - protected static final int FLAG_EXACT = 0; - protected static final int FLAG_UPPERBOUND = 1; - protected static final int FLAG_LOWERBOUND = 2; - - protected static class Transposition { - private final double value; - private final int depth; - private final int flag; - private final K key; - - protected Transposition(double value, int depth, int flag, K key) { - this.value = value; - this.depth = depth; - this.flag = flag; - this.key = key; - } - } - - public interface TranspositionTableFactory { - Map> newTranspositionTable(); - } - - private final transient TreeMap>> transpositionTableMap; - private final transient TranspositionTableFactory transpositionTableFactory; - - public TranspositionNegamax() { - this(new TranspositionTableFactory() { - @Override - public Map> newTranspositionTable() { - return new HashMap<>(); - } - }); - } - - public TranspositionNegamax(final int initialCapacity) { - this(new TranspositionTableFactory() { - @Override - public Map> newTranspositionTable() { - return new HashMap<>(initialCapacity); - } - }); - } - - public TranspositionNegamax(final int initialCapacity, final float loadFactor) { - this(new TranspositionTableFactory() { - @Override - public Map> newTranspositionTable() { - return new HashMap<>(initialCapacity, loadFactor); - } - }); - } - - public TranspositionNegamax(TranspositionTableFactory transpositionTableFactory) { - super(); - this.transpositionTableFactory = transpositionTableFactory; - this.transpositionTableMap = initTranspositionTableMap(); - } - - - /** - * Initialize the map of transposition table classified by groups. - * @return - * A {@link TreeMap} storing transposition tables by group - */ - @SuppressWarnings("unchecked") - private TreeMap>> initTranspositionTableMap() { - Type t = getClass().getGenericSuperclass(); - // search for the Group class within class hierarchy - while (!(t instanceof ParameterizedType - && TranspositionNegamax.class.getSimpleName().equals( - ((Class) ((ParameterizedType) t).getRawType()).getSimpleName()))) { - t = ((Class) t).getGenericSuperclass(); - } - Class cls = (Class) ((ParameterizedType) t).getActualTypeArguments()[2]; - if (Comparable.class.isAssignableFrom(cls)) { - // the transposition Group type is Comparable - return new TreeMap<>(); - } else if (cls.isAssignableFrom(Void.class)) { - // no transposition Group required - // use everything-is-equal Comparator - return new TreeMap<>(new Comparator() { - @Override - public int compare(G o1, G o2) { - return 0; - } - }); - } else { - throw new IllegalArgumentException("The transposition group type : " + cls.getSimpleName() + " is neither Void nor implement the java.lang.Comparable interface."); - } - } - - private void clearGroups(G currentGroup) { - if (currentGroup != null) { - // free memory : - // evict unnecessary transpositions - transpositionTableMap.headMap(currentGroup).clear(); - } - } - - /** - * Reset the content of the transposition table. - * The preferred way to free memory is to use the grouping functionality. - * - * @see #getGroup() - */ - public final void clearTranspositions() { - transpositionTableMap.clear(); - } - - /** - * Returns the current configuration key.
- * Implementation MUST override the {@link #hashCode()} and {@link #equals(Object)} methods. - * A Zobrist hashing could be use to provide - * the hash value of the transposition key. Equality between key will be used to check for collision when - * different configurations map to the same hash value. - *
- *
{@link #hashCode()}
- *
- * Should be tuned to adjust the number of entry in the transposition table as well as its memory footprint. - * Increasing the number of possible hashCode values will allow more transpositions and consume more memory. - *
- *
{@link #equals(Object)}
- *
- * Might be tuned to avoid using an invalid transposition du to collisions in the transposition table. - *
- *
- * Use {@link #saveTransposition(Object, Transposition, double, int, int)} to implement replacement strategy. - * - * @see #saveTransposition(Object, Transposition, double, int, int) - * @return - * The key representing the current configuration. - * MUST be non null and preferably immutable. - */ - public abstract K getTranspositionKey(); - - /** - * Represent the group in which the current transposition belong.
- * Groups can be use to lower the number of transposition stored in memory : - *
- *
Reversi
- *
Transpositions can be grouped by number of discs on board
- *
Chess
- *
Transpositions can be grouped by number of left pieces of each color on the board
- *
Connect Four
- *
Transpositions can be grouped by number of dropped discs
- *
- * Groups MUST be ordered such as when the current configuration hash belong to group - * G1, transpositions that belongs to groups G < G1 can be removed... If you don't want to - * handle groups, let G be {@link Void} and return null. - * - * @return - * The group for the current position - */ - public abstract G getGroup(); - - /** - * Save the transposition for the current position using a default strategy: - *
    - *
  • existing transposition is null
  • - *
  • existing transposition depth is lower than the remaining depth
  • - *
- * Override this method to implement your own replacement strategy using additional criteria such as ancient, - * - * @param key the transposition key for the current configuration - * @param transposition the existing transposition for the given key hash (or null if no transposition exists) - * @param score the evaluation for the given depth - * @param depth the depth of the searched subtree (aka remaining depth) - * @param flag type of evaluation {@link #FLAG_EXACT}, {@link #FLAG_LOWERBOUND}, {@link #FLAG_UPPERBOUND} - */ - protected void saveTransposition(final K key, final Transposition transposition, final double score, final int depth, final int flag) { - if (transposition == null || transposition.depth <= depth) { - getTranspositionTable().put(key.hashCode(), new Transposition(score, depth, flag, key)); - } - } - - private Map> getTranspositionTable() { - Map> transpositionTable = transpositionTableMap.get(getGroup()); - if (transpositionTable == null) { - transpositionTable = transpositionTableFactory.newTranspositionTable(); - transpositionTableMap.put(getGroup(), transpositionTable); - } - return transpositionTable; - } - - @Override - public List getBestMoves(final int depth, Iterable possibleMoves) { - if (depth <= 0) { - throw new IllegalArgumentException("Search depth MUST be > 0"); - } - List orderedMoves = iterableToSortedList(possibleMoves); - super.negamax(orderedMoves, depth, -maxEvaluateValue(), maxEvaluateValue()); - // clear useless groups - clearGroups(getGroup()); - Collections.sort(orderedMoves); - return orderedMoves; - } - - @Override - protected double negamax(final Iterable possibleMoves, final int depth, final double alpha, final double beta) { - double a = alpha; - double b = beta; - K key = getTranspositionKey(); - Transposition transposition = getTranspositionTable().get(key.hashCode()); - if (transposition != null && depth <= transposition.depth && key.equals(transposition.key)) { - switch (transposition.flag) { - case FLAG_EXACT: - // transposition has a deeper or equal search depth - // we can stop here as we already know the value - // returned by the evaluation function - return transposition.value; - case FLAG_UPPERBOUND: - if (transposition.value < beta) { - b = transposition.value; - } - break; - case FLAG_LOWERBOUND: - if (transposition.value > alpha) { - a = transposition.value; - } - break; - } - if (a >= b) { - return transposition.value; - } - } - - double score = super.negamax(possibleMoves, depth, a, b); - - if (score <= a) { - saveTransposition(key, transposition, score, depth, FLAG_UPPERBOUND); - } else if (score >= beta) { - saveTransposition(key, transposition, score, depth, FLAG_LOWERBOUND); - } else { - saveTransposition(key, transposition, score, depth, FLAG_EXACT); - } - - return score; - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/BestMoveTest.java b/minimax4j/src/test/java/fr/avianey/minimax4j/BestMoveTest.java deleted file mode 100644 index b3c69e3..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/BestMoveTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import fr.avianey.minimax4j.ia.*; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.Parameterized; -import org.junit.runners.Parameterized.Parameters; - -import java.util.Arrays; -import java.util.Collection; - -import static org.junit.Assert.assertEquals; - -@RunWith(Parameterized.class) -public class BestMoveTest { - - private final int depth; - private final IA IA; - - public BestMoveTest(int depth, IA IA) { - this.depth = depth; - this.IA = IA; - } - - @Parameters - public static Collection params() { - return Arrays.asList( - // IA - new Object[]{1, new BaseMinimax()}, - new Object[]{2, new BaseMinimax()}, - new Object[]{3, new BaseMinimax()}, - new Object[]{1, new BaseAlphaBeta()}, - new Object[]{2, new BaseAlphaBeta()}, - new Object[]{3, new BaseAlphaBeta()}, - new Object[]{1, new BaseNegamax()}, - new Object[]{2, new BaseNegamax()}, - new Object[]{3, new BaseNegamax()}, - // parallel IA - new Object[]{1, new BaseParallelNegamax()}, - new Object[]{2, new BaseParallelNegamax()}, - new Object[]{3, new BaseParallelNegamax()}, - // transposition IA - new Object[]{1, new TranspositionNegamaxNoCollision()}, - new Object[]{2, new TranspositionNegamaxNoCollision()}, - new Object[]{3, new TranspositionNegamaxNoCollision()} - //new Object[]{4, new TranspositionNegamaxNoCollision()} - ); - } - - @Test - public void shouldBestMoveAlwaysReturnLastAvailableCell() { - int cell = Logic.GRID_SIZE - 1; - while (!IA.isOver()) { - IAMove move = IA.getBestMoves(depth).get(0); - assertEquals("Best move must be highest available position in grid.", cell, move.getPosition()); - IA.makeMove(move); - cell--; - } - assertEquals("When over, all cell should be taken.", -1, cell); - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ParallelSpeedTest.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ParallelSpeedTest.java deleted file mode 100644 index b2db8c7..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ParallelSpeedTest.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import com.google.common.base.Stopwatch; -import fr.avianey.minimax4j.impl.Negamax; -import fr.avianey.minimax4j.impl.ParallelNegamax; - -import java.util.AbstractList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -public class ParallelSpeedTest { - - private static final int TURNS = 64; - private static final int COST = 1; // 1 ms - private static final String FORMAT = "|\t%s\t|\t%s\t|\t%d\t|\t%d\t|\t%d\t|\t%d\t|\t%d\t|\t%d\t|\t%d\t|\t%d\t|"; - - private TestIA ia; - - private final int depth; - - public static Collection params() { - return Arrays.asList( - new Object[]{NegamaxIA.class, 3, 4, 1, 1, 1, 1, 1, 1}, - new Object[]{NegamaxIA.class, 3, 4, 2, 1, 1, 1, 1, 1}, - new Object[]{NegamaxIA.class, 3, 4, 1, 2, 1, 1, 1, 1}, - new Object[]{NegamaxIA.class, 3, 4, 1, 1, 2, 1, 1, 1}, - new Object[]{NegamaxIA.class, 3, 4, 1, 1, 1, 2, 1, 1}, - new Object[]{NegamaxIA.class, 3, 4, 1, 1, 1, 1, 2, 1}, - new Object[]{NegamaxIA.class, 3, 4, 1, 1, 1, 1, 1, 2}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 1, 1, 1, 1, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 2, 1, 1, 1, 1, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 2, 1, 1, 1, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 1, 2, 1, 1, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 1, 1, 2, 1, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 1, 1, 1, 2, 1}, - new Object[]{ParallelTestIA.class, 3, 4, 1, 1, 1, 1, 1, 2} - ); - } - - public static void main(String[] args) throws InstantiationException, IllegalAccessException { - for (Object[] params : params()) { - ParallelSpeedTest speedTest = new ParallelSpeedTest( - (Class>) params[0], - (int) params[1], (int) params[2], - (long) params[3], (long) params[5], (long) params[5], - (long) params[6], (long) params[7], (long) params[8]); - speedTest.warmup(); - speedTest.run(); - } - } - - public ParallelSpeedTest(Class> iaClass, - int depth, int branchingFactor, - long getPossibleMovesCost, long makeMoveCost, long unmakeMoveCost, - long evaluateCost, long nextPreviousCost, long cloneCost) { - this.depth = depth; - if (NegamaxIA.class.equals(iaClass)) { - ia = new NegamaxIA(branchingFactor, - COST * makeMoveCost, COST * unmakeMoveCost, - COST * getPossibleMovesCost, COST * evaluateCost, - COST * nextPreviousCost, COST * cloneCost); - } - if (ParallelTestIA.class.equals(iaClass)) { - ia = new ParallelTestIA(branchingFactor, - COST * makeMoveCost, COST * unmakeMoveCost, - COST * getPossibleMovesCost, COST * evaluateCost, - COST * nextPreviousCost, COST * cloneCost); - } - } - - public void warmup() throws IllegalAccessException, InstantiationException { - ia.clear(); - dryRun((IA) ia); - } - - public void run() throws IllegalAccessException, InstantiationException { - Stopwatch watch = Stopwatch.createStarted(); - ia.clear(); - dryRun((IA) ia); - watch.stop(); - System.out.println(String.format(FORMAT, ia.getClass().getSuperclass().getSimpleName(), watch, - depth, - ia.getBranchingFactor(), - ia.getGetPossibleMovesCost(), - ia.getMakeMoveCost(), - ia.getUnmakeMoveCost(), - ia.getEvaluateCost(), - ia.getNextPreviousCost(), - ia.getCloneCost())); - } - - private void dryRun(IA IA) { - while (!IA.isOver()) { - VoidMove move = IA.getBestMoves(depth).get(0); - IA.makeMove(move); - } - } - - private static class VoidMove extends Move {} - - private static class VoidMoves extends AbstractList { - - private final VoidMove move = new VoidMove(); - private final int size; - - private VoidMoves(int size) { - this.size = size; - } - - @Override - public VoidMove get(int i) { - return move; - } - - @Override - public int size() { - return size; - } - } - - private interface TestIA { - - int getBranchingFactor(); - - long getMakeMoveCost(); - - long getUnmakeMoveCost(); - - long getGetPossibleMovesCost(); - - long getEvaluateCost(); - - long getNextPreviousCost(); - - long getCloneCost(); - - void clear(); - } - - private static class NegamaxIA extends Negamax implements TestIA { - - private final int branchingFactor; - private final long makeMoveCost; - private final long unmakeMoveCost; - private final long getPossibleMovesCost; - private final long evaluateCost; - private final long nextPreviousCost; - private final long cloneCost; - - private int turn = 0; - - public NegamaxIA(int branchingFactor, - long makeMoveCost, long unmakeMoveCost, long getPossibleMovesCost, - long evaluateCost, long nextPreviousCost, long cloneCost) { - this.branchingFactor = branchingFactor; - this.makeMoveCost = makeMoveCost; - this.unmakeMoveCost = unmakeMoveCost; - this.getPossibleMovesCost = getPossibleMovesCost; - this.evaluateCost = evaluateCost; - this.nextPreviousCost = nextPreviousCost; - this.cloneCost = cloneCost; - } - - public void clear() { - this.turn = 0; - } - - @Override - public boolean isOver() { - return turn == TURNS; - } - - @Override - public void makeMove(VoidMove move) { - simulateCost(makeMoveCost); - turn++; - } - - @Override - public void unmakeMove(VoidMove move) { - simulateCost(unmakeMoveCost); - turn--; - } - - @Override - public List getPossibleMoves() { - simulateCost(getPossibleMovesCost); - return new VoidMoves(branchingFactor); - } - - @Override - public double evaluate() { - simulateCost(evaluateCost); - return 0; - } - - @Override - public double maxEvaluateValue() { - return Integer.MAX_VALUE; - } - - @Override - public void next() { - simulateCost(nextPreviousCost); - } - - @Override - public void previous() { - simulateCost(nextPreviousCost); - } - - @Override - public int getBranchingFactor() { - return branchingFactor; - } - - @Override - public long getMakeMoveCost() { - return makeMoveCost; - } - - @Override - public long getUnmakeMoveCost() { - return unmakeMoveCost; - } - - @Override - public long getGetPossibleMovesCost() { - return getPossibleMovesCost; - } - - @Override - public long getEvaluateCost() { - return evaluateCost; - } - - @Override - public long getNextPreviousCost() { - return nextPreviousCost; - } - - @Override - public long getCloneCost() { - return cloneCost; - } - } - - private static class ParallelTestIA extends ParallelNegamax implements TestIA { - - private final int branchingFactor; - private final long makeMoveCost; - private final long unmakeMoveCost; - private final long getPossibleMovesCost; - private final long evaluateCost; - private final long nextPreviousCost; - private final long cloneCost; - - private int turn = 0; - - public ParallelTestIA(int branchingFactor, - long makeMoveCost, long unmakeMoveCost, long getPossibleMovesCost, - long evaluateCost, long nextPreviousCost, long cloneCost) { - this.branchingFactor = branchingFactor; - this.makeMoveCost = makeMoveCost; - this.unmakeMoveCost = unmakeMoveCost; - this.getPossibleMovesCost = getPossibleMovesCost; - this.evaluateCost = evaluateCost; - this.nextPreviousCost = nextPreviousCost; - this.cloneCost = cloneCost; - } - - public void clear() { - this.turn = 0; - } - - @Override - public boolean isOver() { - return turn == TURNS; - } - - @Override - public void makeMove(VoidMove move) { - simulateCost(makeMoveCost); - turn++; - } - - @Override - public void unmakeMove(VoidMove move) { - simulateCost(unmakeMoveCost); - turn--; - } - - @Override - public List getPossibleMoves() { - simulateCost(getPossibleMovesCost); - return new VoidMoves(branchingFactor); - } - - @Override - public double evaluate() { - simulateCost(evaluateCost); - return 0; - } - - @Override - public double maxEvaluateValue() { - return Integer.MAX_VALUE; - } - - @Override - public void next() { - simulateCost(nextPreviousCost); - } - - @Override - public void previous() { - simulateCost(nextPreviousCost); - } - - @Override - public ParallelNegamax clone() { - simulateCost(cloneCost); - ParallelTestIA ia = new ParallelTestIA(branchingFactor, makeMoveCost, unmakeMoveCost, getPossibleMovesCost, evaluateCost, nextPreviousCost, cloneCost); - ia.turn = turn; - return ia; - } - - @Override - public int getBranchingFactor() { - return branchingFactor; - } - - @Override - public long getMakeMoveCost() { - return makeMoveCost; - } - - @Override - public long getUnmakeMoveCost() { - return unmakeMoveCost; - } - - @Override - public long getGetPossibleMovesCost() { - return getPossibleMovesCost; - } - - @Override - public long getEvaluateCost() { - return evaluateCost; - } - - @Override - public long getNextPreviousCost() { - return nextPreviousCost; - } - - @Override - public long getCloneCost() { - return cloneCost; - } - } - - private static void simulateCost(long cost) { - try { - Thread.sleep(cost); - } catch (InterruptedException e) { - // ignore - } - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/TranspositionSpeedTest.java b/minimax4j/src/test/java/fr/avianey/minimax4j/TranspositionSpeedTest.java deleted file mode 100644 index 3823ab5..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/TranspositionSpeedTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j; - -import com.google.common.base.Stopwatch; -import fr.avianey.minimax4j.ia.BaseNegamax; -import fr.avianey.minimax4j.ia.Cleanable; -import fr.avianey.minimax4j.ia.IAMove; -import fr.avianey.minimax4j.ia.TranspositionNegamaxNoCollision; - -import java.util.Arrays; -import java.util.Collection; - -public class TranspositionSpeedTest { - - private static final String FORMAT = "|\t%s\t|\t%s\t|\t%d\t|"; - - private IA ia; - - private final int depth; - - public static Collection params() { - return Arrays.asList( - new Object[]{BaseNegamax.class, 3}, - new Object[]{TranspositionNegamaxNoCollision.class, 3} - ); - } - - public static void main(String[] args) throws InstantiationException, IllegalAccessException { - for (Object[] params : params()) { - TranspositionSpeedTest speedTest = new TranspositionSpeedTest( - (Class>) params[0], - (int) params[1]); - speedTest.warmup(); - speedTest.run(); - } - } - - public TranspositionSpeedTest(Class> iaClass, int depth) throws IllegalAccessException, InstantiationException { - this.depth = depth; - ia = iaClass.newInstance(); - } - - public void warmup() throws IllegalAccessException, InstantiationException { - dryRun((IA) ia); - } - - public void run() throws IllegalAccessException, InstantiationException { - Stopwatch watch = Stopwatch.createStarted(); - ((Cleanable) ia).clean(); - dryRun((IA) ia); - watch.stop(); - System.out.println(String.format(FORMAT, - ia.getClass().getSuperclass().getSimpleName(), - watch, - depth)); - } - - private void dryRun(IA IA) { - while (!IA.isOver()) { - IA.makeMove(IA.getBestMoves(depth).get(0)); - } - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseAlphaBeta.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseAlphaBeta.java deleted file mode 100644 index a8f05f5..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseAlphaBeta.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.impl.AlphaBeta; - -public class BaseAlphaBeta extends AlphaBeta implements Cleanable { - - private final Logic logic; - private final BaseState state; - - public BaseAlphaBeta() { - logic = new Logic(); - state = new BaseState(); - } - - @Override - public void clean() { - state.clean(); - } - - @Override - public boolean isOver() { - return logic.isOver(state); - } - - @Override - public void makeMove(IAMove move) { - state.makeMove(move); - } - - @Override - public void unmakeMove(IAMove move) { - state.unmakeMove(move); - } - - @Override - public Iterable getPossibleMoves() { - return logic.getPossibleMoves(state); - } - - @Override - public double evaluate() { - return logic.evaluate(state); - } - - @Override - public double maxEvaluateValue() { - return logic.maxEvaluateValue(); - } - - @Override - public void next() { - state.next(); - } - - @Override - public void previous() { - state.previous(); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseMinimax.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseMinimax.java deleted file mode 100644 index c415acb..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseMinimax.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.impl.Minimax; - -/** - * Basic IA to test behaviour and speed of the various implementations. - * We simulate a game where each cell of a 8x8 grid has a score corresponding - * to its index in the grid. When the grid is filled by the players, the winner - * is the player with the highest score. Each move score the value of the cell + - * a fraction of the value depending of the turn in the game so that the IA is - * expected to always play the cell with the highest value... - * - * @author antoine vianey - */ -public class BaseMinimax extends Minimax implements Cleanable { - - private final Logic logic; - private final BaseState state; - - public BaseMinimax() { - logic = new Logic(); - state = new BaseState(); - } - - @Override - public void clean() { - state.clean(); - } - - @Override - public boolean isOver() { - return logic.isOver(state); - } - - @Override - public void makeMove(IAMove move) { - state.makeMove(move); - } - - @Override - public void unmakeMove(IAMove move) { - state.unmakeMove(move); - } - - @Override - public Iterable getPossibleMoves() { - return logic.getPossibleMoves(state); - } - - @Override - public double evaluate() { - return logic.evaluate(state); - } - - @Override - public double maxEvaluateValue() { - return logic.maxEvaluateValue(); - } - - @Override - public void next() { - state.next(); - } - - @Override - public void previous() { - state.previous(); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseNegamax.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseNegamax.java deleted file mode 100644 index 9d238a0..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseNegamax.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.impl.Negamax; - -public class BaseNegamax extends Negamax implements Cleanable { - - private final Logic logic; - private final BaseState state; - - public BaseNegamax() { - logic = new Logic(); - state = new BaseState(); - } - - @Override - public void clean() { - state.clean(); - } - - @Override - public boolean isOver() { - return logic.isOver(state); - } - - @Override - public void makeMove(IAMove move) { - state.makeMove(move); - } - - @Override - public void unmakeMove(IAMove move) { - state.unmakeMove(move); - } - - @Override - public Iterable getPossibleMoves() { - return logic.getPossibleMoves(state); - } - - @Override - public double evaluate() { - return logic.evaluate(state); - } - - @Override - public double maxEvaluateValue() { - return logic.maxEvaluateValue(); - } - - @Override - public void next() { - state.next(); - } - - @Override - public void previous() { - state.previous(); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseParallelNegamax.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseParallelNegamax.java deleted file mode 100644 index 0c4d908..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseParallelNegamax.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.impl.ParallelNegamax; - -/** - * Parallel version of the test {@code BasicMinimax}. - * - * @author antoine vianey - */ -public class BaseParallelNegamax extends ParallelNegamax implements Cleanable { - - private final Logic logic; - private final BaseState state; - - public BaseParallelNegamax() { - logic = new Logic(); - state = new BaseState(); - } - - private BaseParallelNegamax(BaseParallelNegamax ia) { - super(ia); - logic = ia.logic; - state = ia.state.clone(); - } - - @Override - public void clean() { - state.clean(); - } - - @Override - public ParallelNegamax clone() { - return new BaseParallelNegamax(this); - } - - @Override - public boolean isOver() { - return logic.isOver(state); - } - - @Override - public void makeMove(IAMove move) { - state.makeMove(move); - } - - @Override - public void unmakeMove(IAMove move) { - state.unmakeMove(move); - } - - @Override - public Iterable getPossibleMoves() { - return logic.getPossibleMoves(state); - } - - @Override - public double evaluate() { - return logic.evaluate(state); - } - - @Override - public double maxEvaluateValue() { - return logic.maxEvaluateValue(); - } - - @Override - public void next() { - state.next(); - } - - @Override - public void previous() { - state.previous(); - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseState.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseState.java deleted file mode 100644 index e8c8537..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/BaseState.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import java.util.Arrays; - -import static fr.avianey.minimax4j.ia.Logic.EMPTY_CELL; -import static fr.avianey.minimax4j.ia.Logic.GRID_SIZE; -import static fr.avianey.minimax4j.ia.Logic.SIZE; - -/** - * Wrapper to reuse state across IA implementations. - * This class IS NOT safe to use in multiple concurrent threads. - * - * @author antoine vianey - */ -class BaseState implements Cleanable { - - protected final int[] grid = new int[GRID_SIZE]; - protected int turn; - protected int currentPlayer; - - BaseState() { - Arrays.fill(grid, EMPTY_CELL); - } - - @Override - public void clean() { - Arrays.fill(grid, EMPTY_CELL); - turn = 0; - currentPlayer = 0; - } - - // for parallel minimax - @Override - public BaseState clone() { - BaseState clone = new BaseState(); - clone.turn = turn; - clone.currentPlayer = currentPlayer; - System.arraycopy(grid, 0, clone.grid, 0, GRID_SIZE); - return clone; - } - - void makeMove(IAMove move) { - // take position - grid[move.getPosition()] = currentPlayer; - turn++; - // move to next player - next(); - } - - void unmakeMove(IAMove move) { - // free position - grid[move.getPosition()] = EMPTY_CELL; - turn--; - // restore previous player - previous(); - } - - void next() { - currentPlayer++; - if (currentPlayer > 1) { - currentPlayer = 0; - } - } - - void previous() { - currentPlayer--; - if (currentPlayer < 0) { - currentPlayer = 1; - } - } - - int[] getGrid() { - return grid; - } - - int getTurn() { - return turn; - } - - int getCurrentPlayer() { - return currentPlayer; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - int n = 0; - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - sb.append(grid[n++] == 0 ? 'O' : 'X'); - } - sb.append('\n'); - } - return sb.toString(); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Cleanable.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Cleanable.java deleted file mode 100644 index 38846f8..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Cleanable.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -public interface Cleanable { - - void clean(); - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/IAMove.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/IAMove.java deleted file mode 100644 index e5bfc8a..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/IAMove.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.Move; - -public final class IAMove extends Move { - - private final int position; - - public IAMove(int position) { - this.position = position; - } - - public int getPosition() { - return position; - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Logic.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Logic.java deleted file mode 100644 index d1dde2d..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/Logic.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import java.util.LinkedList; -import java.util.List; - -/** - * Stateless Wrapper to reuse logic across IA implementations. - * This class IS safe to use in multiple concurrent threads. - * - * @author antoine vianey - */ -public final class Logic { - - public static final int SIZE = 8; - public static final int GRID_SIZE = SIZE * SIZE; - - static final int MAX_SCORE = ((GRID_SIZE - 1) * GRID_SIZE) / 2; - static final int EMPTY_CELL = -1; - static final int[] GRID_VALUES = new int[GRID_SIZE]; - static { - for (int i = 0; i < GRID_SIZE; i++) { - GRID_VALUES[i] = i + 1; - } - } - - Logic() {} - - boolean isOver(BaseState state) { - return state.getTurn() == GRID_SIZE; - } - - List getPossibleMoves(BaseState state) { - LinkedList moves = new LinkedList<>(); - int index = 0; - for (double cell : state.getGrid()) { - if (cell == EMPTY_CELL) { - moves.add(new IAMove(index)); - } - index++; - } - return moves; - } - - double evaluate(BaseState state) { - if (isOver(state)) { - // check win - int[] scores = new int[2]; - int index = 0; - for (int cell : state.getGrid()) { - if (cell != EMPTY_CELL) { - scores[cell] += GRID_VALUES[index]; - } - index++; - } - for (int i = 0; i < 2; i++) { - if (i != state.getCurrentPlayer() && scores[state.getCurrentPlayer()] < scores[i]) { - // player i win - return -MAX_SCORE + scores[state.getCurrentPlayer()]; - } - } - // current player win - return MAX_SCORE + scores[state.getCurrentPlayer()]; - } - - // maximize position - int diff = 0; - int index = 0; - for (int cell : state.getGrid()) { - if (cell == state.getCurrentPlayer()) { - // current player cell - diff += GRID_VALUES[index]; - } else if (cell != EMPTY_CELL) { - // opponent cell - diff -= GRID_VALUES[index]; - } - index++; - } - - return diff; - } - - double maxEvaluateValue() { - return Integer.MAX_VALUE; - } - -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionNegamaxNoCollision.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionNegamaxNoCollision.java deleted file mode 100644 index b27e13a..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionNegamaxNoCollision.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.minimax4j.impl.TranspositionNegamax; - -import java.util.List; - -public class TranspositionNegamaxNoCollision extends TranspositionNegamax implements Cleanable { - - private final Logic logic; - private final TranspositionStateNoCollision state; - - public TranspositionNegamaxNoCollision() { - logic = new Logic(); - state = new TranspositionStateNoCollision(); - } - - @Override - public TranspositionStateNoCollision.NoCollision getTranspositionKey() { - return state.getTranspositionValue(); - } - - @Override - public Integer getGroup() { - return state.getGroup(); - } - - @Override - public void clean() { - state.clean(); - } - - @Override - public boolean isOver() { - return logic.isOver(state); - } - - @Override - public void makeMove(IAMove move) { - state.makeMove(move); - } - - @Override - public void unmakeMove(IAMove move) { - state.unmakeMove(move); - } - - @Override - public List getPossibleMoves() { - return logic.getPossibleMoves(state); - } - - @Override - public double evaluate() { - return logic.evaluate(state); - } - - @Override - public double maxEvaluateValue() { - return logic.maxEvaluateValue(); - } - - @Override - public void next() { - state.next(); - } - - @Override - public void previous() { - state.previous(); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionState.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionState.java deleted file mode 100644 index 4d2cc10..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionState.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.bitboard4j.hash.ZobristHashing; - -import static fr.avianey.minimax4j.ia.Logic.GRID_SIZE; - -class TranspositionState extends BaseState { - - protected final ZobristHashing hash; - - TranspositionState() { - super(); - hash = new ZobristHashing(2, GRID_SIZE); - } - - @Override - public void clean() { - super.clean(); - hash.reset(); - } - - Integer getTranspositionValue() { - return hash.hashCode(); - } - - Integer getGroup() { - return turn; - } - - @Override - void makeMove(IAMove move) { - hash.add(currentPlayer, move.getPosition()); - super.makeMove(move); - } - - @Override - void unmakeMove(IAMove move) { - super.unmakeMove(move); - hash.remove(currentPlayer, move.getPosition()); - } -} diff --git a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionStateNoCollision.java b/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionStateNoCollision.java deleted file mode 100644 index 573f105..0000000 --- a/minimax4j/src/test/java/fr/avianey/minimax4j/ia/TranspositionStateNoCollision.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of minimax4j. - * - * - * The MIT License (MIT) - * - * Copyright (c) 2015 Antoine Vianey - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package fr.avianey.minimax4j.ia; - -import fr.avianey.bitboard4j.hash.ZobristHashing; - -import static fr.avianey.minimax4j.ia.Logic.GRID_SIZE; - -class TranspositionStateNoCollision extends BaseState { - - public static class NoCollision { - private final int hash; - private final int[] grid; - - public NoCollision(int hash, int[] grid) { - this.hash = hash; - this.grid = new int[grid.length]; - System.arraycopy(grid, 0, this.grid, 0, grid.length); - } - - @Override - public boolean equals(Object o) { - NoCollision other = ((NoCollision) o); - if (other.hash != hash) { - return false; - } - for (int i = grid.length - 1; i >= 0; i--) { - if (grid[i] != other.grid[i]) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - return hash & 0xFFFF; - } - } - - protected final ZobristHashing hash; - - TranspositionStateNoCollision() { - super(); - hash = new ZobristHashing(2, GRID_SIZE); - } - - @Override - public void clean() { - super.clean(); - hash.reset(); - } - - NoCollision getTranspositionValue() { - return new NoCollision(hash.hashCode(), super.grid); - } - - Integer getGroup() { - return turn; - } - - @Override - void makeMove(IAMove move) { - hash.add(currentPlayer, move.getPosition()); - super.makeMove(move); - } - - @Override - void unmakeMove(IAMove move) { - super.unmakeMove(move); - hash.remove(currentPlayer, move.getPosition()); - } -} diff --git a/overview-tree.html b/overview-tree.html new file mode 100644 index 0000000..8a487a0 --- /dev/null +++ b/overview-tree.html @@ -0,0 +1,145 @@ + + + + + + +Class Hierarchy (minimax4j 1.0.0 API) + + + + + + + +
+ + + + + +
+ + +
+

Hierarchy For All Packages

+Package Hierarchies: + +
+
+

Class Hierarchy

+
    +
  • java.lang.Object +
      +
    • fr.pixelprose.minimax4j.IA<M>
    • +
    +
  • +
+

Interface Hierarchy

+ +

Enum Hierarchy

+ +
+ +
+ + + + + +
+ + +

Copyright © 2013. All Rights Reserved.

+ + diff --git a/package-list b/package-list new file mode 100644 index 0000000..02a6623 --- /dev/null +++ b/package-list @@ -0,0 +1 @@ +fr.pixelprose.minimax4j diff --git a/resources/background.gif b/resources/background.gif new file mode 100644 index 0000000..f471940 Binary files /dev/null and b/resources/background.gif differ diff --git a/resources/tab.gif b/resources/tab.gif new file mode 100644 index 0000000..1a73a83 Binary files /dev/null and b/resources/tab.gif differ diff --git a/resources/titlebar.gif b/resources/titlebar.gif new file mode 100644 index 0000000..17443b3 Binary files /dev/null and b/resources/titlebar.gif differ diff --git a/resources/titlebar_end.gif b/resources/titlebar_end.gif new file mode 100644 index 0000000..3ad78d4 Binary files /dev/null and b/resources/titlebar_end.gif differ diff --git a/stylesheet.css b/stylesheet.css new file mode 100644 index 0000000..0aeaa97 --- /dev/null +++ b/stylesheet.css @@ -0,0 +1,474 @@ +/* Javadoc style sheet */ +/* +Overall document style +*/ +body { + background-color:#ffffff; + color:#353833; + font-family:Arial, Helvetica, sans-serif; + font-size:76%; + margin:0; +} +a:link, a:visited { + text-decoration:none; + color:#4c6b87; +} +a:hover, a:focus { + text-decoration:none; + color:#bb7a2a; +} +a:active { + text-decoration:none; + color:#4c6b87; +} +a[name] { + color:#353833; +} +a[name]:hover { + text-decoration:none; + color:#353833; +} +pre { + font-size:1.3em; +} +h1 { + font-size:1.8em; +} +h2 { + font-size:1.5em; +} +h3 { + font-size:1.4em; +} +h4 { + font-size:1.3em; +} +h5 { + font-size:1.2em; +} +h6 { + font-size:1.1em; +} +ul { + list-style-type:disc; +} +code, tt { + font-size:1.2em; +} +dt code { + font-size:1.2em; +} +table tr td dt code { + font-size:1.2em; + vertical-align:top; +} +sup { + font-size:.6em; +} +/* +Document title and Copyright styles +*/ +.clear { + clear:both; + height:0px; + overflow:hidden; +} +.aboutLanguage { + float:right; + padding:0px 21px; + font-size:.8em; + z-index:200; + margin-top:-7px; +} +.legalCopy { + margin-left:.5em; +} +.bar a, .bar a:link, .bar a:visited, .bar a:active { + color:#FFFFFF; + text-decoration:none; +} +.bar a:hover, .bar a:focus { + color:#bb7a2a; +} +.tab { + background-color:#0066FF; + background-image:url(resources/titlebar.gif); + background-position:left top; + background-repeat:no-repeat; + color:#ffffff; + padding:8px; + width:5em; + font-weight:bold; +} +/* +Navigation bar styles +*/ +.bar { + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + padding:.8em .5em .4em .8em; + height:auto;/*height:1.8em;*/ + font-size:1em; + margin:0; +} +.topNav { + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; +} +.bottomNav { + margin-top:10px; + background-image:url(resources/background.gif); + background-repeat:repeat-x; + color:#FFFFFF; + float:left; + padding:0; + width:100%; + clear:right; + height:2.8em; + padding-top:10px; + overflow:hidden; +} +.subNav { + background-color:#dee3e9; + border-bottom:1px solid #9eadc0; + float:left; + width:100%; + overflow:hidden; +} +.subNav div { + clear:left; + float:left; + padding:0 0 5px 6px; +} +ul.navList, ul.subNavList { + float:left; + margin:0 25px 0 0; + padding:0; +} +ul.navList li{ + list-style:none; + float:left; + padding:3px 6px; +} +ul.subNavList li{ + list-style:none; + float:left; + font-size:90%; +} +.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited { + color:#FFFFFF; + text-decoration:none; +} +.topNav a:hover, .bottomNav a:hover { + text-decoration:none; + color:#bb7a2a; +} +.navBarCell1Rev { + background-image:url(resources/tab.gif); + background-color:#a88834; + color:#FFFFFF; + margin: auto 5px; + border:1px solid #c9aa44; +} +/* +Page header and footer styles +*/ +.header, .footer { + clear:both; + margin:0 20px; + padding:5px 0 0 0; +} +.indexHeader { + margin:10px; + position:relative; +} +.indexHeader h1 { + font-size:1.3em; +} +.title { + color:#2c4557; + margin:10px 0; +} +.subTitle { + margin:5px 0 0 0; +} +.header ul { + margin:0 0 25px 0; + padding:0; +} +.footer ul { + margin:20px 0 5px 0; +} +.header ul li, .footer ul li { + list-style:none; + font-size:1.2em; +} +/* +Heading styles +*/ +div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 { + background-color:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + margin:0 0 6px -8px; + padding:2px 5px; +} +ul.blockList ul.blockList ul.blockList li.blockList h3 { + background-color:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + margin:0 0 6px -8px; + padding:2px 5px; +} +ul.blockList ul.blockList li.blockList h3 { + padding:0; + margin:15px 0; +} +ul.blockList li.blockList h2 { + padding:0px 0 20px 0; +} +/* +Page layout container styles +*/ +.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer { + clear:both; + padding:10px 20px; + position:relative; +} +.indexContainer { + margin:10px; + position:relative; + font-size:1.0em; +} +.indexContainer h2 { + font-size:1.1em; + padding:0 0 3px 0; +} +.indexContainer ul { + margin:0; + padding:0; +} +.indexContainer ul li { + list-style:none; +} +.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt { + font-size:1.1em; + font-weight:bold; + margin:10px 0 0 0; + color:#4E4E4E; +} +.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd { + margin:10px 0 10px 20px; +} +.serializedFormContainer dl.nameValue dt { + margin-left:1px; + font-size:1.1em; + display:inline; + font-weight:bold; +} +.serializedFormContainer dl.nameValue dd { + margin:0 0 0 1px; + font-size:1.1em; + display:inline; +} +/* +List styles +*/ +ul.horizontal li { + display:inline; + font-size:0.9em; +} +ul.inheritance { + margin:0; + padding:0; +} +ul.inheritance li { + display:inline; + list-style:none; +} +ul.inheritance li ul.inheritance { + margin-left:15px; + padding-left:15px; + padding-top:1px; +} +ul.blockList, ul.blockListLast { + margin:10px 0 10px 0; + padding:0; +} +ul.blockList li.blockList, ul.blockListLast li.blockList { + list-style:none; + margin-bottom:25px; +} +ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList { + padding:0px 20px 5px 10px; + border:1px solid #9eadc0; + background-color:#f9f9f9; +} +ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList { + padding:0 0 5px 8px; + background-color:#ffffff; + border:1px solid #9eadc0; + border-top:none; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockList { + margin-left:0; + padding-left:0; + padding-bottom:15px; + border:none; + border-bottom:1px solid #9eadc0; +} +ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast { + list-style:none; + border-bottom:none; + padding-bottom:0; +} +table tr td dl, table tr td dl dt, table tr td dl dd { + margin-top:0; + margin-bottom:1px; +} +/* +Table styles +*/ +.contentContainer table, .classUseContainer table, .constantValuesContainer table { + border-bottom:1px solid #9eadc0; + width:100%; +} +.contentContainer ul li table, .classUseContainer ul li table, .constantValuesContainer ul li table { + width:100%; +} +.contentContainer .description table, .contentContainer .details table { + border-bottom:none; +} +.contentContainer ul li table th.colOne, .contentContainer ul li table th.colFirst, .contentContainer ul li table th.colLast, .classUseContainer ul li table th, .constantValuesContainer ul li table th, .contentContainer ul li table td.colOne, .contentContainer ul li table td.colFirst, .contentContainer ul li table td.colLast, .classUseContainer ul li table td, .constantValuesContainer ul li table td{ + vertical-align:top; + padding-right:20px; +} +.contentContainer ul li table th.colLast, .classUseContainer ul li table th.colLast,.constantValuesContainer ul li table th.colLast, +.contentContainer ul li table td.colLast, .classUseContainer ul li table td.colLast,.constantValuesContainer ul li table td.colLast, +.contentContainer ul li table th.colOne, .classUseContainer ul li table th.colOne, +.contentContainer ul li table td.colOne, .classUseContainer ul li table td.colOne { + padding-right:3px; +} +.overviewSummary caption, .packageSummary caption, .contentContainer ul.blockList li.blockList caption, .summary caption, .classUseContainer caption, .constantValuesContainer caption { + position:relative; + text-align:left; + background-repeat:no-repeat; + color:#FFFFFF; + font-weight:bold; + clear:none; + overflow:hidden; + padding:0px; + margin:0px; +} +caption a:link, caption a:hover, caption a:active, caption a:visited { + color:#FFFFFF; +} +.overviewSummary caption span, .packageSummary caption span, .contentContainer ul.blockList li.blockList caption span, .summary caption span, .classUseContainer caption span, .constantValuesContainer caption span { + white-space:nowrap; + padding-top:8px; + padding-left:8px; + display:block; + float:left; + background-image:url(resources/titlebar.gif); + height:18px; +} +.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd { + width:10px; + background-image:url(resources/titlebar_end.gif); + background-repeat:no-repeat; + background-position:top right; + position:relative; + float:left; +} +ul.blockList ul.blockList li.blockList table { + margin:0 0 12px 0px; + width:100%; +} +.tableSubHeadingColor { + background-color: #EEEEFF; +} +.altColor { + background-color:#eeeeef; +} +.rowColor { + background-color:#ffffff; +} +.overviewSummary td, .packageSummary td, .contentContainer ul.blockList li.blockList td, .summary td, .classUseContainer td, .constantValuesContainer td { + text-align:left; + padding:3px 3px 3px 7px; +} +th.colFirst, th.colLast, th.colOne, .constantValuesContainer th { + background:#dee3e9; + border-top:1px solid #9eadc0; + border-bottom:1px solid #9eadc0; + text-align:left; + padding:3px 3px 3px 7px; +} +td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover { + font-weight:bold; +} +td.colFirst, th.colFirst { + border-left:1px solid #9eadc0; + white-space:nowrap; +} +td.colLast, th.colLast { + border-right:1px solid #9eadc0; +} +td.colOne, th.colOne { + border-right:1px solid #9eadc0; + border-left:1px solid #9eadc0; +} +table.overviewSummary { + padding:0px; + margin-left:0px; +} +table.overviewSummary td.colFirst, table.overviewSummary th.colFirst, +table.overviewSummary td.colOne, table.overviewSummary th.colOne { + width:25%; + vertical-align:middle; +} +table.packageSummary td.colFirst, table.overviewSummary th.colFirst { + width:25%; + vertical-align:middle; +} +/* +Content styles +*/ +.description pre { + margin-top:0; +} +.deprecatedContent { + margin:0; + padding:10px 0; +} +.docSummary { + padding:0; +} +/* +Formatting effect styles +*/ +.sourceLineNo { + color:green; + padding:0 30px 0 0; +} +h1.hidden { + visibility:hidden; + overflow:hidden; + font-size:.9em; +} +.block { + display:block; + margin:3px 0 0 0; +} +.strong { + font-weight:bold; +}