forked from s425077/PotatoPlan
203 lines
6.3 KiB
C#
203 lines
6.3 KiB
C#
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 int Rotation;
|
|
private PriorityQueueC5 PriorityQueueC5;
|
|
private Astar astar = new Astar();
|
|
|
|
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 Vector2 newTarget()
|
|
{
|
|
PriorityQueueC5 queue = new PriorityQueueC5();
|
|
int score = 0;
|
|
int count = 0;
|
|
int testsize = 2;
|
|
Vector2 newTarget;
|
|
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() == 3 && farm.getCrop(x, y).getCropTimer() != 1)
|
|
{
|
|
if (housePos == tractorPos)
|
|
{
|
|
score = calculateSoilScore(x, y);
|
|
queue.AddToQueue(x, y, score);
|
|
count++;
|
|
}
|
|
//do nothing
|
|
}
|
|
else
|
|
{
|
|
score = calculateSoilScore(x, y);
|
|
queue.AddToQueue(x, y, score);
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
if (count > 0)
|
|
break;
|
|
else if (tractorPos != housePos)
|
|
return housePos;
|
|
|
|
/*
|
|
else if (tractorPos == housePos)
|
|
{
|
|
List<Nodes> temp = astar.GetAdjacentNodes(tractorPos);
|
|
return temp[0].getCords();
|
|
}
|
|
*/
|
|
}
|
|
|
|
newTarget = GetMinFNode(Math.Min(testsize, count), queue);
|
|
return newTarget;
|
|
}
|
|
|
|
public Farm changeCropStatus()
|
|
{
|
|
if (farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getCropTimer() == 1)
|
|
{
|
|
farm.setCropStatus(tractorPos.X, tractorPos.Y);
|
|
if (farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getStatus() == 2)
|
|
{
|
|
inventory.addItem(farm.getCrop((int)tractorPos.X, (int)tractorPos.Y).getCropType() - 1, 1);
|
|
}
|
|
|
|
}
|
|
return farm;
|
|
}
|
|
|
|
public Inventory getInventory()
|
|
{
|
|
return inventory;
|
|
}
|
|
|
|
private int calculateSoilScore(int x, int y)
|
|
{
|
|
int score = 0;
|
|
int statusScore = 0;
|
|
int aproxDistance = (int)(Math.Abs(x - tractorPos.X) + Math.Abs(y - tractorPos.Y));
|
|
CropTypesHolder holder = new CropTypesHolder();
|
|
holder.init();
|
|
|
|
Crops crop = farm.getCrop(x, y);
|
|
SoilProperties soilP = crop.getSoilProperties();
|
|
int cropType = crop.getCropType();
|
|
CropTypes avgHold = holder.getPresetCropTypes(cropType);
|
|
|
|
if (crop.getStatus() == 2)
|
|
statusScore = 25;
|
|
else if (crop.getStatus() == 3)
|
|
statusScore = 5;
|
|
else if (crop.getStatus() == 4)
|
|
statusScore = -10;
|
|
else
|
|
statusScore = 1;
|
|
|
|
float[] currentValue = { soilP.Temperature, soilP.Humidity, soilP.Moisture, soilP.Nitrogen, soilP.Potassium, soilP.Phosphorous };
|
|
float[] targetAvg = { avgHold.Temparature, avgHold.Humidity, avgHold.Moisture, avgHold.Nitrogen, avgHold.Potassium, avgHold.Phosphorous };
|
|
float[,] minMax = { {22,30}, {22*1.9f, 30*2.1f}, {20, 70}, {4, 55}, {0, 28}, {0, 60} }; //probably should make it dynamic
|
|
float[] normVal = normArray(minMax, currentValue);
|
|
float[] normAvg = normArray(minMax, targetAvg);
|
|
|
|
for (int i = 0; i < normVal.Count(); i++)
|
|
{
|
|
score = score + (int)Math.Round(System.Convert.ToDouble(10*(1 - Math.Abs(normAvg[i] - normVal[i]))));
|
|
}
|
|
|
|
return score + (-aproxDistance * 3) + statusScore;
|
|
}
|
|
|
|
private float[] normArray(float[,] minMax, float[] values)
|
|
{
|
|
float[] temp = new float[values.Count()];
|
|
if (minMax.GetLength(0) != values.Count())
|
|
throw new InvalidOperationException("Values and their MinMax arrays are not of the same length!");
|
|
|
|
for (int i = 0; i < values.Count(); i++)
|
|
temp[i] = norm(minMax[i, 0], minMax[i, 1], values[i]);
|
|
|
|
return temp;
|
|
}
|
|
|
|
private float norm(float min, float max, float val)
|
|
{
|
|
return ((val - min) / (max - min));
|
|
}
|
|
|
|
public Vector2 GetMinFNode(int testSize, PriorityQueueC5 queue)
|
|
{
|
|
int index = 0;
|
|
int min = 999;
|
|
Path path = new Path();
|
|
List<PQEntry> entryList = new List<PQEntry>();
|
|
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);
|
|
path = astar.FindPath(false);
|
|
Nodes tempF = new Nodes(path.getByIndex(0));
|
|
if (min > tempF.getF())
|
|
{
|
|
min = tempF.getF();
|
|
index = i;
|
|
}
|
|
}
|
|
PQEntry minEntry = entryList[index];
|
|
entryList.RemoveAt(index);
|
|
|
|
//add the non-minimum entries back to the queue.
|
|
queue.AddAll(entryList);
|
|
|
|
return minEntry.Coordinates;
|
|
}
|
|
|
|
}
|