📄 botclient.java
字号:
/* * MegaMek - Copyright (C) 2000,2001,2002,2003,2004,2005 Ben Mazur (bmazur@sev.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. */package megamek.client.bot;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.Comparator;import java.util.Enumeration;import java.util.Vector;import megamek.client.Client;import megamek.common.AmmoType;import megamek.common.Compute;import megamek.common.Coords;import megamek.common.Entity;import megamek.common.GameTurn;import megamek.common.IGame;import megamek.common.Infantry;import megamek.common.Mech;import megamek.common.MiscType;import megamek.common.Minefield;import megamek.common.MovePath;import megamek.common.Mounted;import megamek.common.IEntityMovementMode;import megamek.common.Protomech;import megamek.common.Tank;import megamek.common.Terrains;import megamek.common.ToHitData;import megamek.common.actions.WeaponAttackAction;import megamek.common.WeaponType;import megamek.common.event.GameListenerAdapter;import megamek.common.event.GamePlayerChatEvent;import megamek.common.event.GameReportEvent;import megamek.common.event.GameTurnChangeEvent;import java.util.ArrayList;public abstract class BotClient extends Client { public BotClient(String playerName, String host, int port) { super(playerName, host, port); game.addGameListener(new GameListenerAdapter(){ public void gamePlayerChat(GamePlayerChatEvent e) { processChat(e); } public void gameTurnChange(GameTurnChangeEvent e) { if (isMyTurn()) { calculateMyTurn(); } } public void gameReport(GameReportEvent e) { if (game.getPhase() == IGame.PHASE_INITIATIVE_REPORT) { //Opponent has used tactical genius, must press // "Done" again to advance past initiative report. sendDone(true); } } }); } BotConfiguration config = new BotConfiguration(); public abstract void initialize(); protected abstract void processChat(GamePlayerChatEvent ge); protected abstract void initMovement(); protected abstract void initFiring(); protected abstract MovePath calculateMoveTurn(); protected abstract void calculateFiringTurn(); protected abstract void calculateDeployment(); protected abstract PhysicalOption calculatePhysicalTurn(); protected abstract MovePath continueMovementFor(Entity entity); protected abstract Vector calculateMinefieldDeployment(); protected abstract Vector calculateArtyAutoHitHexes(); public ArrayList getEntitiesOwned() { ArrayList result = new ArrayList(); for (Enumeration i = game.getEntities(); i.hasMoreElements();) { Entity entity = (Entity) i.nextElement(); if (entity.getOwner().equals(this.getLocalPlayer()) && entity.getPosition() != null && !entity.isOffBoard()) { result.add(entity); } } return result; } public ArrayList getEnemyEntities() { ArrayList result = new ArrayList(); for (Enumeration i = game.getEntities(); i.hasMoreElements();) { Entity entity = (Entity) i.nextElement(); if (entity.getOwner().isEnemyOf(this.getLocalPlayer()) && entity.getPosition() != null && !entity.isOffBoard()) { result.add(entity); } } return result; } //TODO: move initMovement to be called on phase end public void changePhase(int phase) { super.changePhase(phase); try { switch (phase) { case IGame.PHASE_LOUNGE : sendChat(Messages.getString("BotClient.Hi")); //$NON-NLS-1$ break; case IGame.PHASE_DEPLOYMENT : initialize(); break; case IGame.PHASE_MOVEMENT : if (game.getEntitiesOwnedBy(this.getLocalPlayer()) == 0) { sendChat(Messages.getString("BotClient.HowAbout")); //$NON-NLS-1$ this.die(); } if (!(game.getOptions().booleanOption("double_blind")) //$NON-NLS-1$ && game.getEntitiesOwnedBy(this.getLocalPlayer()) - game.getNoOfEntities() == 0) { this.die(); } if ( Compute.randomInt(4) == 1 ){ String message = getRandomBotMessage(); if ( message != null) sendChat(message); } initMovement(); break; case IGame.PHASE_FIRING : initFiring(); break; case IGame.PHASE_PHYSICAL : break; case IGame.PHASE_END_REPORT : // Check if stealth armor should be switched on/off // Kinda cheap leaving this until the end phase, players can't do this toggleStealth(); case IGame.PHASE_INITIATIVE_REPORT : case IGame.PHASE_MOVEMENT_REPORT : case IGame.PHASE_OFFBOARD_REPORT : case IGame.PHASE_FIRING_REPORT : case IGame.PHASE_PHYSICAL_REPORT : sendDone(true); break; case IGame.PHASE_VICTORY : break; } } catch (Throwable t) { t.printStackTrace(); } } protected void calculateMyTurn() { try { if (game.getPhase() == IGame.PHASE_MOVEMENT) { MovePath mp = null; if (game.getTurn() instanceof GameTurn.SpecificEntityTurn) { GameTurn.SpecificEntityTurn turn = (GameTurn.SpecificEntityTurn) game.getTurn(); Entity mustMove = game.getEntity(turn.getEntityNum()); mp = continueMovementFor(mustMove); } else { mp = calculateMoveTurn(); } moveEntity(mp.getEntity().getId(), mp); } else if (game.getPhase() == IGame.PHASE_FIRING) { calculateFiringTurn(); } else if (game.getPhase() == IGame.PHASE_PHYSICAL) { PhysicalOption po = calculatePhysicalTurn(); // Bug #1072137: don't crash if the bot can't find a physical. if (null != po) { sendAttackData(po.attacker.getId(), po.getVector()); } else { // Send a "no attack" to clear the game turn, if any. sendAttackData( getLocalPlayer().getId(), new Vector(0) ); } } else if (game.getPhase() == IGame.PHASE_DEPLOYMENT) { calculateDeployment(); } else if (game.getPhase() == IGame.PHASE_DEPLOY_MINEFIELDS) { Vector mines = calculateMinefieldDeployment(); for (int i = 0; i < mines.size(); i++) { game.addMinefield((Minefield)mines.get(i)); } sendDeployMinefields(mines); sendPlayerInfo(); } else if (game.getPhase() == IGame.PHASE_SET_ARTYAUTOHITHEXES) { // For now, declare no autohit hexes. Vector autoHitHexes = calculateArtyAutoHitHexes(); sendArtyAutoHitHexes(autoHitHexes); } else if (game.getPhase() == IGame.PHASE_TARGETING || game.getPhase() == IGame.PHASE_OFFBOARD) { // Send a "no attack" to clear the game turn, if any. // TODO: Fix for real arty stuff sendAttackData( game.getFirstEntityNum(), new Vector(0) ); sendDone(true); } } catch (Throwable t) { t.printStackTrace(); } } /** * Gets valid & empty starting coords around the specified point */ protected Coords getCoordsAround(Entity deploy_me, Coords[] c) { int mech_count; int conv_fcount; // Friendly conventional units int conv_ecount; // Enemy conventional units // Check all of the hexes in order. for (int x = 0; x < c.length; x++) { // Verify stacking limits. Gotta do this the long way, as // Compute.stackingViolation references the entity's CURRENT // position as well as the hex being checked; because its not // deployed yet it doesn't have a location! mech_count = 0; conv_fcount = 0; conv_ecount = 0; for (Enumeration stacked_ents = game.getEntities(c[x]); stacked_ents.hasMoreElements();){ Entity test_ent = (Entity) stacked_ents.nextElement(); if (test_ent instanceof Mech) { mech_count++; } else { if (deploy_me.isEnemyOf(test_ent)){ conv_ecount++; } else { conv_fcount++; } } } if (deploy_me instanceof Mech){ mech_count ++; } else { conv_fcount++; } if (mech_count > 1) continue; if ((conv_fcount + mech_count) > 2) continue; if ((conv_fcount + mech_count) > 2) continue; if ((conv_fcount + conv_ecount) > 4) continue; return c[x]; } System.out.println("Returning no deployment position; THIS IS BAD!"); // If NONE of them are acceptable, then just return null. return null;/* // check the requested coords
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -