Compare commits

..

No commits in common. "master" and "Paweł" have entirely different histories.

11 changed files with 252 additions and 491 deletions

View File

@ -1,3 +1,5 @@
import random
import keyboard as keyboard import keyboard as keyboard
import field as F import field as F
@ -9,20 +11,18 @@ from src import mapschema as maps
def genetic_algorithm_setup(field): def genetic_algorithm_setup(field):
population_units = ["", "w", "p", "s"] population_units = ["", "w", "p", "s"]
# TODO REPREZENTACJA OSOBNIKA - MACIERZ ROZKłADU PLONÓW # new_population to be
population_text = [] population_text = []
population_text_single = []
population_size = 10
# Populate the population_text array # Populate the population_text array
for k in range(population_size):
population_text_single = []
for row in range(D.GSIZE): for row in range(D.GSIZE):
population_text_single.append([]) population_text.append([])
for column in range(D.GSIZE): for column in range(D.GSIZE):
population_text_single[row].append(random.choice(population_units)) population_text[row].append(random.choice(population_units))
population_text.append(population_text_single)
# printer
for _ in population_text:
print(population_text)
""" """
Genetic algorithm parameters: Genetic algorithm parameters:
@ -31,110 +31,75 @@ def genetic_algorithm_setup(field):
""" """
# units per population in generation # units per population in generation
best_outputs = [] sol_per_pop = 8
num_generations = 100 num_parents_mating = 4
num_parents = 4
population_values = []
fitness_row = []
# population Fitness
for i in range(0, D.GSIZE):
for j in range(D.GSIZE):
fitness_row.append(local_fitness(field, i, j, population_text))
population_values.append(fitness_row)
best_outputs = []
num_generations = 10
# iterative var
generation = 0 generation = 0
stop = 0
# TODO WARUNEK STOPU while generation < num_generations:
while generation < num_generations and stop < 3:
if keyboard.is_pressed('space'): if keyboard.is_pressed('space'):
generation += 1 generation += 1
print("Generation : ", generation) print("Generation : ", generation)
# Measuring the fitness of each chromosome in the population. # Measuring the fitness of each chromosome in the population.
# population Fitness fitness = cal_pop_fitness(population_values)
fitness = []
for i in range(0, population_size):
fitness.append((i, population_fitness(population_text[i], field, population_size)))
print("Fitness") print("Fitness")
print(fitness) print(fitness)
best = sorted(fitness, key=lambda tup: tup[1], reverse=True)[0:num_parents] # best_outputs.append(best_Output(new_population))
# Leaderboard only
best_outputs.append(best[0][1])
# The best result in the current iteration. # The best result in the current iteration.
print("Best result : ", best[0]) # print("Best result : ", best_Output(new_population))
# TODO METODA WYBORU OSOBNIKA - RANKING
# Selecting the best parents in the population for mating. # Selecting the best parents in the population for mating.
parents = [population_text[i[0]] for i in best] parents = select_mating_pool(new_population, fitness,
parents_copy = copy.deepcopy(parents) num_parents_mating)
print("Parents") print("Parents")
for i in range(0, len(parents)): print(parents)
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in parents[i]]))
print("")
# Generating next generation using crossover. # Generating next generation using crossover.
offspring_x = random.randint(1, D.GSIZE - 2) offspring_crossover = crossover(parents, offspring_size=(pop_size[0] - parents.shape[0], num_weights))
offspring_y = random.randint(1, D.GSIZE - 2)
# TODO OPERATOR KRZYŻOWANIA
offspring_crossover = crossover(parents)
print("Crossover") print("Crossover")
for i in range(0, len(offspring_crossover)): print(offspring_crossover)
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in offspring_crossover[i]]))
print("")
# TODO OPERATOR MUTACJI # Adding some variations to the offspring using mutation.
offspring_mutation = mutation(population_units, offspring_crossover, population_size - num_parents, offspring_mutation = mutation(offspring_crossover, num_mutations=2)
num_mutations=10)
print("Mutation") print("Mutation")
for i in range(0, len(offspring_mutation)): print(offspring_mutation)
print('\n'.join([''.join(['{:4}'.format(item) for item in row])
for row in offspring_mutation[i]]))
print("")
population_text_copy = copy.deepcopy(population_text) # Creating the new population based on the parents and offspring.
unused_indexes = [i for i in range(0, population_size) if i not in [j[0] for j in best]] new_population[0:parents.shape[0], :] = parents
# Creating next generation new_population[parents.shape[0]:, :] = offspring_mutation
population_text = []
for k in parents_copy:
population_text.append(k)
for k in range(0, len(offspring_mutation)):
population_text.append(offspring_mutation[k])
while len(population_text) < population_size:
x = random.choice(unused_indexes)
population_text.append(population_text_copy[x])
unused_indexes.remove(x)
# TODO WARUNEK STOPU # Getting the best solution after iterating finishing all generations.
stop = 0 # At first, the fitness is calculated for each solution in the final generation.
if generation > 10: fitness = cal_pop_fitness(new_population)
if best_outputs[-1] / best_outputs[-2] < 1.001: # Then return the index of that solution corresponding to the best fitness.
stop += 1 best_match_idx = numpy.where(fitness == numpy.max(fitness))
if best_outputs[-1] / best_outputs[-3] < 1.001:
stop += 1
if best_outputs[-2] / best_outputs[-3] < 1.001:
stop += 1
# final Fitness print("Best solution : ", new_population[best_match_idx, :])
fitness = [] print("Best solution fitness : ", fitness[best_match_idx])
for i in range(0, population_size):
fitness.append((i, population_fitness(population_text[i], field, population_size)))
print("Final Fitness") import matplotlib.pyplot
print(fitness)
best = sorted(fitness, key=lambda tup: tup[1])[0:num_parents] matplotlib.pyplot.plot(best_outputs)
matplotlib.pyplot.xlabel("Iteration")
matplotlib.pyplot.ylabel("Fitness")
matplotlib.pyplot.show()
print("Best solution : ", ) # return best iteration of field
for i in range(0, D.GSIZE):
print(population_text[best[0][0]][i])
print("Best solution fitness : ", best[0][1])
pretty_printer(best_outputs)
# TODO REALLY return best iteration of field
return 0 return 0

