Merge pull request 'development' (#11) from development into master
Reviewed-on: #11
This commit is contained in:
commit
342a74c1d8
100
data.txt
Normal file
100
data.txt
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
{"weight": 9, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 11, "eatable": true, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 5, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 11, "eatable": true, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 7, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 7, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 1, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 2, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 4, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 1, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 3, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 7, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 1, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 2, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 2, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 8, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 4, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 4, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 4, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 1, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 3, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 0, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 4, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 8, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 7, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 1, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 2, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 4, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 2, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 0, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 9, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 2, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 8, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 4, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 0, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 8, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 2, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 2, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 11, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 0, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 0, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 5, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 0, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 7, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 4, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 4, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 8, "eatable": false, "toughness": 3, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 3, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 1, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 1, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 1, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 3, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 6, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 7, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 9, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 9, "eatable": false, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 11, "eatable": true, "toughness": 0, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 3, "resource": "food"}
|
||||||
|
{"weight": 10, "eatable": false, "toughness": 1, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": true, "toughness": 2, "resource": "food"}
|
||||||
|
{"weight": 5, "eatable": true, "toughness": 0, "resource": "water"}
|
||||||
|
{"weight": 0, "eatable": false, "toughness": 2, "resource": "wood"}
|
||||||
|
{"weight": 10, "eatable": false, "toughness": 2, "resource": "wood"}
|
28
generate_test_data.py
Normal file
28
generate_test_data.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
|
||||||
|
def generate_data():
|
||||||
|
f = open("data.txt", "w")
|
||||||
|
for i in range(100):
|
||||||
|
weight = random.randint(0, 11)
|
||||||
|
eatable = bool(random.randint(0, 1))
|
||||||
|
toughness = random.randint(0, 3)
|
||||||
|
f.write('{')
|
||||||
|
f.write(
|
||||||
|
f'"weight": {weight}, "eatable": {str(eatable).lower()}, "toughness": {toughness}, "resource": "{get_resource_type(weight, eatable, toughness)}"')
|
||||||
|
f.write('}')
|
||||||
|
f.write('\n')
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
def get_resource_type(weight, eatable, toughness):
|
||||||
|
if weight > 10 or eatable is False:
|
||||||
|
return "wood"
|
||||||
|
|
||||||
|
if toughness < 1:
|
||||||
|
return "water"
|
||||||
|
|
||||||
|
return "food"
|
||||||
|
|
||||||
|
|
||||||
|
generate_data()
|
@ -1,3 +1,5 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
from settings import SCREEN_WIDTH, SCREEN_HEIGHT
|
from settings import SCREEN_WIDTH, SCREEN_HEIGHT
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
class InventoryComponent:
|
class InventoryComponent:
|
||||||
def __init__(self, maxitems=10):
|
def __init__(self, maxitems=100):
|
||||||
self.maxitems = maxitems
|
self.maxitems = maxitems
|
||||||
self.items = {}
|
self.items = {}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
class PathfindingComponent:
|
class PathfindingComponent:
|
||||||
def __init__(self, target_pos):
|
def __init__(self, target_pos, searching_for_resource=False):
|
||||||
self.target_grid_pos = (int(target_pos[0] / 32), int(target_pos[1] / 32))
|
self.target_grid_pos = (int(target_pos[0] / 32), int(target_pos[1] / 32))
|
||||||
|
self.searching_for_resource = False
|
||||||
self.current_target = None
|
self.current_target = None
|
||||||
self.path = None
|
self.path = None
|
||||||
|
@ -1,3 +1,29 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
from survival.generators.resource_type import ResourceType
|
||||||
|
|
||||||
|
|
||||||
class ResourceComponent:
|
class ResourceComponent:
|
||||||
def __init__(self, resource_type):
|
def __init__(self, resource_type):
|
||||||
self.resource_type = resource_type
|
self.resource_type = resource_type
|
||||||
|
w, e, t = self.generate_attributes(resource_type)
|
||||||
|
self.weight = w
|
||||||
|
self.eatable = e
|
||||||
|
self.toughness = t
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def generate_attributes(resource_type):
|
||||||
|
if resource_type == ResourceType.WOOD:
|
||||||
|
weight = random.randint(10, 15)
|
||||||
|
eatable = False
|
||||||
|
toughness = random.randint(10, 15)
|
||||||
|
elif resource_type == ResourceType.WATER:
|
||||||
|
weight = random.randint(1, 2)
|
||||||
|
eatable = True
|
||||||
|
toughness = 0
|
||||||
|
else:
|
||||||
|
weight = random.randint(1, 7)
|
||||||
|
eatable = True
|
||||||
|
toughness = random.randint(2, 5)
|
||||||
|
|
||||||
|
return weight, eatable, toughness
|
||||||
|
48
survival/decision_tree.py
Normal file
48
survival/decision_tree.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
from sklearn import tree
|
||||||
|
from sklearn.feature_extraction import DictVectorizer
|
||||||
|
|
||||||
|
from survival.components.resource_component import ResourceComponent
|
||||||
|
|
||||||
|
|
||||||
|
class DecisionTree:
|
||||||
|
def __init__(self):
|
||||||
|
self.clf = None
|
||||||
|
self.vec = None
|
||||||
|
|
||||||
|
def build(self, depth: int):
|
||||||
|
path = os.path.join("..", "data.txt")
|
||||||
|
|
||||||
|
samples = list()
|
||||||
|
results = list()
|
||||||
|
|
||||||
|
with open(path, "r") as training_file:
|
||||||
|
for sample in training_file:
|
||||||
|
sample, result = self.process_input(sample)
|
||||||
|
samples.append(sample)
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
|
self.vec = DictVectorizer()
|
||||||
|
self.clf = tree.DecisionTreeClassifier(max_depth=depth)
|
||||||
|
self.clf = self.clf.fit(self.vec.fit_transform(samples).toarray(), results)
|
||||||
|
# print(tree.export_text(self.clf, feature_names=self.vec.get_feature_names()))
|
||||||
|
|
||||||
|
def predict_answer(self, resource: ResourceComponent):
|
||||||
|
params = {
|
||||||
|
"weight": resource.weight,
|
||||||
|
"eatable": resource.eatable,
|
||||||
|
"toughness": resource.toughness
|
||||||
|
}
|
||||||
|
return self.clf.predict(self.vec.transform(params).toarray())
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def process_input(line):
|
||||||
|
data = json.loads(line.strip())
|
||||||
|
result = data['resource']
|
||||||
|
del data['resource']
|
||||||
|
sample = data
|
||||||
|
|
||||||
|
return sample, result
|
||||||
|
|
0
survival/generators/__init__.py
Normal file
0
survival/generators/__init__.py
Normal file
@ -6,6 +6,7 @@ from survival.components.movement_component import MovementComponent
|
|||||||
from survival.components.position_component import PositionComponent
|
from survival.components.position_component import PositionComponent
|
||||||
from survival.components.sprite_component import SpriteComponent
|
from survival.components.sprite_component import SpriteComponent
|
||||||
from survival.components.time_component import TimeComponent
|
from survival.components.time_component import TimeComponent
|
||||||
|
from survival.systems.automation_system import AutomationComponent
|
||||||
|
|
||||||
|
|
||||||
class PlayerGenerator:
|
class PlayerGenerator:
|
||||||
@ -20,6 +21,7 @@ class PlayerGenerator:
|
|||||||
world.add_component(player, InventoryComponent())
|
world.add_component(player, InventoryComponent())
|
||||||
camera_target = CameraTargetComponent(pos)
|
camera_target = CameraTargetComponent(pos)
|
||||||
world.add_component(player, camera_target)
|
world.add_component(player, camera_target)
|
||||||
|
world.add_component(player, AutomationComponent())
|
||||||
game_map.add_entity(player, pos)
|
game_map.add_entity(player, pos)
|
||||||
sprite = SpriteComponent('stevenson.png')
|
sprite = SpriteComponent('stevenson.png')
|
||||||
sprite.set_scale(1)
|
sprite.set_scale(1)
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
from enum import Enum
|
|
||||||
from survival import GameMap
|
from survival import GameMap
|
||||||
from survival.components.OnCollisionComponent import OnCollisionComponent
|
from survival.components.OnCollisionComponent import OnCollisionComponent
|
||||||
from survival.components.inventory_component import InventoryComponent
|
from survival.components.inventory_component import InventoryComponent
|
||||||
from survival.components.position_component import PositionComponent
|
from survival.components.position_component import PositionComponent
|
||||||
from survival.components.resource_component import ResourceComponent
|
from survival.components.resource_component import ResourceComponent
|
||||||
from survival.components.sprite_component import SpriteComponent
|
from survival.components.sprite_component import SpriteComponent
|
||||||
|
from survival.decision_tree import DecisionTree
|
||||||
from survival.esper import World
|
from survival.esper import World
|
||||||
|
from survival.generators.resource_type import ResourceType
|
||||||
from survival.settings import RESOURCES_AMOUNT
|
from survival.settings import RESOURCES_AMOUNT
|
||||||
|
|
||||||
|
|
||||||
class ResourceType(Enum):
|
|
||||||
FOOD = 1
|
|
||||||
WATER = 2
|
|
||||||
WOOD = 3
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceGenerator:
|
class ResourceGenerator:
|
||||||
def __init__(self, world, game_map):
|
def __init__(self, world, game_map):
|
||||||
self.world = world
|
self.world = world
|
||||||
self.map = game_map
|
self.map = game_map
|
||||||
|
self.decision_tree = DecisionTree()
|
||||||
|
self.built_tree = self.decision_tree.build(10)
|
||||||
|
|
||||||
def generate_resources(self, player: int):
|
def generate_resources(self, player: int):
|
||||||
for x in range(RESOURCES_AMOUNT):
|
for x in range(RESOURCES_AMOUNT):
|
||||||
@ -37,7 +34,7 @@ class ResourceGenerator:
|
|||||||
resource_type = random.choice(list(ResourceType))
|
resource_type = random.choice(list(ResourceType))
|
||||||
sprite = SpriteComponent(sprites[resource_type])
|
sprite = SpriteComponent(sprites[resource_type])
|
||||||
col = OnCollisionComponent()
|
col = OnCollisionComponent()
|
||||||
col.addCallback(self.remove_resource, world=self.world, game_map=self.map, entity=obj, player=player)
|
col.addCallback(self.remove_resource, world=self.world, game_map=self.map, resource_ent=obj, player=player, decision_tree=self.decision_tree)
|
||||||
self.world.add_component(obj, pos)
|
self.world.add_component(obj, pos)
|
||||||
self.world.add_component(obj, sprite)
|
self.world.add_component(obj, sprite)
|
||||||
self.world.add_component(obj, col)
|
self.world.add_component(obj, col)
|
||||||
@ -51,10 +48,12 @@ class ResourceGenerator:
|
|||||||
return free_pos
|
return free_pos
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remove_resource(world: World, game_map: GameMap, entity: int, player: int):
|
def remove_resource(world: World, game_map: GameMap, resource_ent: int, player: int, decision_tree: DecisionTree):
|
||||||
pos = world.component_for_entity(entity, PositionComponent)
|
pos = world.component_for_entity(resource_ent, PositionComponent)
|
||||||
resource = world.component_for_entity(entity, ResourceComponent)
|
resource = world.component_for_entity(resource_ent, ResourceComponent)
|
||||||
inventory = world.component_for_entity(player, InventoryComponent)
|
inventory = world.component_for_entity(player, InventoryComponent)
|
||||||
inventory.add_item(resource.resource_type, 1)
|
answer = decision_tree.predict_answer(resource)
|
||||||
|
# print(answer)
|
||||||
|
inventory.add_item(ResourceType.get_from_string(answer), 1)
|
||||||
game_map.remove_entity(pos.grid_position)
|
game_map.remove_entity(pos.grid_position)
|
||||||
world.delete_entity(entity, immediate=True)
|
world.delete_entity(resource_ent, immediate=True)
|
||||||
|
18
survival/generators/resource_type.py
Normal file
18
survival/generators/resource_type.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceType(Enum):
|
||||||
|
FOOD = 1
|
||||||
|
WATER = 2
|
||||||
|
WOOD = 3
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_from_string(string):
|
||||||
|
if string == 'food':
|
||||||
|
return ResourceType.FOOD
|
||||||
|
elif string == 'water':
|
||||||
|
return ResourceType.WATER
|
||||||
|
elif string == 'wood':
|
||||||
|
return ResourceType.WOOD
|
||||||
|
else:
|
||||||
|
raise Exception("Unknown resource type")
|
@ -76,3 +76,6 @@ class TileGenerator:
|
|||||||
found_biome = TileGenerator.Biomes[0]
|
found_biome = TileGenerator.Biomes[0]
|
||||||
|
|
||||||
return found_biome
|
return found_biome
|
||||||
|
|
||||||
|
|
||||||
|
# {"weight": 2, "size": 3, "eatable": true, "resource": "food"}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
from survival import esper
|
from survival import esper
|
||||||
|
from survival.systems.automation_system import AutomationSystem
|
||||||
from survival.systems.camera_system import CameraSystem
|
from survival.systems.camera_system import CameraSystem
|
||||||
|
from survival.systems.collection_system import ResourceCollectionSystem
|
||||||
from survival.systems.collision_system import CollisionSystem
|
from survival.systems.collision_system import CollisionSystem
|
||||||
from survival.systems.direction_system import DirectionSystem
|
from survival.systems.direction_system import DirectionSystem
|
||||||
from survival.systems.draw_system import DrawSystem
|
from survival.systems.draw_system import DrawSystem
|
||||||
@ -13,13 +15,15 @@ class WorldGenerator:
|
|||||||
|
|
||||||
def create_world(self, camera, game_map):
|
def create_world(self, camera, game_map):
|
||||||
world = esper.World()
|
world = esper.World()
|
||||||
world.add_processor(InputSystem(camera))
|
world.add_processor(InputSystem(camera, game_map))
|
||||||
world.add_processor(CameraSystem(camera))
|
world.add_processor(CameraSystem(camera))
|
||||||
world.add_processor(MovementSystem(game_map), priority=1)
|
world.add_processor(MovementSystem(game_map), priority=2)
|
||||||
world.add_processor(CollisionSystem(game_map), priority=2)
|
world.add_processor(CollisionSystem(game_map), priority=3)
|
||||||
world.add_processor(DrawSystem(camera))
|
world.add_processor(DrawSystem(camera))
|
||||||
|
world.add_processor(ResourceCollectionSystem(), priority=1)
|
||||||
world.add_processor(TimeSystem())
|
world.add_processor(TimeSystem())
|
||||||
world.add_processor(PathfindingMovementSystem(game_map), priority=3)
|
world.add_processor(AutomationSystem(game_map))
|
||||||
|
world.add_processor(PathfindingMovementSystem(game_map), priority=4)
|
||||||
world.add_processor(DirectionSystem())
|
world.add_processor(DirectionSystem())
|
||||||
|
|
||||||
return world
|
return world
|
||||||
|
@ -4,7 +4,9 @@ from typing import Tuple, List
|
|||||||
|
|
||||||
from survival import GameMap
|
from survival import GameMap
|
||||||
from survival.components.position_component import PositionComponent
|
from survival.components.position_component import PositionComponent
|
||||||
|
from survival.components.resource_component import ResourceComponent
|
||||||
from survival.enums import Direction
|
from survival.enums import Direction
|
||||||
|
from survival.esper import World
|
||||||
|
|
||||||
|
|
||||||
class Action(Enum):
|
class Action(Enum):
|
||||||
@ -38,7 +40,7 @@ def get_moved_position(position: Tuple[int, int], direction: Direction):
|
|||||||
return position[0] + vector[0], position[1] + vector[1]
|
return position[0] + vector[0], position[1] + vector[1]
|
||||||
|
|
||||||
|
|
||||||
def get_states(state: State, game_map: GameMap) -> List[Tuple[Action, State, int]]:
|
def get_states(state: State, game_map: GameMap, world: World) -> List[Tuple[Action, State, int]]:
|
||||||
states = list()
|
states = list()
|
||||||
|
|
||||||
states.append((Action.ROTATE_LEFT, State(state.position, state.direction.rotate_left(state.direction)), 1))
|
states.append((Action.ROTATE_LEFT, State(state.position, state.direction.rotate_left(state.direction)), 1))
|
||||||
@ -47,6 +49,10 @@ def get_states(state: State, game_map: GameMap) -> List[Tuple[Action, State, int
|
|||||||
target_position = get_moved_position(state.position, state.direction)
|
target_position = get_moved_position(state.position, state.direction)
|
||||||
if not game_map.is_colliding(target_position):
|
if not game_map.is_colliding(target_position):
|
||||||
states.append((Action.MOVE, State(target_position, state.direction), game_map.get_cost(target_position)))
|
states.append((Action.MOVE, State(target_position, state.direction), game_map.get_cost(target_position)))
|
||||||
|
elif game_map.get_entity(target_position) is not None:
|
||||||
|
ent = game_map.get_entity(target_position)
|
||||||
|
if world.has_component(ent, ResourceComponent):
|
||||||
|
states.append((Action.MOVE, State(target_position, state.direction), 3))
|
||||||
|
|
||||||
return states
|
return states
|
||||||
|
|
||||||
@ -68,7 +74,7 @@ def heuristic(new_node: Node, goal: Tuple[int, int]):
|
|||||||
return abs(new_node.state.position[0] - goal[0]) + abs(new_node.state.position[1] - goal[1])
|
return abs(new_node.state.position[0] - goal[0]) + abs(new_node.state.position[1] - goal[1])
|
||||||
|
|
||||||
|
|
||||||
def graph_search(game_map: GameMap, start: PositionComponent, goal: tuple):
|
def graph_search(game_map: GameMap, start: PositionComponent, goal: tuple, world: World):
|
||||||
fringe = PriorityQueue()
|
fringe = PriorityQueue()
|
||||||
explored = list()
|
explored = list()
|
||||||
|
|
||||||
@ -97,7 +103,7 @@ def graph_search(game_map: GameMap, start: PositionComponent, goal: tuple):
|
|||||||
explored_states.add((tuple(node.state.position), node.state.direction))
|
explored_states.add((tuple(node.state.position), node.state.direction))
|
||||||
|
|
||||||
# Get all possible states
|
# Get all possible states
|
||||||
for state in get_states(node.state, game_map):
|
for state in get_states(node.state, game_map, world):
|
||||||
sub_state = (tuple(state[1].position), state[1].direction)
|
sub_state = (tuple(state[1].position), state[1].direction)
|
||||||
new_node = Node(state=state[1],
|
new_node = Node(state=state[1],
|
||||||
parent=node,
|
parent=node,
|
||||||
|
62
survival/systems/automation_system.py
Normal file
62
survival/systems/automation_system.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
from survival import esper, GameMap
|
||||||
|
from survival.components.moving_component import MovingComponent
|
||||||
|
from survival.components.pathfinding_component import PathfindingComponent
|
||||||
|
from survival.components.position_component import PositionComponent
|
||||||
|
from survival.components.resource_component import ResourceComponent
|
||||||
|
|
||||||
|
|
||||||
|
class AutomationComponent:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AutomationSystem(esper.Processor):
|
||||||
|
def __init__(self, game_map: GameMap):
|
||||||
|
self.game_map = game_map
|
||||||
|
|
||||||
|
def process(self, dt):
|
||||||
|
for ent, (automation, pos) in self.world.get_components(AutomationComponent, PositionComponent):
|
||||||
|
if self.world.has_component(ent, PathfindingComponent):
|
||||||
|
continue
|
||||||
|
|
||||||
|
resource = self.detect_closest_resource(pos, ent)
|
||||||
|
if resource is None:
|
||||||
|
# TODO: Check if target position is not out of map bounds
|
||||||
|
self.world.add_component(ent, PathfindingComponent((pos.grid_position[0] * 32 + 64, pos.grid_position[1] * 32 + 64)))
|
||||||
|
# Move somewhere else
|
||||||
|
else:
|
||||||
|
target = self.world.component_for_entity(resource, PositionComponent).grid_position
|
||||||
|
self.world.add_component(ent, PathfindingComponent((target[0] * 32, target[1] * 32), True))
|
||||||
|
# Go collect target resource
|
||||||
|
|
||||||
|
def detect_closest_resource(self, position: PositionComponent, target_entity: int):
|
||||||
|
entity_position = position.grid_position
|
||||||
|
x_range = [entity_position[0] - 5, entity_position[0] + 5]
|
||||||
|
y_range = [entity_position[1] - 5, entity_position[1] + 5]
|
||||||
|
|
||||||
|
# Check if range is not out of map bounds
|
||||||
|
if x_range[0] < 0:
|
||||||
|
x_range[0] = 0
|
||||||
|
if x_range[1] >= self.game_map.width:
|
||||||
|
x_range[1] = self.game_map.width - 1
|
||||||
|
if y_range[0] < 0:
|
||||||
|
y_range[0] = 0
|
||||||
|
if y_range[1] >= self.game_map.height:
|
||||||
|
y_range[1] = self.game_map.height - 1
|
||||||
|
|
||||||
|
found_resource = [-1, 200000]
|
||||||
|
|
||||||
|
for y in range(y_range[0], y_range[1]):
|
||||||
|
for x in range(x_range[0], x_range[1]):
|
||||||
|
ent = self.game_map.get_entity([x, y])
|
||||||
|
if ent == target_entity:
|
||||||
|
continue
|
||||||
|
if ent is not None and self.world.has_component(ent, ResourceComponent):
|
||||||
|
res_position = self.world.component_for_entity(ent, PositionComponent).grid_position
|
||||||
|
distance = abs(entity_position[0] - res_position[0]) + abs(entity_position[1] - res_position[1])
|
||||||
|
if found_resource[1] > distance:
|
||||||
|
found_resource = [ent, distance]
|
||||||
|
|
||||||
|
if found_resource[0] == -1:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return found_resource[0]
|
20
survival/systems/collection_system.py
Normal file
20
survival/systems/collection_system.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from survival import esper
|
||||||
|
from survival.components.direction_component import DirectionChangeComponent
|
||||||
|
from survival.components.moving_component import MovingComponent
|
||||||
|
from survival.components.position_component import PositionComponent
|
||||||
|
from survival.graph_search import Action
|
||||||
|
from survival.systems.pathfinding_movement_system import CollectingResourceComponent
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceCollectionSystem(esper.Processor):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def process(self, dt):
|
||||||
|
for ent, (collect, pos) in self.world.get_components(CollectingResourceComponent, PositionComponent):
|
||||||
|
if self.world.has_component(ent, MovingComponent) or self.world.has_component(ent, DirectionChangeComponent):
|
||||||
|
continue
|
||||||
|
|
||||||
|
if collect.action == Action.MOVE:
|
||||||
|
self.world.remove_component(ent, CollectingResourceComponent)
|
||||||
|
self.world.add_component(ent, MovingComponent())
|
@ -1,16 +1,18 @@
|
|||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
from survival import esper
|
from survival import esper, GameMap
|
||||||
from survival.components.direction_component import DirectionChangeComponent
|
from survival.components.direction_component import DirectionChangeComponent
|
||||||
from survival.components.input_component import InputComponent
|
from survival.components.input_component import InputComponent
|
||||||
from survival.components.moving_component import MovingComponent
|
from survival.components.moving_component import MovingComponent
|
||||||
from survival.components.pathfinding_component import PathfindingComponent
|
from survival.components.pathfinding_component import PathfindingComponent
|
||||||
from survival.components.position_component import PositionComponent
|
from survival.components.position_component import PositionComponent
|
||||||
|
from survival.components.resource_component import ResourceComponent
|
||||||
|
|
||||||
|
|
||||||
class InputSystem(esper.Processor):
|
class InputSystem(esper.Processor):
|
||||||
def __init__(self, camera):
|
def __init__(self, camera, game_map: GameMap):
|
||||||
self.camera = camera
|
self.camera = camera
|
||||||
|
self.game_map = game_map
|
||||||
|
|
||||||
def process(self, dt):
|
def process(self, dt):
|
||||||
for ent, (inp, pos) in self.world.get_components(InputComponent, PositionComponent):
|
for ent, (inp, pos) in self.world.get_components(InputComponent, PositionComponent):
|
||||||
@ -20,7 +22,11 @@ class InputSystem(esper.Processor):
|
|||||||
pos = pygame.mouse.get_pos()
|
pos = pygame.mouse.get_pos()
|
||||||
pos = (pos[0] - self.camera.camera.left, pos[1] - self.camera.camera.top)
|
pos = (pos[0] - self.camera.camera.left, pos[1] - self.camera.camera.top)
|
||||||
if not self.world.has_component(ent, PathfindingComponent):
|
if not self.world.has_component(ent, PathfindingComponent):
|
||||||
self.world.add_component(ent, PathfindingComponent(pos))
|
target_ent = self.game_map.get_entity([int(pos[0] / 32), int(pos[1]/ 32)])
|
||||||
|
if target_ent is not None and self.world.has_component(target_ent, ResourceComponent):
|
||||||
|
self.world.add_component(ent, PathfindingComponent(pos, True))
|
||||||
|
else:
|
||||||
|
self.world.add_component(ent, PathfindingComponent(pos))
|
||||||
|
|
||||||
if self.world.has_component(ent, MovingComponent):
|
if self.world.has_component(ent, MovingComponent):
|
||||||
continue
|
continue
|
||||||
|
@ -14,8 +14,8 @@ class MovementSystem(esper.Processor):
|
|||||||
MovingComponent,
|
MovingComponent,
|
||||||
SpriteComponent):
|
SpriteComponent):
|
||||||
cost = self.map.get_cost(moving.target)
|
cost = self.map.get_cost(moving.target)
|
||||||
pos.position[0] += moving.direction_vector[0] * mov.speed * dt / 100 / cost
|
pos.position[0] += moving.direction_vector[0] * mov.speed * dt / 100 / cost
|
||||||
pos.position[1] += moving.direction_vector[1] * mov.speed * dt / 100 / cost
|
pos.position[1] += moving.direction_vector[1] * mov.speed * dt / 100 / cost
|
||||||
|
|
||||||
if abs(moving.target[0] * 32 - pos.position[0]) < 0.1 * mov.speed and abs(
|
if abs(moving.target[0] * 32 - pos.position[0]) < 0.1 * mov.speed and abs(
|
||||||
pos.position[1] - moving.target[1] * 32) < 0.1 * mov.speed:
|
pos.position[1] - moving.target[1] * 32) < 0.1 * mov.speed:
|
||||||
|
@ -8,21 +8,30 @@ from survival.graph_search import graph_search, Action
|
|||||||
from survival.systems.input_system import PathfindingComponent
|
from survival.systems.input_system import PathfindingComponent
|
||||||
|
|
||||||
|
|
||||||
|
class CollectingResourceComponent:
|
||||||
|
def __init__(self, action):
|
||||||
|
self.action = action
|
||||||
|
|
||||||
|
|
||||||
class PathfindingMovementSystem(esper.Processor):
|
class PathfindingMovementSystem(esper.Processor):
|
||||||
def __init__(self, game_map):
|
def __init__(self, game_map):
|
||||||
self.game_map = game_map
|
self.game_map = game_map
|
||||||
pass
|
|
||||||
|
|
||||||
def process(self, dt):
|
def process(self, dt):
|
||||||
for ent, (pos, pathfinding, movement) in self.world.get_components(PositionComponent, PathfindingComponent,
|
for ent, (pos, pathfinding, movement) in self.world.get_components(PositionComponent, PathfindingComponent,
|
||||||
MovementComponent):
|
MovementComponent):
|
||||||
if pathfinding.path is None:
|
if pathfinding.path is None:
|
||||||
pathfinding.path = graph_search(self.game_map, pos, pathfinding.target_grid_pos)
|
pathfinding.path = graph_search(self.game_map, pos, pathfinding.target_grid_pos, self.world)
|
||||||
|
|
||||||
if len(pathfinding.path) < 1:
|
if len(pathfinding.path) < 1:
|
||||||
self.world.remove_component(ent, PathfindingComponent)
|
self.world.remove_component(ent, PathfindingComponent)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if pathfinding.searching_for_resource and len(pathfinding.path) == 1:
|
||||||
|
self.world.add_component(ent, CollectingResourceComponent(pathfinding.path.pop(0)))
|
||||||
|
self.world.remove_component(ent, PathfindingComponent)
|
||||||
|
continue
|
||||||
|
|
||||||
if self.world.has_component(ent, MovingComponent) or self.world.has_component(ent, DirectionChangeComponent):
|
if self.world.has_component(ent, MovingComponent) or self.world.has_component(ent, DirectionChangeComponent):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -9,4 +9,3 @@ class TimeSystem(esper.Processor):
|
|||||||
if time.timer > 1000:
|
if time.timer > 1000:
|
||||||
time.add_time(1)
|
time.add_time(1)
|
||||||
time.timer = 0
|
time.timer = 0
|
||||||
print(time)
|
|
||||||
|
@ -2,7 +2,7 @@ import pygame.font
|
|||||||
|
|
||||||
from survival import settings
|
from survival import settings
|
||||||
from survival.components.inventory_component import InventoryComponent
|
from survival.components.inventory_component import InventoryComponent
|
||||||
from survival.generators.resource_generator import ResourceType
|
from survival.generators.resource_type import ResourceType
|
||||||
from survival.image import Image
|
from survival.image import Image
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user