mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
Test framework improves (Monte Carlo AI):
* Added support to test Monte Carlo AI (CardTestPlayerBaseWithMonteCarloAIHelps - any aiXXX commands); * Added Quick Start button to test Monte Carlo AI games (MCTS);
This commit is contained in:
parent
a7ac35a82d
commit
79c5c7a6a5
6 changed files with 224 additions and 47 deletions
|
|
@ -44,10 +44,14 @@
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Group type="102" attributes="0">
|
||||||
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
|
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
|
<Component id="btnQuickStartMCTS" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
|
<Component id="btnQuickStartCommander" min="-2" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace pref="667" max="32767" attributes="0"/>
|
<EmptySpace pref="540" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
|
|
@ -63,7 +67,13 @@
|
||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="filterBar1" max="32767" attributes="0"/>
|
<Component id="filterBar1" max="32767" attributes="0"/>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
|
<Component id="btnQuickStartDuel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="btnQuickStartMCTS" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
|
@ -567,6 +577,14 @@
|
||||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartCommanderActionPerformed"/>
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartCommanderActionPerformed"/>
|
||||||
</Events>
|
</Events>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JButton" name="btnQuickStartMCTS">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" value="Quick start MCTS"/>
|
||||||
|
</Properties>
|
||||||
|
<Events>
|
||||||
|
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="btnQuickStartMCTSActionPerformed"/>
|
||||||
|
</Events>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Container>
|
</Container>
|
||||||
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
<Container class="javax.swing.JSplitPane" name="jSplitPane1">
|
||||||
|
|
|
||||||
|
|
@ -693,6 +693,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
if (SessionHandler.getSession() != null) {
|
if (SessionHandler.getSession() != null) {
|
||||||
btnQuickStartDuel.setVisible(SessionHandler.isTestMode());
|
btnQuickStartDuel.setVisible(SessionHandler.isTestMode());
|
||||||
btnQuickStartCommander.setVisible(SessionHandler.isTestMode());
|
btnQuickStartCommander.setVisible(SessionHandler.isTestMode());
|
||||||
|
btnQuickStartMCTS.setVisible(SessionHandler.isTestMode());
|
||||||
gameChooser.init();
|
gameChooser.init();
|
||||||
chatRoomId = SessionHandler.getRoomChatId(roomId).orElse(null);
|
chatRoomId = SessionHandler.getRoomChatId(roomId).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
@ -987,6 +988,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
btnPassword = new javax.swing.JToggleButton();
|
btnPassword = new javax.swing.JToggleButton();
|
||||||
btnQuickStartDuel = new javax.swing.JButton();
|
btnQuickStartDuel = new javax.swing.JButton();
|
||||||
btnQuickStartCommander = new javax.swing.JButton();
|
btnQuickStartCommander = new javax.swing.JButton();
|
||||||
|
btnQuickStartMCTS = new javax.swing.JButton();
|
||||||
jSplitPane1 = new javax.swing.JSplitPane();
|
jSplitPane1 = new javax.swing.JSplitPane();
|
||||||
jPanelTables = new javax.swing.JPanel();
|
jPanelTables = new javax.swing.JPanel();
|
||||||
jSplitPaneTables = new javax.swing.JSplitPane();
|
jSplitPaneTables = new javax.swing.JSplitPane();
|
||||||
|
|
@ -1456,6 +1458,13 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
btnQuickStartMCTS.setText("Quick start MCTS");
|
||||||
|
btnQuickStartMCTS.addActionListener(new java.awt.event.ActionListener() {
|
||||||
|
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||||
|
btnQuickStartMCTSActionPerformed(evt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
javax.swing.GroupLayout jPanelTopLayout = new javax.swing.GroupLayout(jPanelTop);
|
javax.swing.GroupLayout jPanelTopLayout = new javax.swing.GroupLayout(jPanelTop);
|
||||||
jPanelTop.setLayout(jPanelTopLayout);
|
jPanelTop.setLayout(jPanelTopLayout);
|
||||||
jPanelTopLayout.setHorizontalGroup(
|
jPanelTopLayout.setHorizontalGroup(
|
||||||
|
|
@ -1471,9 +1480,12 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addGroup(jPanelTopLayout.createSequentialGroup()
|
||||||
.addComponent(btnQuickStartDuel)
|
.addComponent(btnQuickStartDuel)
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
|
.addComponent(btnQuickStartMCTS))
|
||||||
.addComponent(btnQuickStartCommander))
|
.addComponent(btnQuickStartCommander))
|
||||||
.addContainerGap(667, Short.MAX_VALUE))
|
.addContainerGap(540, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
jPanelTopLayout.setVerticalGroup(
|
jPanelTopLayout.setVerticalGroup(
|
||||||
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
|
@ -1486,7 +1498,11 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
.addGroup(jPanelTopLayout.createSequentialGroup()
|
.addGroup(jPanelTopLayout.createSequentialGroup()
|
||||||
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(filterBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
.addComponent(btnQuickStartDuel))
|
.addGroup(jPanelTopLayout.createSequentialGroup()
|
||||||
|
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(btnQuickStartDuel)
|
||||||
|
.addComponent(btnQuickStartMCTS))
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)))
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(jPanelTopLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
.addComponent(filterBar2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||||
|
|
@ -1596,7 +1612,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
newTournamentDialog.showDialog(roomId);
|
newTournamentDialog.showDialog(roomId);
|
||||||
}//GEN-LAST:event_btnNewTournamentActionPerformed
|
}//GEN-LAST:event_btnNewTournamentActionPerformed
|
||||||
|
|
||||||
private void createTestGame(String gameName, String gameType) {
|
private void createTestGame(String gameName, String gameType, boolean useMonteCarloAI) {
|
||||||
TableView table;
|
TableView table;
|
||||||
try {
|
try {
|
||||||
String testDeckFile = "test.dck";
|
String testDeckFile = "test.dck";
|
||||||
|
|
@ -1612,9 +1628,10 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile);
|
DeckCardLists testDeck = DeckImporter.importDeckFromFile(testDeckFile);
|
||||||
|
|
||||||
|
PlayerType aiType = useMonteCarloAI ? PlayerType.COMPUTER_MONTE_CARLO : PlayerType.COMPUTER_MAD;
|
||||||
MatchOptions options = new MatchOptions(gameName, gameType, false, 2);
|
MatchOptions options = new MatchOptions(gameName, gameType, false, 2);
|
||||||
options.getPlayerTypes().add(PlayerType.HUMAN);
|
options.getPlayerTypes().add(PlayerType.HUMAN);
|
||||||
options.getPlayerTypes().add(PlayerType.COMPUTER_MAD);
|
options.getPlayerTypes().add(aiType);
|
||||||
options.setDeckType("Limited");
|
options.setDeckType("Limited");
|
||||||
options.setAttackOption(MultiplayerAttackOption.LEFT);
|
options.setAttackOption(MultiplayerAttackOption.LEFT);
|
||||||
options.setRange(RangeOfInfluence.ALL);
|
options.setRange(RangeOfInfluence.ALL);
|
||||||
|
|
@ -1630,7 +1647,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
table = SessionHandler.createTable(roomId, options);
|
table = SessionHandler.createTable(roomId, options);
|
||||||
|
|
||||||
SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, testDeck, "");
|
SessionHandler.joinTable(roomId, table.getTableId(), "Human", PlayerType.HUMAN, 1, testDeck, "");
|
||||||
SessionHandler.joinTable(roomId, table.getTableId(), "Computer", PlayerType.COMPUTER_MAD, 5, testDeck, "");
|
SessionHandler.joinTable(roomId, table.getTableId(), "Computer", aiType, 5, testDeck, "");
|
||||||
SessionHandler.startMatch(roomId, table.getTableId());
|
SessionHandler.startMatch(roomId, table.getTableId());
|
||||||
} catch (HeadlessException ex) {
|
} catch (HeadlessException ex) {
|
||||||
handleError(ex);
|
handleError(ex);
|
||||||
|
|
@ -1638,7 +1655,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void btnQuickStartDuelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartDuelActionPerformed
|
private void btnQuickStartDuelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartDuelActionPerformed
|
||||||
createTestGame("Test duel", "Two Player Duel");
|
createTestGame("Test duel", "Two Player Duel", false);
|
||||||
}//GEN-LAST:event_btnQuickStartDuelActionPerformed
|
}//GEN-LAST:event_btnQuickStartDuelActionPerformed
|
||||||
|
|
||||||
private void btnNewTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewTableActionPerformed
|
private void btnNewTableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnNewTableActionPerformed
|
||||||
|
|
@ -1677,9 +1694,13 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
}//GEN-LAST:event_buttonWhatsNewActionPerformed
|
}//GEN-LAST:event_buttonWhatsNewActionPerformed
|
||||||
|
|
||||||
private void btnQuickStartCommanderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartCommanderActionPerformed
|
private void btnQuickStartCommanderActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartCommanderActionPerformed
|
||||||
createTestGame("Test commander", "Commander Two Player Duel");
|
createTestGame("Test commander", "Commander Two Player Duel", false);
|
||||||
}//GEN-LAST:event_btnQuickStartCommanderActionPerformed
|
}//GEN-LAST:event_btnQuickStartCommanderActionPerformed
|
||||||
|
|
||||||
|
private void btnQuickStartMCTSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnQuickStartMCTSActionPerformed
|
||||||
|
createTestGame("Test Monte Carlo AI", "Two Player Duel", true);
|
||||||
|
}//GEN-LAST:event_btnQuickStartMCTSActionPerformed
|
||||||
|
|
||||||
private void handleError(Exception ex) {
|
private void handleError(Exception ex) {
|
||||||
LOGGER.fatal("Error loading deck: ", ex);
|
LOGGER.fatal("Error loading deck: ", ex);
|
||||||
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE);
|
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Error loading deck.", "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
|
@ -1691,9 +1712,9 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
private javax.swing.JToggleButton btnFormatLegacy;
|
private javax.swing.JToggleButton btnFormatLegacy;
|
||||||
private javax.swing.JToggleButton btnFormatLimited;
|
private javax.swing.JToggleButton btnFormatLimited;
|
||||||
private javax.swing.JToggleButton btnFormatModern;
|
private javax.swing.JToggleButton btnFormatModern;
|
||||||
private javax.swing.JToggleButton btnFormatPioneer;
|
|
||||||
private javax.swing.JToggleButton btnFormatOathbreaker;
|
private javax.swing.JToggleButton btnFormatOathbreaker;
|
||||||
private javax.swing.JToggleButton btnFormatOther;
|
private javax.swing.JToggleButton btnFormatOther;
|
||||||
|
private javax.swing.JToggleButton btnFormatPioneer;
|
||||||
private javax.swing.JToggleButton btnFormatPremodern;
|
private javax.swing.JToggleButton btnFormatPremodern;
|
||||||
private javax.swing.JToggleButton btnFormatStandard;
|
private javax.swing.JToggleButton btnFormatStandard;
|
||||||
private javax.swing.JToggleButton btnFormatTinyLeader;
|
private javax.swing.JToggleButton btnFormatTinyLeader;
|
||||||
|
|
@ -1704,6 +1725,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
||||||
private javax.swing.JToggleButton btnPassword;
|
private javax.swing.JToggleButton btnPassword;
|
||||||
private javax.swing.JButton btnQuickStartCommander;
|
private javax.swing.JButton btnQuickStartCommander;
|
||||||
private javax.swing.JButton btnQuickStartDuel;
|
private javax.swing.JButton btnQuickStartDuel;
|
||||||
|
private javax.swing.JButton btnQuickStartMCTS;
|
||||||
private javax.swing.JToggleButton btnRated;
|
private javax.swing.JToggleButton btnRated;
|
||||||
private javax.swing.JToggleButton btnSkillBeginner;
|
private javax.swing.JToggleButton btnSkillBeginner;
|
||||||
private javax.swing.JToggleButton btnSkillCasual;
|
private javax.swing.JToggleButton btnSkillCasual;
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@
|
||||||
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
<playerType name="Human" jar="mage-player-human.jar" className="mage.player.human.HumanPlayer"/>
|
||||||
<!--<playerType name="Computer - minimax" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/>-->
|
<!--<playerType name="Computer - minimax" jar="mage-player-aiminimax.jar" className="mage.player.ai.ComputerPlayer3"/>-->
|
||||||
<playerType name="Computer - mad" jar="mage-player-ai-ma.jar" className="mage.player.ai.ComputerPlayer7"/>
|
<playerType name="Computer - mad" jar="mage-player-ai-ma.jar" className="mage.player.ai.ComputerPlayer7"/>
|
||||||
<!--<playerType name="Computer - monte carlo" jar="mage-player-aimcts.jar" className="mage.player.ai.ComputerPlayerMCTS"/>-->
|
<playerType name="Computer - monte carlo" jar="mage-player-aimcts.jar" className="mage.player.ai.ComputerPlayerMCTS"/>
|
||||||
<playerType name="Computer - draftbot" jar="mage-player-ai-draft-bot.jar" className="mage.player.ai.ComputerDraftPlayer"/>
|
<playerType name="Computer - draftbot" jar="mage-player-ai-draft-bot.jar" className="mage.player.ai.ComputerDraftPlayer"/>
|
||||||
</playerTypes>
|
</playerTypes>
|
||||||
<gameTypes>
|
<gameTypes>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package org.mage.test.cards.requirement;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBaseWithMonteCarloAIHelps;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public class BecomeBlockTriggersMonteCarloAITest extends CardTestPlayerBaseWithMonteCarloAIHelps {
|
||||||
|
|
||||||
|
// continue from BecomeBlockTriggersTest
|
||||||
|
@Test
|
||||||
|
public void test_AI_CantBlockAgain() {
|
||||||
|
// Monte Carlo bug: Triggered ability triggered twice (should be once), see https://github.com/magefree/mage/issues/6367
|
||||||
|
|
||||||
|
removeAllCardsFromHand(playerA);
|
||||||
|
removeAllCardsFromHand(playerB);
|
||||||
|
|
||||||
|
// All creatures able to block Nessian Boar do so.
|
||||||
|
// Whenever Nessian Boar becomes blocked by a creature, that creature’s controller draws a card.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Nessian Boar", 1);
|
||||||
|
//
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Balduvian Bears", 1);
|
||||||
|
|
||||||
|
// auto-block by requirement effect
|
||||||
|
attack(1, playerA, "Nessian Boar");
|
||||||
|
// AI can't block same creature twice
|
||||||
|
aiPlayStep(1, PhaseStep.DECLARE_BLOCKERS, playerB);
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
assertAllCommandsUsed();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 0);
|
||||||
|
assertGraveyardCount(playerB, 1);
|
||||||
|
assertHandCount(playerA, 0);
|
||||||
|
assertHandCount(playerB, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.mage.test.player;
|
||||||
|
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.abilities.ActivatedAbility;
|
||||||
|
import mage.abilities.SpellAbility;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.RangeOfInfluence;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.player.ai.ComputerPlayerMCTS;
|
||||||
|
import mage.target.Target;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
|
||||||
|
// mock class to override AI logic in tests
|
||||||
|
public class TestComputerPlayerMonteCarlo extends ComputerPlayerMCTS {
|
||||||
|
|
||||||
|
private TestPlayer testPlayerLink;
|
||||||
|
|
||||||
|
public TestComputerPlayerMonteCarlo(String name, RangeOfInfluence range, int skill) {
|
||||||
|
super(name, range, skill);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestPlayerLink(TestPlayer testPlayerLink) {
|
||||||
|
this.testPlayerLink = testPlayerLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
|
||||||
|
// copy-paste for TestComputerXXX
|
||||||
|
|
||||||
|
// workaround to cast fused cards in tests by it's NAMES (Wear, Tear, Wear // Tear)
|
||||||
|
// reason: TestPlayer uses outer computerPlayer to cast, not TestPlayer
|
||||||
|
switch (ability.getSpellAbilityType()) {
|
||||||
|
case SPLIT:
|
||||||
|
case SPLIT_FUSED:
|
||||||
|
case SPLIT_AFTERMATH:
|
||||||
|
if (!this.testPlayerLink.getChoices().isEmpty()) {
|
||||||
|
MageObject object = game.getObject(ability.getSourceId());
|
||||||
|
if (object != null) {
|
||||||
|
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = getSpellAbilities(playerId, object, game.getState().getZone(object.getId()), game);
|
||||||
|
|
||||||
|
// left, right or fused cast
|
||||||
|
for (String choose : this.testPlayerLink.getChoices()) {
|
||||||
|
for (ActivatedAbility activatedAbility : useableAbilities.values()) {
|
||||||
|
if (activatedAbility instanceof SpellAbility) {
|
||||||
|
if (((SpellAbility) activatedAbility).getCardName().equals(choose)) {
|
||||||
|
return (SpellAbility) activatedAbility;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// default implementation by AI
|
||||||
|
return super.chooseSpellAbilityForCast(ability, game, noMana);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
|
||||||
|
// copy-paste for TestComputerXXX
|
||||||
|
|
||||||
|
// workaround for discard spells
|
||||||
|
// reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
|
||||||
|
return testPlayerLink.choose(outcome, target, sourceId, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.mage.test.serverside.base;
|
||||||
|
|
||||||
|
import mage.constants.RangeOfInfluence;
|
||||||
|
import org.mage.test.player.TestComputerPlayerMonteCarlo;
|
||||||
|
import org.mage.test.player.TestPlayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class but with Monte Carlo computer player to test single AI commands (it's different from full AI simulation from CardTestPlayerBaseAI):
|
||||||
|
* 1. AI don't play normal priorities (you must use ai*** commands to play it);
|
||||||
|
* 2. AI will choose in non strict mode (it's simulated ComputerPlayerMCTS, not simple ComputerPlayer from basic tests)
|
||||||
|
*
|
||||||
|
* @author JayDi85
|
||||||
|
*/
|
||||||
|
public abstract class CardTestPlayerBaseWithMonteCarloAIHelps extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
|
||||||
|
TestPlayer testPlayer = new TestPlayer(new TestComputerPlayerMonteCarlo(name, RangeOfInfluence.ONE, 6));
|
||||||
|
testPlayer.setAIPlayer(false); // AI can't play it by itself, use AI commands
|
||||||
|
return testPlayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue