This repository has been archived by the owner on Feb 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Подготовка к слиянию - испраление QBot
- Loading branch information
Showing
20 changed files
with
671 additions
and
85 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package io.deeplay.qchess.qbot; | ||
|
||
import static io.deeplay.qchess.qbot.profile.ParserKt.fill; | ||
import static io.deeplay.qchess.qbot.profile.ParserKt.getProfilesMap; | ||
|
||
import com.google.gson.Gson; | ||
import com.google.gson.reflect.TypeToken; | ||
import io.deeplay.qchess.qbot.profile.Profile; | ||
import java.io.BufferedWriter; | ||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.nio.file.StandardCopyOption; | ||
import java.nio.file.StandardOpenOption; | ||
import java.util.HashMap; | ||
|
||
public class Main { | ||
|
||
private static final Path toReplace = Paths.get("./data/profiles.gson"); | ||
private static final Path newContents = toReplace.resolveSibling("profiles_temp.json"); | ||
|
||
public static void main(final String[] args) throws IOException { | ||
// Запуск парсинга профилей | ||
fill(); | ||
try (final BufferedWriter writer = | ||
Files.newBufferedWriter( | ||
newContents, | ||
StandardCharsets.UTF_8, | ||
StandardOpenOption.CREATE, | ||
StandardOpenOption.TRUNCATE_EXISTING)) { | ||
new Gson() | ||
.toJson( | ||
getProfilesMap(), | ||
new TypeToken<HashMap<String, Profile>>() {}.getType(), | ||
writer); | ||
} | ||
Files.move( | ||
newContents, | ||
toReplace, | ||
StandardCopyOption.REPLACE_EXISTING, | ||
StandardCopyOption.ATOMIC_MOVE); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
qbot/src/main/java/io/deeplay/qchess/qbot/QExpectimaxBot.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package io.deeplay.qchess.qbot; | ||
|
||
import static io.deeplay.qchess.qbot.profile.ParserKt.fill; | ||
import static io.deeplay.qchess.qbot.profile.ParserKt.getProfilesMap; | ||
|
||
import io.deeplay.qchess.game.GameSettings; | ||
import io.deeplay.qchess.game.exceptions.ChessError; | ||
import io.deeplay.qchess.game.logics.EndGameDetector.EndGameType; | ||
import io.deeplay.qchess.game.model.Color; | ||
import io.deeplay.qchess.game.model.Move; | ||
import io.deeplay.qchess.qbot.profile.Profile; | ||
import io.deeplay.qchess.qbot.strategy.PestoStrategy; | ||
import io.deeplay.qchess.qbot.strategy.Strategy; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
|
||
public class QExpectimaxBot extends QBot { | ||
private final Profile enemyProfile; | ||
|
||
protected QExpectimaxBot( | ||
final GameSettings roomSettings, | ||
final Color color, | ||
final int searchDepth, | ||
final Strategy strategy) { | ||
this(roomSettings, color, searchDepth, strategy, null); | ||
} | ||
|
||
protected QExpectimaxBot( | ||
final GameSettings roomSettings, | ||
final Color color, | ||
final int searchDepth, | ||
final Strategy strategy, | ||
final String enemyProfileStr) { | ||
super(roomSettings, color, searchDepth, strategy, "ExpectiMaxBot"); | ||
if (enemyProfileStr != null) { | ||
if (getProfilesMap().isEmpty()) fill(); | ||
enemyProfile = getProfilesMap().get(enemyProfileStr); | ||
Objects.requireNonNull(enemyProfile, "Профиль " + enemyProfileStr + " не найден!"); | ||
} else enemyProfile = new Profile(); | ||
} | ||
|
||
protected QExpectimaxBot( | ||
final GameSettings roomSettings, final Color color, final int searchDepth) { | ||
this(roomSettings, color, searchDepth, new PestoStrategy()); | ||
} | ||
|
||
@Override | ||
public List<Move> getTopMoves() throws ChessError { | ||
final List<Move> topMoves = new ArrayList<>(); | ||
int maxGrade = color == Color.WHITE ? Integer.MIN_VALUE : Integer.MAX_VALUE; | ||
final List<Move> allMoves = ms.getAllPreparedMoves(color); | ||
for (final Move move : allMoves) { | ||
final int curGrade = minimaxRootWithVirtualMove(move); | ||
if (color == Color.WHITE) { | ||
if (curGrade > maxGrade) { | ||
maxGrade = curGrade; | ||
topMoves.clear(); | ||
} | ||
if (curGrade >= maxGrade) { | ||
topMoves.add(move); | ||
} | ||
} else { | ||
if (curGrade < maxGrade) { | ||
maxGrade = curGrade; | ||
topMoves.clear(); | ||
} | ||
if (curGrade <= maxGrade) { | ||
topMoves.add(move); | ||
} | ||
} | ||
} | ||
return topMoves; | ||
} | ||
|
||
/** Точка входа в минимакс после выполнения виртуального хода */ | ||
public int minimaxRootWithVirtualMove(final Move move) throws ChessError { | ||
ms.move(move); | ||
final int res = expectimax(depth, color.inverse()); | ||
ms.undoMove(); | ||
return res; | ||
} | ||
|
||
private int expectimax(final int curDepth, final Color curColor) throws ChessError { | ||
if (curDepth == 0) return strategy.evaluateBoard(board); | ||
|
||
final List<Move> moves = ms.getAllPreparedMoves(curColor); | ||
final EndGameType endGameType = egd.updateEndGameStatus(moves, curColor); | ||
egd.revertEndGameStatus(); | ||
if (endGameType != EndGameType.NOTHING) | ||
return strategy.gradeIfTerminalNode(endGameType, curDepth); | ||
|
||
if (color == curColor) { | ||
int bestMoveValue = Integer.MIN_VALUE; | ||
for (final Move move : moves) { | ||
ms.move(move); | ||
final int currentValue = expectimax(curDepth - 1, curColor.inverse()); | ||
ms.undoMove(); | ||
bestMoveValue = Math.max(bestMoveValue, currentValue); | ||
} | ||
return bestMoveValue; | ||
} else { | ||
double sum = 0; | ||
for (final Move move : moves) { | ||
ms.move(move); | ||
final int currentValue = expectimax(curDepth - 1, curColor.inverse()); | ||
ms.undoMove(); | ||
Double coef; | ||
final String fen = history.getBoardToStringForsythEdwards(); | ||
final Map<Move, Double> probs = enemyProfile.movesWithProb(fen); | ||
if (probs.isEmpty()) coef = 1. / moves.size(); | ||
else { | ||
coef = probs.get(move); | ||
if (coef == null) coef = 0.0; | ||
} | ||
sum += currentValue * coef; | ||
} | ||
return (int) Math.round(sum); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.