using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; class AI { private Vector2 tractorPos; private Vector2 housePos; private Farm farm; private Vector2 Size; private Vector2 targetPos; private Inventory inventory = new Inventory(); private FertilizerHolder fertilizerHolder = new FertilizerHolder(); private int Rotation; private Astar astar = new Astar(); public bool WaitTwoFrames { get; set; } private Random r = new Random(); public void init() { inventory.initInventorySystem(); } public void update(Farm newFarm, Vector2 newSize, Vector2 newTractorPos, Vector2 newHousePos, Vector2 newtargetPos, int rotation) { tractorPos = new Vector2((int)newTractorPos.X, (int)newTractorPos.Y); housePos = new Vector2((int)newHousePos.X, (int)newHousePos.Y); targetPos = newtargetPos; farm = newFarm; Size = newSize; Rotation = rotation; astar.update(farm.getCrops(), Size, tractorPos, housePos, rotation); } public void drawInventory(Input input, SpriteBatch spriteBatch, SpriteFont Bold, Cargo itemStorageDefined) { inventory.printItems(input, spriteBatch, Bold); } public Path newTarget() { PriorityQueueC5 queue = new PriorityQueueC5(); int score = 0; int count = 0; int testsize = 2; Path newTarget; Nodes nodes; if (astar.GetAdjacentNodes(tractorPos).Count == 0) nodes = new Nodes(housePos); else nodes = astar.GetAdjacentNodes(tractorPos)[0]; if (tractorPos != housePos) if (inventory.getWeight() == inventory.getMaxWeight() || inventory.isMissingFertilizer()) { astar.update(farm.getCrops(), Size, tractorPos, housePos, housePos, Rotation); return astar.FindPath(true); } while (true) { for (int x = 0; x < Size.X; x++) for (int y = 0; y < Size.Y; y++) { if (farm.getCrop(x, y).getStatus() >= 2 && tractorPos != new Vector2(x, y)) { if (farm.getCrop(x, y).getStatus() != 2 && (farm.getCrop(x, y).getProductionRate() > 0.99f || !farm.getCrop(x, y).belowCapacity())) { //skip growing fields with high production rate } else { score = calculateSoilScore(x, y); queue.AddToQueue(x, y, score); if (farm.getCrop(x, y).getCropTimer() == 1 || farm.getCrop(x, y).getStatus() == 2) count++; } } } break; } if (queue.getCount() == 0) { astar.update(farm.getCrops(), Size, tractorPos, housePos, nodes.getCords(), Rotation); return newTarget = astar.FindPath(true); } newTarget = GetMinFNode(Math.Min(testsize, queue.getCount()), queue); queue = null; return newTarget; } public Farm changeCropStatus() { int x = (int)tractorPos.X; int y = (int)tractorPos.Y; Fertilizer fertilizer = new Fertilizer(); fertilizerHolder.init(); WaitTwoFrames = false; if (farm.getCrop(x, y).getStatus() >= 2) { fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType()))); while (!(farm.getCrop(x, y).isSaturated(-1)) && farm.getCrop(x, y).belowCapacity() && inventory.useItem(fertilizerHolder.GetFertilizerID(fertilizer.Name), 0, false)) { farm.getCrop(x, y).Fertilize(fertilizer); fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType()))); WaitTwoFrames = true; } } if (farm.getCrop(x, y).getCropTimer() == 1) { farm.setCropStatus(tractorPos.X, tractorPos.Y); if (farm.getCrop(x, y).getStatus() == 2) { inventory.addItem(farm.getCrop(x, y).getCropType() - 1, 1); } } return farm; } public Inventory getInventory() { return inventory; } private int calculateSoilScore(int x, int y) { int score = 1; int statusScore = 1; int timerScore = 1; int saturationScore = 1; int productionRateScore = 1; int aproxDistance = (int)(Math.Abs(x - tractorPos.X) + Math.Abs(y - tractorPos.Y)); Crops crop = farm.getCrop(x, y); int cropType = crop.getCropType(); if (crop.getCropTimer() == 1) timerScore = 100; productionRateScore = (int)(crop.getProductionRate() * 25); score = (int)(crop.getProductionRate() * -50); if (crop.getStatus() == 2) { statusScore = 50; productionRateScore = 0; } else if (crop.getStatus() == 3) statusScore = -100; if (!crop.isSaturated(2)) saturationScore = 5; else { saturationScore = -100; } return score + (-aproxDistance * 5) + statusScore + timerScore + saturationScore; } private float norm(float min, float max, float val) { return ((val - min) / (max - min)); } public Path GetMinFNode(int testSize, PriorityQueueC5 queue) { int index = 0; int min = 9999; Path path = new Path(); List entryList = new List(); Path[] pathList = new Path[testSize]; for (int i = 0; i < testSize; i++) { entryList.Add(queue.DeleteMax()); } for (int i = 0; i < testSize; i++) { Nodes temp = new Nodes(entryList[i].Coordinates); astar.update(farm.getCrops(), Size, tractorPos, housePos, temp.getCords(), Rotation); path = astar.FindPath(false); pathList[i] = path; Nodes tempF = new Nodes(path.getByIndex(0)); if (min > tempF.getF()) { min = tempF.getF(); index = i; } } return pathList[index].FlipArray(); } public Path GetMaxFNode(int testSize, PriorityQueueC5 queue) { int index = 0; int max = -9999; Path path = new Path(); List entryList = new List(); Path[] pathList = new Path[testSize]; for (int i = 0; i < testSize; i++) { entryList.Add(queue.DeleteMax()); } for (int i = 0; i < testSize; i++) { Nodes temp = new Nodes(entryList[i].Coordinates); astar.update(farm.getCrops(), Size, tractorPos, housePos, temp.getCords(), Rotation); path = astar.FindPath(false); pathList[i] = path; Nodes tempF = new Nodes(path.getByIndex(0)); if (max < tempF.getF()) { max = tempF.getF(); index = i; } } return pathList[index].FlipArray(); } public void reloadCargo() { inventory.clearInventory(); inventory.fillWithFertilizer(); } }