View File

@ -1,47 +1,63 @@
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
from matplotlib.pyplot import imshow
import os
import PIL import PIL
import numpy as np import torchvision.transforms as transforms
from matplotlib.pyplot import imshow
import neural_network from AI import neural_network
from matplotlib.pyplot import imshow
# wcześniej grader.py # wcześniej grinder.py
# Get accuracy for neural_network model 'network_model.pth' # Get accuracy for neural_network model 'network_model.pth'
def NN_accuracy(): def NN_accuracy():
# Create the model # Create the model
net = neural_network.Net() model = neural_network.Net()
# Load state_dict # Load state_dict
neural_network.load_network_from_structure(net) neural_network.load_network_from_structure(model)
# Create the preprocessing transformation here
transform = transforms.Compose([neural_network.Negative(), transforms.ToTensor()])
# load your image(s)
img = PIL.Image.open('../src/test/0_100.jpg')
img2 = PIL.Image.open('../src/test/1_100.jpg')
img3 = PIL.Image.open('../src/test/4_100.jpg')
img4 = PIL.Image.open('../src/test/5_100.jpg')
# Transform
input = transform(img)
input2 = transform(img2)
input3 = transform(img3)
input4 = transform(img4)
# unsqueeze batch dimension, in case you are dealing with a single image
input = input.unsqueeze(0)
input2 = input2.unsqueeze(0)
input3 = input3.unsqueeze(0)
input4 = input4.unsqueeze(0)
# Set model to eval # Set model to eval
net.eval() model.eval()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # Get prediction
output = model(input)
output2 = model(input2)
output3 = model(input3)
output4 = model(input4)
folderlist = os.listdir(os.path.dirname(__file__) + "\\test") print(output)
index = output.cpu().data.numpy().argmax()
print(index)
tested = 0 print(output2)
correct = 0 index = output2.cpu().data.numpy().argmax()
print(index)
for folder in folderlist: print(output3)
for file in os.listdir(os.path.dirname(__file__) + "\\test\\" + folder): index = output3.cpu().data.numpy().argmax()
if neural_network.result_from_network(net, os.path.dirname(__file__) + "\\test\\" + folder + "\\" + file) == folder: print(index)
correct += 1
tested += 1
else:
tested += 1
print(correct/tested) print(output4)
index = output4.cpu().data.numpy().argmax()
print(index)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -1,8 +1,3 @@
import copy
import random
import matplotlib
import matplotlib.pyplot
import numpy import numpy
import src.dimensions as D import src.dimensions as D
@ -10,94 +5,88 @@ import src.dimensions as D
# Genetic Algorithm methods # Genetic Algorithm methods
def local_fitness(field, x, y, plants_case): def local_fitness(field, x, y, plants):
soil_value = 0 soil_value = 0
if field[x][y].field_type == "soil": if field[x][y].field_type == "soil":
soil_value = 1 soil_value = 1
else: else:
soil_value = 0.5 soil_value = 0.5
if plants_case[x][y] == "": if plants[x][y] == "":
plant_value = 0 plant_value = 0
elif plants_case[x][y] == "w": elif plants[x][y] == "w":
plant_value = 1 plant_value = 1
elif plants_case[x][y] == "p": elif plants[x][y] == "p":
plant_value = 2 plant_value = 2
elif plants_case[x][y] == "s": elif plants[x][y] == "s":
plant_value = 3 plant_value = 3
else:
plant_value = 1
neighbour_bonus = 1 neighbour_bonus = 1
if x - 1 >= 0: if x - 1 >= 0:
if plants_case[x][y] == plants_case[x - 1][y]: if plants[x][y] == plants[x - 1][y]:
neighbour_bonus += 1 neighbour_bonus += 1
if x + 1 < D.GSIZE: if x + 1 < D.GSIZE:
if plants_case[x][y] == plants_case[x + 1][y]: if plants[x][y] == plants[x + 1][y]:
neighbour_bonus += 1 neighbour_bonus += 1
if y - 1 >= 0: if y - 1 >= 0:
if plants_case[x][y] == plants_case[x][y - 1]: if plants[x][y] == plants[x][y - 1]:
neighbour_bonus += 1 neighbour_bonus += 1
if y + 1 < D.GSIZE: if y + 1 < D.GSIZE:
if plants_case[x][y] == plants_case[x][y + 1]: if plants[x][y] == plants[x][y + 1]:
neighbour_bonus += 1 neighbour_bonus += 1
# TODO * multiculture_bonus
local_fitness_value = (soil_value + plant_value) * (0.5 * neighbour_bonus + 1) local_fitness_value = (soil_value + plant_value) * (0.5 * neighbour_bonus + 1)
return local_fitness_value return local_fitness_value
def population_fitness(population_text_local, field, population_size): def cal_pop_fitness(pop):
# Calculating the fitness value of each solution in the current population. # Calculating the fitness value of each solution in the current population.
# The fitness function calulates the sum of products between each input and its corresponding weight. # The fitness function calulates the sum of products between each input and its corresponding weight.
fitness = [] fitness = sum(map(sum, pop))
for k in range(population_size):
population_values_single = []
population_values_single_row = []
fitness_row = []
for i in range(0, D.GSIZE):
for j in range(0, D.GSIZE):
population_values_single_row.append(local_fitness(field, i, j, population_text_local))
population_values_single.append(population_values_single_row)
for i in range(D.GSIZE):
fitness_row.append(sum(population_values_single[i]))
fitness = sum(fitness_row)
return fitness return fitness
def crossover(local_parents): def select_mating_pool(pop, fitness, num_parents):
ret = [] # Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.
for i in range(0, len(local_parents)): parents = numpy.empty((num_parents, pop.shape[1]))
child = copy.deepcopy(local_parents[i]) for parent_num in range(num_parents):
# Vertical randomization max_fitness_idx = numpy.where(fitness == numpy.max(fitness))
width = random.randint(1, D.GSIZE // len(local_parents)) # width of stripes max_fitness_idx = max_fitness_idx[0][0]
indexes_parents = numpy.random.permutation(range(0, len(local_parents))) # sorting of stripes parents[parent_num, :] = pop[max_fitness_idx, :]
beginning = random.randint(0, len(local_parents[0]) - width * len( fitness[max_fitness_idx] = -99999999999
local_parents)) # point we start putting the stripes from return parents
for x in indexes_parents:
child[beginning:beginning + width] = local_parents[x][beginning:beginning + width]
beginning += width
ret.append(child)
return ret
def mutation(population_units, offspring_crossover, num_mutants, num_mutations=10): def crossover(parents, offspring_size):
for case in range(0, len(offspring_crossover)): offspring = numpy.empty(offspring_size)
for mutation in range(0, num_mutations): # The point at which crossover takes place between two parents. Usually, it is at the center.
mutation_x = random.randint(0, D.GSIZE - 1) crossover_point = numpy.uint8(offspring_size[1] / 2)
mutation_y = random.randint(0, D.GSIZE - 1)
mutation_value = random.choice(population_units)
offspring_crossover[case][mutation_x][mutation_y] = mutation_value
num_mutants -= 1
for k in range(offspring_size[0]):
# Index of the first parent to mate.
parent1_idx = k % parents.shape[0]
# Index of the second parent to mate.
parent2_idx = (k + 1) % parents.shape[0]
# The new offspring will have its first half of its genes taken from the first parent.
offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point]
# The new offspring will have its second half of its genes taken from the second parent.
offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:]
return offspring
def mutation(offspring_crossover, num_mutations=1):
mutations_counter = numpy.uint8(offspring_crossover.shape[1] / num_mutations)
# Mutation changes a number of genes as defined by the num_mutations argument. The changes are random.
for idx in range(offspring_crossover.shape[0]):
gene_idx = mutations_counter - 1
for mutation_num in range(num_mutations):
# The random value to be added to the gene.
random_value = numpy.random.uniform(-1.0, 1.0, 1)
offspring_crossover[idx, gene_idx] = offspring_crossover[idx, gene_idx] + random_value
gene_idx = gene_idx + mutations_counter
return offspring_crossover return offspring_crossover
def pretty_printer(best_outputs): def best_Output(new_population):
matplotlib.pyplot.plot(best_outputs) return numpy.max(numpy.sum(new_population * equation_inputs, axis=1))
matplotlib.pyplot.xlabel("Iteration")
matplotlib.pyplot.ylabel("Fitness")
matplotlib.pyplot.show()

View File

@ -1,20 +1,18 @@
import torch
import torchvision
import torchvision.transforms as transforms
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import numpy as np
from matplotlib.pyplot import imshow
import os
import PIL import PIL
import numpy as np import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from matplotlib.pyplot import imshow from matplotlib.pyplot import imshow
def to_negative(img): def to_negative(img):
img = PIL.ImageOps.invert(img) img = PIL.ImageOps.invert(img)
return img return img
class Negative(object): class Negative(object):
def __init__(self): def __init__(self):
pass pass
@ -22,46 +20,41 @@ class Negative(object):
def __call__(self, img): def __call__(self, img):
return to_negative(img) return to_negative(img)
transform = transforms.Compose([Negative(), transforms.ToTensor()])
train_set = torchvision.datasets.ImageFolder(root='train', transform=transform)
classes = ("pepper", "potato", "strawberry", "tomato")
BATCH_SIZE = 4 def plotdigit(image):
img = np.reshape(image, (-1, 100))
imshow(img, cmap='Greys')
transform = transforms.Compose([Negative(), transforms.ToTensor()])
train_set = torchvision.datasets.ImageFolder(root='../src/train', transform=transform)
classes = ("apple", "potato")
BATCH_SIZE = 2
train_loader = torch.utils.data.DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=0) train_loader = torch.utils.data.DataLoader(train_set, batch_size=BATCH_SIZE, shuffle=True, num_workers=0)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
class Net(nn.Module): class Net(nn.Module):
def __init__(self): def __init__(self):
super().__init__() super(Net, self).__init__()
self.network = nn.Sequential( self.flatten = nn.Flatten()
nn.Conv2d(3, 32, kernel_size=3, padding=1), #3 channels to 32 channels self.linear_relu_stack = nn.Sequential(
nn.Linear(3 * 100 * 100, 512),
nn.ReLU(), nn.ReLU(),
nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1), nn.Linear(512, 512),
nn.ReLU(), nn.ReLU(),
nn.MaxPool2d(2, 2), # output: 64 channels x 50 x 50 image size - decrease nn.Linear(512, 2),
nn.ReLU()
)
self.linear_relu_stack = self.linear_relu_stack.to(device)
nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1), def forward(self, x):
nn.ReLU(), x = self.flatten(x).to(device)
nn.Conv2d(128, 128, kernel_size=3, stride=1, padding=1), #increase power of model logits = self.linear_relu_stack(x).to(device)
nn.ReLU(), return logits
nn.MaxPool2d(2, 2), # output: 128 x 25 x 25
nn.Conv2d(128, 256, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.Conv2d(256, 256, kernel_size=3, stride=1, padding=1),
nn.ReLU(),
nn.MaxPool2d(5, 5), # output: 256 x 5 x 5
nn.Flatten(), #a single vector 256*5*5,
nn.Linear(256*5*5, 1024),
nn.ReLU(),
nn.Linear(1024, 512),
nn.ReLU(),
nn.Linear(512, 4))
def forward(self, xb):
return self.network(xb)
def training_network(): def training_network():
net = Net() net = Net()
@ -70,7 +63,7 @@ def training_network():
criterion = nn.CrossEntropyLoss() criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
for epoch in range(10): for epoch in range(4):
running_loss = 0.0 running_loss = 0.0
for i, data in enumerate(train_loader, 0): for i, data in enumerate(train_loader, 0):
inputs, labels = data[0].to(device), data[1].to(device) inputs, labels = data[0].to(device), data[1].to(device)
@ -81,7 +74,7 @@ def training_network():
optimizer.step() optimizer.step()
running_loss += loss.item() running_loss += loss.item()
if i % 200 == 199: if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss)) print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss))
running_loss = 0.0 running_loss = 0.0
@ -91,8 +84,8 @@ def training_network():
def result_from_network(net, loaded_image): def result_from_network(net, loaded_image):
image = PIL.Image.open(loaded_image) image = PIL.Image.open(loaded_image)
pil_to_tensor = transforms.Compose([Negative(), transforms.ToTensor()])(image.convert("RGB")).unsqueeze_(0) pil_to_tensor = transforms.ToTensor()(image.convert("RGB")).unsqueeze_(0)
outputs = net(pil_to_tensor) outputs = net(pil_to_tensor.to(device))
return classes[torch.max(outputs, 1)[1]] return classes[torch.max(outputs, 1)[1]]
@ -106,6 +99,7 @@ def load_network_from_structure(network):
network.load_state_dict(torch.load('network_model.pth')) network.load_state_dict(torch.load('network_model.pth'))
# Create network_model.pth
if __name__ == "__main__": if __name__ == "__main__":
print(torch.cuda.is_available()) print(torch.cuda.is_available())
training_network() training_network()

View File

@ -1,7 +1,9 @@
import pygame import pygame
from src.colors import * from src.colors import *
from src.dimensions import * from src.dimensions import *
class Field(pygame.sprite.Sprite): class Field(pygame.sprite.Sprite):
def __init__(self, row, column, field_type): def __init__(self, row, column, field_type):
super(Field, self).__init__() super(Field, self).__init__()
@ -24,62 +26,22 @@ class Field(pygame.sprite.Sprite):
self.position = [row, column] self.position = [row, column]
self.hydration = 0 self.hydration = 0
self.planted = 0 self.planted = 0
self.fertility = 0 self.fertility = 1
self.tractor_there = False self.tractor_there = False
def hydrate(self): def hydrate(self):
if self.field_type == "soil" and self.hydration <= 5: if self.field_type == "soil" and self.hydration <= 5:
self.hydration += 1 self.hydration += 1
if self.fertility == 1:
if self.hydration == 0: # color field to it's hydration value
self.surf.fill(REDDISH0) self.surf.fill(eval('BROWN' + str(self.hydration)))
self.fertility = 0
if self.hydration == 1:
self.surf.fill(REDDISH1)
if self.hydration == 2:
self.surf.fill(REDDISH2)
if self.hydration == 3:
self.surf.fill(REDDISH3)
if self.hydration == 4 or self.hydration == 5:
self.surf.fill(REDDISH4)
else:
if self.hydration == 0:
self.surf.fill(BROWN0)
if self.hydration == 1:
self.surf.fill(BROWN1)
if self.hydration == 2:
self.surf.fill(BROWN2)
if self.hydration == 3:
self.surf.fill(BROWN3)
if self.hydration == 4 or self.hydration == 5:
self.surf.fill(BROWN4)
def dehydrate(self): def dehydrate(self):
if self.field_type == "soil" and self.hydration > 0: if self.field_type == "soil" and self.hydration > 0:
self.hydration -= 1 self.hydration -= 1
if self.fertility == 1:
if self.hydration == 0: # color field to it's hydration value
self.surf.fill(REDDISH0) self.surf.fill(eval('BROWN' + str(self.hydration)))
self.fertility = 0
if self.hydration == 1:
self.surf.fill(REDDISH1)
if self.hydration == 2:
self.surf.fill(REDDISH2)
if self.hydration == 3:
self.surf.fill(REDDISH3)
if self.hydration == 4 or self.hydration == 5:
self.surf.fill(REDDISH4)
else:
if self.hydration == 0:
self.surf.fill(BROWN0)
if self.hydration == 1:
self.surf.fill(BROWN1)
if self.hydration == 2:
self.surf.fill(BROWN2)
if self.hydration == 3:
self.surf.fill(BROWN3)
if self.hydration == 4 or self.hydration == 5:
self.surf.fill(BROWN4)
def free(self): def free(self):
self.planted = 0 self.planted = 0

37
main.py
View File

@ -10,15 +10,12 @@ from pygame.locals import (
QUIT QUIT
) )
# Import other files from project # Import other files from project
import field as F import field as F
import node as N import node as N
import plant as P import plant as P
import src.colors as C import src.colors as C
import src.dimensions as D import src.dimensions as D
import AI.GeneticAlgorithm as ga
import AI.neural_network as nn
import tractor as T import tractor as T
from src import mapschema as maps from src import mapschema as maps
@ -47,16 +44,6 @@ if __name__ == "__main__":
field[row].append(fieldbit) field[row].append(fieldbit)
# genetic_algorithm_setup(field) # genetic_algorithm_setup(field)
num_of_plants = 0
plant_pops = []
best_plant_pop = []
goal_gen = 100
best_plant_pop, plant_pops, num_of_plants, fitness = ga.genetic_algorithm_setup(field, plant_pops, goal_gen)
net = nn.Net()
nn.load_network_from_structure(net)
net.eval()
# Create Tractor object # Create Tractor object
tractor = T.Tractor(field, [0, 0]) tractor = T.Tractor(field, [0, 0])
@ -71,11 +58,9 @@ if __name__ == "__main__":
for row in range(D.GSIZE): for row in range(D.GSIZE):
plants.append([]) plants.append([])
for column in range(D.GSIZE): for column in range(D.GSIZE):
if best_plant_pop[column][row] != "": if mapschema[column][row] != 0:
plantbit = P.Plant(field[row][column], best_plant_pop[column][row]) plantbit = P.Plant(field[row][column], mapschema[column][row])
plants[row].append(plantbit) plants[row].append(plantbit)
else:
plants[row].append(0)
# Create list for tractor instructions # Create list for tractor instructions
path = [] path = []
@ -92,6 +77,7 @@ if __name__ == "__main__":
# Main loop # Main loop
while RUNNING: while RUNNING:
# Look at every event in the queue
for event in pygame.event.get(): for event in pygame.event.get():
# Did the user hit a key? # Did the user hit a key?
if event.type == KEYDOWN: if event.type == KEYDOWN:
@ -119,11 +105,19 @@ if __name__ == "__main__":
tractor.rotate_right() tractor.rotate_right()
elif path[0] == "hydrate": elif path[0] == "hydrate":
tractor.hydrate(field) tractor.hydrate(field)
elif path[0] == "fertilize":
if plants[tractor.position[1]][tractor.position[0]]:
tractor.fertilize(field, plants, nn.result_from_network(net, plants[tractor.position[0]][tractor.position[1]].testimage))
path.pop(0) path.pop(0)
# Get all keys pressed at a time CURRENTLY UNUSED
pressed_keys = pygame.key.get_pressed()
# control tractor with pressed keys CURRENTLY UNUSED
if pressed_keys[K_UP]:
tractor.move()
elif pressed_keys[K_LEFT]:
tractor.rotate_left()
elif pressed_keys[K_RIGHT]:
tractor.rotate_right()
# Set the screen background # Set the screen background
screen.fill(C.DBROWN) screen.fill(C.DBROWN)
@ -139,7 +133,6 @@ if __name__ == "__main__":
# Plants grow with every 10th tick, then they are drawn # Plants grow with every 10th tick, then they are drawn
for row in plants: for row in plants:
for plant in row: for plant in row:
if plant != 0:
plant.tick() plant.tick()
plant.grow() plant.grow()
screen.blit(plant.surf, plant.rect) screen.blit(plant.surf, plant.rect)
@ -157,4 +150,4 @@ if __name__ == "__main__":
pygame.display.flip() pygame.display.flip()
# Ensure program maintains a stable framerate # Ensure program maintains a stable framerate
clock.tick(35) clock.tick(8)

56
node.py
View File

@ -137,12 +137,10 @@ class Node:
closedList.append(currentNode) closedList.append(currentNode)
if currentNode.field[currentNode.position[0]][currentNode.position[1]].planted and \ if currentNode.field[currentNode.position[0]][currentNode.position[1]].planted and \
currentNode.field[currentNode.position[0]][currentNode.position[1]].field_type == "soil" and \
currentNode.field[currentNode.position[0]][currentNode.position[1]].hydration < 2: currentNode.field[currentNode.position[0]][currentNode.position[1]].hydration < 2:
path = [] path = []
for _ in range(currentNode.field[currentNode.position[0]][currentNode.position[1]].hydration, 4): for _ in range(currentNode.field[currentNode.position[0]][currentNode.position[1]].hydration, 4):
path.append("hydrate") path.append("hydrate")
path.append("fertilize")
current = currentNode current = currentNode
while current is not None: while current is not None:
path.append(current.action) path.append(current.action)
@ -176,57 +174,3 @@ class Node:
continue continue
heapq.heappush(openList, child) heapq.heappush(openList, child)
def findPathToPlantSpot(self, goals):
startNode = Node(self.field, self.position, self.rotation)
openList = []
closedList = []
startNode.parent = None
heapq.heappush(openList, startNode)
while len(openList) > 0:
currentNode = heapq.heappop(openList)
closedList.append(currentNode)
if not currentNode.field[currentNode.position[0]][currentNode.position[1]].planted and \
goals[currentNode.position[0]][currentNode.position[1]] != "":
path = []
path.append("plant")
current = currentNode
while current is not None:
path.append(current.action)
current = current.parent
return path[::-1]
children = succesor(currentNode)
perm = 0
for child in children:
for closedChild in closedList:
if child.position == closedChild.position and child.rotation == closedChild.rotation and child.action == closedChild.action:
perm = 1
break
if perm == 1:
perm = 0
continue
child.parent = currentNode
child.startCost = currentNode.startCost + child.field[child.position[0]][child.position[1]].moveCost
child.heuristic = abs(startNode.position[0] - child.position[0]) + abs(
startNode.position[1] - child.position[1])
child.totalCost = child.startCost + child.heuristic
for openNode in openList:
if child.position == openNode.position and child.rotation == openNode.rotation and child.action == openNode.action and child.startCost >= openNode.startCost:
perm = 1
break
if perm == 1:
perm = 0
continue
heapq.heappush(openList, child)

110
plant.py
View File

@ -1,32 +1,29 @@
import os
import random
from AI.decision_tree import * from AI.decision_tree import *
from src.dimensions import * from src.dimensions import *
from src.sprites import * from src.sprites import *
from src.colors import *
path = os.path.dirname(__file__) + "\\src\\test\\"
class Plant(pygame.sprite.Sprite): class Plant(pygame.sprite.Sprite):
def __init__(self, field, species): def __init__(self, field, species):
super(Plant, self).__init__()
self.species = species self.species = species
if self.species == "tomato": if self.species == "wheat":
self.growth_speed = 1.5
self.humidity_needed = 2
self.img0 = wheat_img_0 self.img0 = wheat_img_0
self.img1 = wheat_img_1 self.img1 = wheat_img_1
self.img2 = wheat_img_2 self.img2 = wheat_img_2
self.img3 = wheat_img_3 self.img3 = wheat_img_3
elif self.species == "potato": elif self.species == "potato":
self.growth_speed = 1
self.humidity_needed = 1
self.img0 = potato_img_0 self.img0 = potato_img_0
self.img1 = potato_img_1 self.img1 = potato_img_1
self.img2 = potato_img_2 self.img2 = potato_img_2
self.img3 = potato_img_3 self.img3 = potato_img_3
elif self.species == "strawberry": elif self.species == "strawberry":
self.img0 = strawberry_img_0 self.growth_speed = 0.8
self.img1 = strawberry_img_1 self.humidity_needed = 1
self.img2 = strawberry_img_2
self.img3 = strawberry_img_3
elif self.species == "pepper":
self.img0 = strawberry_img_0 self.img0 = strawberry_img_0
self.img1 = strawberry_img_1 self.img1 = strawberry_img_1
self.img2 = strawberry_img_2 self.img2 = strawberry_img_2
@ -41,94 +38,9 @@ class Plant(pygame.sprite.Sprite):
field.planted = True field.planted = True
self.tickscount = 0 self.tickscount = 0
self.ticks = 0 self.ticks = 0
self.path = path + self.species + "\\"
self.testimage = self.path + random.choice(os.listdir(self.path))
def dtree(self): def dtree(self):
if self.field.hydration == 4: decision_tree(self)
if self.is_healthy == 1:
if self.field.tractor_there == 0:
if self.ticks == 0:
return 0
elif self.ticks == 1:
return 1
elif self.field.tractor_there == 1:
return 0
elif self.is_healthy == 0:
return 0
elif self.field.hydration == 2:
if self.species == "pepper":
if self.ticks == 1:
if self.is_healthy == 1:
return 1
elif self.is_healthy == 0:
return 0
elif self.ticks == 0:
return 0
elif self.species == "potato":
return 0
elif self.species == "tomato":
return 0
elif self.species == "strawberry":
return 0
elif self.field.hydration == 1:
if self.species == "potato":
return 0
elif self.species == "strawberry":
if self.ticks == 1:
return -1
elif self.ticks == 0:
return 0
elif self.species == "tomato":
return 0
elif self.species == "pepper":
if self.is_healthy == 0:
return 0
elif self.is_healthy == 1:
if self.field.tractor_there == 0:
if self.ticks == 0:
return 0
elif self.ticks == 1:
return 1
elif self.field.tractor_there == 1:
return 0
elif self.field.hydration == 3:
if self.ticks == 1:
if self.field.tractor_there == 0:
if self.is_healthy == 1:
if self.species == "potato":
if self.field.fertility == 1:
return 1
elif self.field.fertility == 0:
return 0
elif self.species == "strawberry":
return 1
elif self.species == "pepper":
return 1
elif self.species == "tomato":
return 1
elif self.is_healthy == 0:
return 0
elif self.field.tractor_there == 1:
return 0
elif self.ticks == 0:
return 0
elif self.field.hydration == 5:
if self.field.tractor_there == 1:
return 0
elif self.field.tractor_there == 0:
if self.is_healthy == 0:
return 0
elif self.is_healthy == 1:
if self.ticks == 1:
return 1
elif self.ticks == 0:
return 0
elif self.field.hydration == 0:
if self.ticks == 0:
return 0
elif self.ticks == 1:
return -1
def update(self): def update(self):
if self.growth == 0: if self.growth == 0:
@ -151,7 +63,6 @@ class Plant(pygame.sprite.Sprite):
self.growth = 4 self.growth = 4
if self.growth < 0: if self.growth < 0:
self.growth = 0 self.growth = 0
self.update() self.update()
def tick(self): def tick(self):
@ -159,6 +70,3 @@ class Plant(pygame.sprite.Sprite):
if self.tickscount >= 25: if self.tickscount >= 25:
self.tickscount = 0 self.tickscount = 0
self.ticks = 1 self.ticks = 1
def remove(self):
self.field.planted = False

View File

@ -7,14 +7,6 @@ BROWN2 = (140, 110, 55)
BROWN3 = (110, 85, 40) BROWN3 = (110, 85, 40)
BROWN4 = (80, 60, 20) BROWN4 = (80, 60, 20)
BROWN5 = (80, 60, 20) BROWN5 = (80, 60, 20)
REDDISH0 = (230, 150, 90)
REDDISH1 = (210, 130, 70)
REDDISH2 = (190, 110, 55)
REDDISH3 = (160, 85, 40)
REDDISH4 = (130, 60, 20)
REDDISH5 = (130, 60, 20)
DBROWN = (65, 50, 20) DBROWN = (65, 50, 20)
LBROWN = (108, 97, 62) LBROWN = (108, 97, 62)
BLUE = (18, 93, 156) BLUE = (18, 93, 156)

View File

@ -2,12 +2,12 @@
GSIZE = 10 GSIZE = 10
# This sets the WIDTH and HEIGHT of each grid location # This sets the WIDTH and HEIGHT of each grid location
WIDTH = 80 WIDTH = 35
HEIGHT = 80 HEIGHT = 35
# This sets the margin between each cell # This sets the margin between each cell
MARGIN = 5 MARGIN = 5
# Window size # Window size
SCREEN_WIDTH = GSIZE * (WIDTH + MARGIN) + MARGIN SCREEN_WIDTH = GSIZE * (WIDTH + MARGIN) + MARGIN
SCREEN_HEIGHT = GSIZE * (HEIGHT + MARGIN) + MARGIN + 100 SCREEN_HEIGHT = GSIZE * (HEIGHT + MARGIN) + MARGIN

View File

@ -1,6 +1,7 @@
from pygame.locals import (K_c)
from src.dimensions import * from src.dimensions import *
from src.sprites import * from src.sprites import *
from plant import *
class Tractor(pygame.sprite.Sprite): class Tractor(pygame.sprite.Sprite):
@ -72,13 +73,10 @@ class Tractor(pygame.sprite.Sprite):
field[self.position[0]][self.position[1]].hydrate() field[self.position[0]][self.position[1]].hydrate()
def cut(self, field, pressed_keys): def cut(self, field, pressed_keys):
if pressed_keys[K_c]:
field[self.position[0]][self.position[1]].free() field[self.position[0]][self.position[1]].free()
def plant(self, plant_map, plants): def plant(self, field, plant, pressed_keys):
print(plant_map[self.position[0]][self.position[1]]) if field.planted == 0:
plant = Plant(self.field[self.position[0]][self.position[1]], plant_map[self.position[0]][self.position[1]]) field.planted = plant
plants.append(plant) plant.field = field
def fertilize(self, field, plants, type):
if plants[self.position[0]][self.position[1]].species == type:
field[self.position[0]][self.position[1]].fertility = 1