2020-05-05 16:27:45 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Microsoft.Xna.Framework;
|
2020-05-06 16:22:30 +02:00
|
|
|
|
using Microsoft.Xna.Framework.Graphics;
|
2020-05-05 16:27:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AI
|
|
|
|
|
{
|
|
|
|
|
private Vector2 tractorPos;
|
|
|
|
|
private Vector2 housePos;
|
2020-05-06 16:22:30 +02:00
|
|
|
|
private Farm farm;
|
2020-05-05 16:27:45 +02:00
|
|
|
|
private Vector2 Size;
|
|
|
|
|
private Vector2 targetPos;
|
2020-05-06 16:22:30 +02:00
|
|
|
|
private Inventory inventory = new Inventory();
|
2020-05-10 01:38:08 +02:00
|
|
|
|
private FertilizerHolder fertilizerHolder = new FertilizerHolder();
|
2020-05-05 16:27:45 +02:00
|
|
|
|
private int Rotation;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
private Astar astar = new Astar();
|
2020-05-10 15:02:22 +02:00
|
|
|
|
public bool WaitTwoFrames { get; set; }
|
2020-05-05 16:27:45 +02:00
|
|
|
|
|
|
|
|
|
private Random r = new Random();
|
|
|
|
|
|
|
|
|
|
|
2020-05-06 16:22:30 +02:00
|
|
|
|
public void init()
|
|
|
|
|
{
|
|
|
|
|
inventory.initInventorySystem();
|
|
|
|
|
}
|
2020-05-05 16:27:45 +02:00
|
|
|
|
|
|
|
|
|
|
2020-05-06 16:22:30 +02:00
|
|
|
|
public void update(Farm newFarm, Vector2 newSize, Vector2 newTractorPos, Vector2 newHousePos, Vector2 newtargetPos, int rotation)
|
2020-05-05 16:27:45 +02:00
|
|
|
|
{
|
|
|
|
|
tractorPos = new Vector2((int)newTractorPos.X, (int)newTractorPos.Y);
|
|
|
|
|
housePos = new Vector2((int)newHousePos.X, (int)newHousePos.Y);
|
|
|
|
|
targetPos = newtargetPos;
|
2020-05-06 16:22:30 +02:00
|
|
|
|
farm = newFarm;
|
2020-05-05 16:27:45 +02:00
|
|
|
|
Size = newSize;
|
|
|
|
|
Rotation = rotation;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
astar.update(farm.getCrops(), Size, tractorPos, housePos, rotation);
|
2020-05-05 16:27:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-05-06 16:22:30 +02:00
|
|
|
|
public void drawInventory(Input input, SpriteBatch spriteBatch, SpriteFont Bold, Cargo itemStorageDefined)
|
|
|
|
|
{
|
|
|
|
|
inventory.printItems(input, spriteBatch, Bold);
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
public Path newTarget()
|
2020-05-05 16:27:45 +02:00
|
|
|
|
{
|
2020-05-07 22:09:45 +02:00
|
|
|
|
PriorityQueueC5 queue = new PriorityQueueC5();
|
|
|
|
|
int score = 0;
|
2020-05-08 00:35:53 +02:00
|
|
|
|
int count = 0;
|
|
|
|
|
int testsize = 2;
|
2020-05-10 13:51:19 +02:00
|
|
|
|
Path newTarget;
|
2020-05-10 18:17:53 +02:00
|
|
|
|
Nodes nodes;
|
2020-05-24 01:57:27 +02:00
|
|
|
|
Random random = new Random();
|
2020-05-10 21:16:24 +02:00
|
|
|
|
|
2020-05-10 18:17:53 +02:00
|
|
|
|
if (astar.GetAdjacentNodes(tractorPos).Count == 0)
|
|
|
|
|
nodes = new Nodes(housePos);
|
|
|
|
|
else
|
2020-05-24 01:57:27 +02:00
|
|
|
|
{
|
|
|
|
|
List<Nodes> templist = astar.GetAdjacentNodes(tractorPos);
|
|
|
|
|
nodes = templist[random.Next(0, templist.Count())];
|
|
|
|
|
templist.Clear();
|
|
|
|
|
}
|
2020-05-10 21:16:24 +02:00
|
|
|
|
|
2020-05-10 01:38:08 +02:00
|
|
|
|
if (tractorPos != housePos)
|
|
|
|
|
if (inventory.getWeight() == inventory.getMaxWeight() || inventory.isMissingFertilizer())
|
2020-05-10 13:51:19 +02:00
|
|
|
|
{
|
|
|
|
|
astar.update(farm.getCrops(), Size, tractorPos, housePos, housePos, Rotation);
|
|
|
|
|
return astar.FindPath(true);
|
|
|
|
|
}
|
2020-05-08 00:35:53 +02:00
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
for (int x = 0; x < Size.X; x++)
|
|
|
|
|
for (int y = 0; y < Size.Y; y++)
|
2020-05-07 22:09:45 +02:00
|
|
|
|
{
|
2020-05-08 00:35:53 +02:00
|
|
|
|
if (farm.getCrop(x, y).getStatus() >= 2 && tractorPos != new Vector2(x, y))
|
2020-05-07 22:09:45 +02:00
|
|
|
|
{
|
2020-05-10 21:16:24 +02:00
|
|
|
|
if (farm.getCrop(x, y).getStatus() != 2 && (farm.getCrop(x, y).getProductionRate() > 0.99f || !farm.getCrop(x, y).belowCapacity()))
|
2020-05-10 01:38:08 +02:00
|
|
|
|
{
|
2020-05-10 21:16:24 +02:00
|
|
|
|
//skip growing fields with high production rate
|
2020-05-10 01:38:08 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
score = calculateSoilScore(x, y);
|
|
|
|
|
queue.AddToQueue(x, y, score);
|
|
|
|
|
if (farm.getCrop(x, y).getCropTimer() == 1 || farm.getCrop(x, y).getStatus() == 2)
|
|
|
|
|
count++;
|
|
|
|
|
}
|
2020-05-07 22:09:45 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-08 00:35:53 +02:00
|
|
|
|
break;
|
|
|
|
|
}
|
2020-05-10 21:16:24 +02:00
|
|
|
|
|
2020-05-10 18:17:53 +02:00
|
|
|
|
if (queue.getCount() == 0)
|
|
|
|
|
{
|
|
|
|
|
astar.update(farm.getCrops(), Size, tractorPos, housePos, nodes.getCords(), Rotation);
|
|
|
|
|
return newTarget = astar.FindPath(true);
|
2020-05-10 21:16:24 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newTarget = GetMinFNode(Math.Min(testsize, queue.getCount()), queue);
|
2020-05-10 01:38:08 +02:00
|
|
|
|
queue = null;
|
2020-05-09 15:54:53 +02:00
|
|
|
|
|
2020-05-07 22:09:45 +02:00
|
|
|
|
return newTarget;
|
2020-05-05 16:27:45 +02:00
|
|
|
|
}
|
2020-05-06 16:22:30 +02:00
|
|
|
|
|
|
|
|
|
public Farm changeCropStatus()
|
|
|
|
|
{
|
2020-05-10 01:38:08 +02:00
|
|
|
|
int x = (int)tractorPos.X;
|
|
|
|
|
int y = (int)tractorPos.Y;
|
|
|
|
|
Fertilizer fertilizer = new Fertilizer();
|
|
|
|
|
fertilizerHolder.init();
|
2020-05-10 15:02:22 +02:00
|
|
|
|
WaitTwoFrames = false;
|
2020-05-10 12:55:13 +02:00
|
|
|
|
if (farm.getCrop(x, y).getStatus() >= 2)
|
2020-05-06 16:22:30 +02:00
|
|
|
|
{
|
2020-05-10 12:55:13 +02:00
|
|
|
|
fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType())));
|
2020-05-11 01:11:00 +02:00
|
|
|
|
while (!(farm.getCrop(x, y).isSaturated(-1)) && farm.getCrop(x, y).belowCapacity() && inventory.useItem(fertilizerHolder.GetFertilizerID(fertilizer.Name), 0, false))
|
2020-05-10 01:38:08 +02:00
|
|
|
|
{
|
2020-05-10 12:55:13 +02:00
|
|
|
|
farm.getCrop(x, y).Fertilize(fertilizer);
|
2020-05-10 01:38:08 +02:00
|
|
|
|
fertilizer = fertilizerHolder.GetFertilizer(Engine.PredictFertilizer(farm.getCrop(x, y), farm.getPresetCropTypes(farm.getCrop(x, y).getCropType())));
|
2020-05-10 15:02:22 +02:00
|
|
|
|
WaitTwoFrames = true;
|
2020-05-10 01:38:08 +02:00
|
|
|
|
}
|
2020-05-10 12:55:13 +02:00
|
|
|
|
}
|
|
|
|
|
if (farm.getCrop(x, y).getCropTimer() == 1)
|
|
|
|
|
{
|
2020-05-06 16:22:30 +02:00
|
|
|
|
farm.setCropStatus(tractorPos.X, tractorPos.Y);
|
2020-05-10 01:38:08 +02:00
|
|
|
|
if (farm.getCrop(x, y).getStatus() == 2)
|
2020-05-09 13:48:28 +02:00
|
|
|
|
{
|
2020-05-10 01:38:08 +02:00
|
|
|
|
inventory.addItem(farm.getCrop(x, y).getCropType() - 1, 1);
|
2020-05-09 13:48:28 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-06 16:22:30 +02:00
|
|
|
|
}
|
|
|
|
|
return farm;
|
|
|
|
|
}
|
2020-05-06 20:48:20 +02:00
|
|
|
|
|
|
|
|
|
public Inventory getInventory()
|
|
|
|
|
{
|
|
|
|
|
return inventory;
|
|
|
|
|
}
|
2020-05-07 22:09:45 +02:00
|
|
|
|
|
|
|
|
|
private int calculateSoilScore(int x, int y)
|
|
|
|
|
{
|
2020-05-10 21:16:24 +02:00
|
|
|
|
int score = 1;
|
|
|
|
|
int statusScore = 1;
|
|
|
|
|
int timerScore = 1;
|
|
|
|
|
int saturationScore = 1;
|
|
|
|
|
int productionRateScore = 1;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
int aproxDistance = (int)(Math.Abs(x - tractorPos.X) + Math.Abs(y - tractorPos.Y));
|
|
|
|
|
|
|
|
|
|
Crops crop = farm.getCrop(x, y);
|
|
|
|
|
int cropType = crop.getCropType();
|
2020-05-10 21:16:24 +02:00
|
|
|
|
|
|
|
|
|
if (crop.getCropTimer() == 1)
|
|
|
|
|
timerScore = 100;
|
|
|
|
|
|
|
|
|
|
productionRateScore = (int)(crop.getProductionRate() * 25);
|
|
|
|
|
score = (int)(crop.getProductionRate() * -50);
|
2020-05-07 22:09:45 +02:00
|
|
|
|
|
|
|
|
|
if (crop.getStatus() == 2)
|
2020-05-10 21:16:24 +02:00
|
|
|
|
{
|
2020-05-10 12:55:13 +02:00
|
|
|
|
statusScore = 50;
|
2020-05-10 21:16:24 +02:00
|
|
|
|
productionRateScore = 0;
|
|
|
|
|
}
|
2020-05-07 22:09:45 +02:00
|
|
|
|
else if (crop.getStatus() == 3)
|
2020-05-09 15:54:53 +02:00
|
|
|
|
statusScore = -100;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
|
2020-05-10 12:55:13 +02:00
|
|
|
|
if (!crop.isSaturated(2))
|
2020-05-10 01:38:08 +02:00
|
|
|
|
saturationScore = 5;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
saturationScore = -100;
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-24 01:57:27 +02:00
|
|
|
|
return score + (-aproxDistance * 10) + statusScore + timerScore + saturationScore;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private float norm(float min, float max, float val)
|
|
|
|
|
{
|
|
|
|
|
return ((val - min) / (max - min));
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
public Path GetMinFNode(int testSize, PriorityQueueC5 queue)
|
2020-05-07 22:09:45 +02:00
|
|
|
|
{
|
|
|
|
|
int index = 0;
|
2020-05-09 15:54:53 +02:00
|
|
|
|
int min = 9999;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
Path path = new Path();
|
|
|
|
|
List<PQEntry> entryList = new List<PQEntry>();
|
2020-05-10 13:51:19 +02:00
|
|
|
|
Path[] pathList = new Path[testSize];
|
2020-05-07 22:09:45 +02:00
|
|
|
|
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);
|
2020-05-10 13:51:19 +02:00
|
|
|
|
astar.update(farm.getCrops(), Size, tractorPos, housePos, temp.getCords(), Rotation);
|
2020-05-07 22:09:45 +02:00
|
|
|
|
path = astar.FindPath(false);
|
2020-05-10 13:51:19 +02:00
|
|
|
|
pathList[i] = path;
|
2020-05-07 22:09:45 +02:00
|
|
|
|
Nodes tempF = new Nodes(path.getByIndex(0));
|
|
|
|
|
if (min > tempF.getF())
|
|
|
|
|
{
|
|
|
|
|
min = tempF.getF();
|
|
|
|
|
index = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
return pathList[index].FlipArray();
|
2020-05-07 22:09:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
public Path GetMaxFNode(int testSize, PriorityQueueC5 queue)
|
2020-05-09 15:54:53 +02:00
|
|
|
|
{
|
|
|
|
|
int index = 0;
|
|
|
|
|
int max = -9999;
|
|
|
|
|
Path path = new Path();
|
|
|
|
|
List<PQEntry> entryList = new List<PQEntry>();
|
2020-05-10 13:51:19 +02:00
|
|
|
|
Path[] pathList = new Path[testSize];
|
2020-05-09 15:54:53 +02:00
|
|
|
|
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);
|
2020-05-10 13:51:19 +02:00
|
|
|
|
astar.update(farm.getCrops(), Size, tractorPos, housePos, temp.getCords(), Rotation);
|
2020-05-09 15:54:53 +02:00
|
|
|
|
path = astar.FindPath(false);
|
2020-05-10 13:51:19 +02:00
|
|
|
|
pathList[i] = path;
|
2020-05-09 15:54:53 +02:00
|
|
|
|
Nodes tempF = new Nodes(path.getByIndex(0));
|
|
|
|
|
if (max < tempF.getF())
|
|
|
|
|
{
|
|
|
|
|
max = tempF.getF();
|
|
|
|
|
index = i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
return pathList[index].FlipArray();
|
2020-05-09 15:54:53 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-10 13:51:19 +02:00
|
|
|
|
|
2020-05-10 01:38:08 +02:00
|
|
|
|
public void reloadCargo()
|
|
|
|
|
{
|
|
|
|
|
inventory.clearInventory();
|
|
|
|
|
inventory.fillWithFertilizer();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-09 15:54:53 +02:00
|
|
|
|
|
|
|
|
|
|
2020-05-05 16:27:45 +02:00
|
|
|
|
}
|