📄 centity.java
字号:
for (int range_walk = (this.entity instanceof Infantry ? 0 : 1); range_walk < this.long_range; range_walk++){ if (range_walk <= this.rd_bracket){ optimizer[RANGE_SHORT] += this.damages[arc][range_walk]; range_damages[RANGE_SHORT] += this.damages[arc][range_walk]; } if (range_walk > this.rd_bracket & range_walk <= 2 * this.rd_bracket){ optimizer[RANGE_MEDIUM] += this.getModifiedDamage(arc, range_walk, -2); range_damages[RANGE_MEDIUM] += this.damages[arc][range_walk]; } if (range_walk > 2 * this.rd_bracket & range_walk <= 3 * this.rd_bracket){ optimizer[RANGE_LONG] += this.getModifiedDamage(arc, range_walk, -4); range_damages[RANGE_LONG]+= this.damages[arc][range_walk]; } range_damages[RANGE_ALL] += this.damages[arc][range_walk]; } if (rd_bracket > 0){ range_damages[RANGE_SHORT] /= this.rd_bracket; optimizer[RANGE_SHORT] /= this.rd_bracket; range_damages[RANGE_MEDIUM] /= this.rd_bracket; optimizer[RANGE_MEDIUM] /= this.rd_bracket; range_damages[RANGE_LONG] /= this.rd_bracket; optimizer[RANGE_LONG] /= this.rd_bracket; range_damages[RANGE_ALL] /= (this.rd_bracket * 3); } else { range_damages[RANGE_SHORT] = this.damages[arc][0]; optimizer[RANGE_SHORT] = this.damages[arc][0]; range_damages[RANGE_MEDIUM] = this.damages[arc][0]; optimizer[RANGE_MEDIUM] = this.damages[arc][0]; range_damages[RANGE_LONG] = this.damages[arc][0]; optimizer[RANGE_LONG] = this.damages[arc][0]; range_damages[RANGE_ALL] = this.damages[arc][0]; } // Now determine the preferred range. Use damage values based on no // range modifiers, but retain the range-based damage values for // further use. int best_range = RANGE_ALL; for (this.range = RANGE_SHORT; this.range <= RANGE_LONG; this.range++){ if (optimizer[this.range] > optimizer[best_range]){ best_range = this.range; } } this.range = best_range; } /** * Returns the value of the armor in the indicated location. * Conventional infantry and battle armor behave differently than other * units. Armor is in integer units. */ protected int getArmorValue(int loc, boolean rear) { int result = entity.getArmor(loc, rear); // Conventional infantry don't have armor (yet), so use the number of troopers // TODO: This will probably need some revamping when Total Warfare is released. if (entity instanceof Infantry & !(entity instanceof BattleArmor)){ result = ((Infantry) entity).getShootingStrength(); } // Battle armor has armor per trooper; treat each trooper as a "location" if (entity instanceof BattleArmor){ result = ((BattleArmor) entity).getArmor(loc, false); } if (result <= 0) result = 0; return result; } /** * The utility of something done against me. -- uses the arcs defined by * ToHitData (FRONT, REAR, LEFT, RIGHT). Takes a damage value and adjusts * it based on the characterized entities armor/internal values in that * arc. Also adjusts based on the strategy module being used by this * entity. */ public double getThreatUtility(double threat, int arc) { double t1 = threat; double t2 = threat; //relative bonus for weak side if (armor_percent[arc] < .75) { t1 *= 1.1; } else if (armor_percent[arc] < .5) { t1 *= 1.3; } else if (armor_percent[arc] < .25) { t1 *= 1.5; } t1 *= this.strategy.target; //absolute bonus for damage that is likely to do critical if (t2 + this.expected_damage[arc] > this.armor_health[arc]) { // expected_damage[] is set on the fly; it tracks damage // the entity expects to take if ( (t2 + this.expected_damage[0] + this.expected_damage[1] + this.expected_damage[2] + this.expected_damage[3] > 3 * (this.avg_armor + this.avg_iarmor) || (this.entity.isProne() && this.base_psr_odds < .1 && !this.entity.isImmobile())) ) { // If I have more friends, this isn't so bad if (this.entity.isEnemyOf((Entity) tb.getEntitiesOwned().get(0))) { return Math.sqrt(t2) * this.strategy.target; } } t2 *= 1.5; // Damage that penetrates armor is bad for me // Even if damage doesn't penetrate, some damage to this arc isn't that great } else if (this.expected_damage[arc] > 0) { t2 *= 1.3; // Even if this arc is still good, taking additional damage isn't a good thing } else if (this.hasTakenDamage) { t2 *= 1.1; } // Return the worst case, either massive damage or penetration to internals return Math.max(t1, t2); } public Integer getKey() { return new Integer(this.entity.getId()); } public MoveOption.Table getAllMoves() { if (moves == null) { moves = calculateMoveOptions(this.current); } return moves; } /** * From the current state, explore based upon an implementation of * Dijkstra's algorithm. */ protected MoveOption.Table calculateMoveOptions(MoveOption base) { ArrayList possible = new ArrayList(); // New array of movement options MoveOption.Table discovered = new MoveOption.Table(); // If this entity can jump, then... what is this doing? // ... I THINK its creating a duplicate of the base movment option, then adding // a jumping start if (entity.getJumpMPWithTerrain() > 0) { possible.add(((MovePath) base.clone()).addStep(MovePath.STEP_START_JUMP)); } possible.add(base); // Add the base movement option to the arraylist of possibles discovered.put(base); // Add the base movement option to the movement option table while (possible.size() > 0) { // Keep going until the arraylist is empty (why?) // Get the first movement option, while stripping it from the arraylist MoveOption min = (MoveOption) possible.remove(0); Iterator adjacent = min.getNextMoves(true, true).iterator(); while (adjacent.hasNext()) { MoveOption next = (MoveOption) adjacent.next(); if (next.changeToPhysical() && next.isMoveLegal()) { discovered.put(next); } else if (next.isMoveLegal()) { //relax edges; if (discovered.get(next) == null || (next.getDistUtility() < discovered.get(next).getDistUtility())) { discovered.put(next); if (next.isJumping()) { MoveOption left = (MoveOption) next.clone(); MoveOption right = (MoveOption) next.clone(); // Think about skipping this for infantry, which have no facing for (int turn = 0; turn < 2; turn++) { left.addStep(MovePath.STEP_TURN_LEFT); right.addStep(MovePath.STEP_TURN_RIGHT); discovered.put(((MoveOption) left.clone())); discovered.put(((MoveOption) right.clone())); } // Accounts for a 180 degree turn right.addStep(MovePath.STEP_TURN_RIGHT); discovered.put(right); } int index = Collections.binarySearch(possible, next, MoveOption.DISTANCE_COMPARATOR); if (index < 0) { index = -index - 1; } possible.add(index, next); } } } } //Final check for illeagal and extra weighting for heat for (Iterator i = discovered.values().iterator(); i.hasNext();) { MoveOption next = (MoveOption) i.next(); next.clipToPossible(); if (!next.isMoveLegal()) { i.remove(); } if (entity.heat > 4) { next.movement_threat += this.bv / 1000 * next.getMovementheatBuildup(); if (entity.heat > 7) { next.movement_threat += this.bv / 500 * next.getMovementheatBuildup(); } if (this.tsm_offset){ if (entity.heat == 9){ next.movement_threat -= this.bv / 100 * next.getMovementheatBuildup(); } if (entity.heat < 12 && entity.heat > 9){ next.movement_threat -= this.bv / 500 * next.getMovementheatBuildup(); } } if (entity.heat > 12) { next.movement_threat += this.bv / 100 * next.getMovementheatBuildup(); } } } return discovered; } /** * find all moves that get into dest */ public ArrayList findMoves(Coords dest) { ArrayList result = new ArrayList(); for (int i = 0; i < 6; i++) { for (int j = 1; j < 2; j++) { MoveOption.Key key = new MoveOption.Key(dest, i, j); MoveOption es = null; if ((es = getAllMoves().get(key)) != null) { result.add(es); } } } return result; } /** * Returns an estimate of damage given the range to the target and * a modifier to the to-hit number. An approximation of the original * to-hit odds is extracted from the damage at that range leaving the * damage that is (hopefully) close to the original value. New odds * are generated based on the units gunnery skill and the modifier * and factored back into the returned damage value. */ public double getModifiedDamage(int arc, int a_range, int modifier) { if (a_range > MAX_RANGE) return 0.0; double damage = this.damages[arc][a_range]; // Use pilots gunnery skill, not the piloting skill... int base = entity.getCrew().getGunnery(); int dist_mod = 0; // Check range brackets based on defined maximum possible // range of weapon double range_bracket = this.long_range/4.0; // Inside minimum range, penalties must be observed if (a_range <= MIN_BRACKET){ dist_mod += this.minRangeMods[a_range]; } // Medium range is +2 if (a_range > range_bracket){ dist_mod += 2; } // Long range is another +2 (i.e. +4) if (a_range > 2 * range_bracket){ dist_mod += 2; } // Anything past 3 "range brackets" is extreme range +8, // or +4 on top of previous modifiers if (a_range > 3 * range_bracket){ dist_mod += 4; } if ((base + dist_mod + modifier > tb.ignore) | (base + dist_mod + modifier > 12)) return 0.0; if (base + dist_mod + modifier == tb.ignore) damage *= 0.5; // Factor out the to-hit odds and re-factor in new odds with the passed modifier double old_odds = Compute.oddsAbove(base + dist_mod)/100; double new_odds = Compute.oddsAbove(dist_mod + modifier + base)/100; return new_odds * damage/old_odds; } /** * Determines the expected damage of a weapon attack, based on to-hit, salvo * sizes, and so on. Note that this is against a generic target, so defensive * coverage, whether trees, ECM, or AMS is not considered. Built in offensive * equipment will be counted, such as Artemis IV/V, as will minimum range * modifiers and inherent weapon modifiers. */ public static double getExpectedDamage(Entity attacker, Mounted weapon, int range, int gunskill) { int total_mod = gunskill; double[] expectedHitsByRackSize = { 0.0, 1.0, 1.58, 2.0, 2.63, 3.17, 4.0, 4.49, 4.98, 5.47, 6.31, 7.23, 8.14, 8.59, 9.04, 9.5, 10.1, 10.8, 11.42, 12.1, 12.7 }; boolean use_table = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -