package ai.general; import java.util.ArrayList; import rts.units.Unit; import rts.units.UnitAction; /** * \brief Manages the farming of resources * @author Jeff Bernard * */ public class FarmManager extends TaskManager { public ArrayList<GeneralAIFarm> farms; /**< resource fields we know about */ public ArrayList<GeneralAIFarm> owned_farms; /**< a quick listing of all the farms that we "own" */ public int workers_wanted; /**< how many workers we want, but don't exist */ public ArrayList<Integer> neutral_farms; /** * Constructs a new farm manager */ public FarmManager() { super(); farms = new ArrayList<GeneralAIFarm>(); owned_farms = new ArrayList<GeneralAIFarm>(); workers_wanted = 0; neutral_farms = new ArrayList<Integer>(); } @Override /** * Requests units to start farming * @param ai the parent ai */ public void manage_units(GeneralAI ai) { // check if any of the scouted units have become available for (int i = 0; i < units_scouted.size(); i++) { GeneralAIUnit unit = units_scouted.get(i); if (unit.strategy == GeneralAI.STRATEGY_NONE) { // free agent!! unit.strategy = GeneralAI.STRATEGY_FARM; unit.wanted_strategy = GeneralAI.STRATEGY_NONE; unit.object = null; for (int j = 0; j < owned_farms.size(); j++) { GeneralAIFarm farm = owned_farms.get(j); for (int k = 0; k < farm.farmers.length; k++) { if (farm.farmers[k] == unit.stats.getID()) { unit.object = farm; break; } } if (unit.object != null) { break; } } units.add(unit); units_scouted.remove(i--); } else if (unit.wanted_strategy == GeneralAI.STRATEGY_NONE) { unit.wanted_strategy = GeneralAI.STRATEGY_FARM; } } // figure out how units we want to scout workers_wanted = 0; for (int i = 0; i < owned_farms.size(); i++) { GeneralAIFarm farm = owned_farms.get(i); if (farm.has_openings_strict()) { boolean done_farm = false; for (int k = 0; k < farm.farmers.length; k++) { if (farm.farmers[k] == GeneralAIFarm.FARM_OPEN) { GeneralAIUnit closest_unit = null; int distance = GeneralAI.DISTANCE_IGNORE; for (int j = 0; j < ai.units.size(); j++) { GeneralAIUnit unit = ai.units.get(j); if (unit.stats.isWorker() && unit.wanted_strategy != GeneralAI.STRATEGY_FARM && unit.strategy != GeneralAI.STRATEGY_FARM) { // make sure not a unit already scouted int d = farm.distance(unit, ai); if (distance == GeneralAI.DISTANCE_IGNORE || (d != GeneralAI.DISTANCE_IGNORE && d < distance)) { distance = d; closest_unit = unit; } } } if (closest_unit != null) { if (closest_unit.strategy == GeneralAI.STRATEGY_NONE) { // we can recruit him now! closest_unit.strategy = GeneralAI.STRATEGY_FARM; closest_unit.object = farm; units.add(closest_unit); } else { units_scouted.add(closest_unit); } closest_unit.wanted_strategy = GeneralAI.STRATEGY_FARM; farm.farmers[k] = closest_unit.stats.getID(); } else if (!done_farm && !neutral_farms.contains(i)) { workers_wanted++; } done_farm = true; } } } } // update what we're doing with each of the unit's we've got for (int i = 0; i < units.size(); i++) { GeneralAIUnit unit = units.get(i); if (ai.state.isFog() && unit.wanted_strategy == GeneralAI.STRATEGY_BUILD) { // can we give this unit up? // farm will only give up to build requests, when this unit has just performed return if (unit.last_action == UnitAction.RETURN) { unit.strategy = GeneralAI.STRATEGY_NONE; units.remove(i--); units_scouted.add(unit); // but we're going to want him back when he's done continue; } } if (unit.object == null) { // he needs a farm to farm at int distance = GeneralAI.DISTANCE_IGNORE; for (int j = 0; j < owned_farms.size(); j++) { int d = owned_farms.get(j).distance(unit, ai); if (d != GeneralAI.DISTANCE_IGNORE && (distance == GeneralAI.DISTANCE_IGNORE || d < distance)) { unit.object = owned_farms.get(j); distance = d; } } if (unit.object == null) { // there are no farms for this unit, so release his servitude unit.strategy = GeneralAI.STRATEGY_NONE; units.remove(i--); } } } } @Override /** * Removes a unit from a farm (unit has likely died) * @param id */ public void remove_unit(long id) { super.remove_unit(id); for (int i = 0; i < owned_farms.size(); i++) { GeneralAIFarm farm = owned_farms.get(i); for (int j = 0; j < farm.farmers.length; j++) { if (farm.farmers[j] == id) { farm.farmers[j] = farm._farmers[j]; return; } } } } @Override /** * Updates farm data */ public void update(GeneralAI ai) { // consider resources found for (int i = 0; i < ai.state.getNeutralUnits().size(); i++) { Unit resource = ai.state.getNeutralUnits().get(i); if (resource.isResources()) { boolean alreadyHas = false; for (int j = 0; j < farms.size(); j++) { GeneralAIFarm farm = farms.get(j); if (resource.getID() == farm.resources.getID()) { farm.resources = resource; alreadyHas = true; break; } } if (!alreadyHas) { GeneralAIFarm farm = new GeneralAIFarm(resource, ai); farms.add(farm); boolean added = false; for (int j = 0; j < ai.town_manager.towns.size(); j++) { if (ai.town_manager.towns.get(j).add(farm)) { added = true; break; } } if (!added) { ai.town_manager.towns.add(new GeneralAITown(farm, ai.production_manager.buildings_possible.size())); } } else { // } } } // remove any empty resources for (int i = 0; i < farms.size(); i++) { GeneralAIFarm farm = farms.get(i); if (farm.resources.getResources() <= 0) { for (int j = 0; j < farm.farmers.length; j++) { if (farm.farmers[j] >= 0) { for (int k = 0; k < units.size(); k++) { if (units.get(k).stats.getID() == farm.farmers[j] && units.get(k).object != null) { units.get(k).object.remove(units.get(k), ai); if (units.get(k).object == null) { units.get(k).strategy = GeneralAI.STRATEGY_NONE; units.remove(k); } break; } } } } for (int j = 0; j < ai.town_manager.towns.size(); j++) { if (ai.town_manager.towns.get(j).remove(farm)) { if (ai.town_manager.towns.get(j).population() == 0) { ai.town_manager.towns.remove(j); } break; } } farms.remove(i--); } } owned_farms.clear(); neutral_farms.clear(); for (int i = 0; i < ai.town_manager.towns.size(); i++) { if ((ai.town_manager.towns.get(i).owner == ai.player_id && ai.town_manager.towns.get(i).has_stockpile()) || ai.town_manager.towns.get(i).owner == -1) { for (int j = 0; j < ai.town_manager.towns.get(i).farms.size(); j++) { if (ai.town_manager.towns.get(i).owner == -1) { neutral_farms.add(owned_farms.size()); } owned_farms.add(ai.town_manager.towns.get(i).farms.get(j)); owned_farms.get(owned_farms.size()-1).update_openings(ai); } } } } }