📄 moveoption.java
字号:
/** * MegaMek - * Copyright (C) 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.util.Enumeration;import java.util.Vector;import megamek.common.Compute;import megamek.common.Coords;import megamek.common.CriticalSlot;import megamek.common.Entity;import megamek.common.IGame;import megamek.common.IHex;import megamek.common.IEntityMovementType;import megamek.common.Infantry;import megamek.common.LosEffects;import megamek.common.Mech;import megamek.common.MovePath;import megamek.common.MoveStep;import megamek.common.PilotingRollData;import megamek.common.Protomech;import megamek.common.Targetable;import megamek.common.TargetRoll;import megamek.common.Terrains;import megamek.common.ToHitData;import java.util.ArrayList;import java.util.Comparator;import java.util.HashMap;/** * TODO: add the notion of a dependent state (at least a first pass estimate of * worst case threat) for when psr's are made. * * TODO: add a notion of a blocked move, something that could open up after * another mech moves. */public class MoveOption extends MovePath implements Cloneable { public static class WeightedComparator implements Comparator { private double utility_weight; private double damage_weight; public WeightedComparator(double utility, double damage) { utility_weight = utility; damage_weight = damage; } public int compare(Object arg0, Object arg1) { MoveOption e0 = (MoveOption) arg0; MoveOption e1 = (MoveOption) arg1; if (damage_weight * e0.damage - utility_weight * e0.getUtility() > damage_weight * e1.damage - utility_weight * e1.getUtility()) { return -1; } return 1; } } public static class Table extends HashMap<MovePath.Key, MoveOption> { public void put(MoveOption es) { this.put(es.getKey(), es); } public MoveOption get(MoveOption es) { return super.get(es.getKey()); } public MoveOption remove(MoveOption es) { return super.remove(es.getKey()); } } public static class DistanceComparator implements Comparator { public int compare(Object arg0, Object arg1) { MoveOption e0 = (MoveOption) arg0; MoveOption e1 = (MoveOption) arg1; return e0.getDistUtility() < e1.getDistUtility() ? -1 : 1; } } public static class DamageInfo { double threat; double damage; double max_threat; double min_damage; } public static final DistanceComparator DISTANCE_COMPARATOR = new DistanceComparator(); public static final int ATTACK_MOD = 0; public static final int DEFENCE_MOD = 1; public static final int ATTACK_PC = 2; public static final int DEFENCE_PC = 3; boolean inDanger = false; boolean doomed = false; boolean isPhysical = false; double self_threat = 0; double movement_threat = 0; double self_damage = 0; double damage = 0; double threat = 0; private transient CEntity centity; transient ArrayList<String> tv = new ArrayList<String>(); transient HashMap damageInfos = new HashMap(); private Coords pos; private int facing; private boolean prone; public MoveOption(IGame game, CEntity centity) { super(game, centity.entity); this.centity = centity; this.pos = centity.entity.getPosition(); this.facing = centity.entity.getFacing(); this.prone = centity.entity.isProne(); } public MoveOption(MoveOption base) { this(base.game, base.centity); steps = (Vector) base.steps.clone(); this.threat = base.threat; this.damage = base.damage; this.movement_threat = base.movement_threat; this.tv = new ArrayList<String>(base.tv); this.self_threat = base.self_threat; this.inDanger = base.inDanger; this.doomed = base.doomed; this.isPhysical = base.isPhysical; this.self_damage = base.self_damage; this.pos = base.pos; this.facing = base.facing; this.prone = base.prone; } public Object clone() { return new MoveOption(this); } public double getThreat(CEntity e) { return getDamageInfo(e, true).threat; } public void setThreat(CEntity e, double value) { getDamageInfo(e, true).threat = value; } public double getMinDamage(CEntity e) { return getDamageInfo(e, true).min_damage; } public double getDamage(CEntity e) { return getDamageInfo(e, true).damage; } public void setDamage(CEntity e, double value) { getDamageInfo(e, true).damage = value; } CEntity getCEntity() { return centity; } public MovePath addStep(int step_type) { super.addStep(step_type); MoveStep current = getLastStep(); // running with gyro or hip hit is dangerous! if (current.getMovementType() == IEntityMovementType.MOVE_RUN && (entity.getBadCriticals(CriticalSlot.TYPE_SYSTEM, Mech.SYSTEM_GYRO, Mech.LOC_CT) > 0 || entity.hasHipCrit())) { this.getStep(0).setDanger(true); current.setDanger(true); } if (current.isDanger()) { if (getCEntity().base_psr_odds < .1) { current.setMovementType(IEntityMovementType.MOVE_ILLEGAL); } else { double cur_threat = getCEntity().getThreatUtility(.2 * this.entity.getWeight(), ToHitData.SIDE_REAR) * (1 - Math.pow(getCEntity().base_psr_odds, 2)); this.movement_threat += cur_threat; if(centity.getTb().debug) this.tv.add(cur_threat + " Movement Threat \r\n"); } } return this; } public int getMovementheatBuildup() { MoveStep last = this.getLastStep(); if (last == null) return 0; int heat = last.getTotalHeat(); int move = 0; switch (last.getMovementType()) { case IEntityMovementType.MOVE_WALK : case IEntityMovementType.MOVE_VTOL_WALK : move = 1; break; case IEntityMovementType.MOVE_RUN : case IEntityMovementType.MOVE_VTOL_RUN : move = 2; break; case IEntityMovementType.MOVE_JUMP : move = getEntity().getJumpHeat(last.getMpUsed()); break; default : move = 1000; } return heat + move; // illegal? } public boolean changeToPhysical() { MoveStep last = getLastStep(); boolean isInfantry = (getEntity() instanceof Infantry); boolean isProtomech = (getEntity() instanceof Protomech); boolean isClan = getEntity().isClan(); if (last == null || last.getMovementType() == IEntityMovementType.MOVE_ILLEGAL) { return false; } if (last.getType() != STEP_FORWARDS || isInfantry || isProtomech || ( isClan && game.getOptions().booleanOption("no_clan_physical") && getEntity().getSwarmAttackerId()==Entity.NONE)) { //$NON-NLS-1$ return false; } Enumeration e = game.getEntities(last.getPosition()); //TODO: this just takes the first target while (e.hasMoreElements()) { Entity en = (Entity) e.nextElement(); if (!en.isSelectableThisTurn() && en.isEnemyOf(this.entity)) { this.isPhysical = true; this.removeLastStep(); if (isJumping()) { addStep(MovePath.STEP_DFA, en); } else { addStep(MovePath.STEP_CHARGE, en); } return true; } } return false; } //it would be nice to have a stand still move... public void setState() { this.entity = this.centity.entity; if (this.steps.size() == 0) { this.entity.setPosition(pos); this.entity.setFacing(facing);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -