├── .gitignore
├── .project
├── .pydevproject
├── Angler.py
├── Arborist.py
├── BaseFunctions.py
├── Builder.py
├── Buildings.py
├── Clips.py
├── DebugTools.py
├── Entities.py
├── Explorer.py
├── Farmer.py
├── FishingShip.py
├── GameEntity.py
├── Images
├── AnimationsGIMPFiles
│ └── CropGrowth.xcf
├── Buildings
│ ├── Building1Test.png
│ ├── Dock.png
│ ├── Dock_Icon.png
│ ├── House.png
│ ├── House_Icon.png
│ ├── Inn.png
│ ├── LumberYard.png
│ ├── LumberYard_Icon.png
│ ├── Manor.png
│ ├── Manor_Icon.png
│ ├── TotalImage.png
│ ├── TownHall_Icon.png
│ ├── UC.png
│ ├── UC_Dock.png
│ └── UC_House.png
├── Dial
│ ├── dial.png
│ └── dial_outline2.png
├── Entities
│ ├── Angler.png
│ ├── Arborist.png
│ ├── BasicDemon.png
│ ├── BigTree.png
│ ├── Builder.png
│ ├── BuilderLarge.png
│ ├── Explorer.png
│ ├── Farmer.png
│ ├── FarmerLarge.png
│ ├── Farmer_dig1.png
│ ├── Farmer_dig2.png
│ ├── Farmer_dig3.png
│ ├── Farmer_dig4.png
│ ├── Farmer_dig5.png
│ ├── Farmer_dig6.png
│ ├── Lumberjack.png
│ ├── Lumberjack_chop1.png
│ ├── Lumberjack_chop2.png
│ ├── Lumberjack_chop3.png
│ ├── Tree2.png
│ ├── UsainBolt.png
│ ├── Villager.png
│ ├── VillagerLarge.png
│ ├── VillagerTest.png
│ ├── fishingship.png
│ ├── info_bar.png
│ └── map.png
├── New folder
│ ├── Clips.png
│ └── LumberjackOptimization.png
├── Screenshots
│ ├── README.md
│ └── Screenshot.png
└── Tiles
│ ├── AndrewCobble.png
│ ├── AndrewCobble2.png
│ ├── AndrewDeepWater.png
│ ├── AndrewGrass.png
│ ├── AndrewSmoothStone.png
│ ├── AndrewSmoothStone2.png
│ ├── AndrewWater.png
│ ├── AndrewWater2.png
│ ├── CarterTree.jpg
│ ├── CarterTree2.jpg
│ ├── Cobble.png
│ ├── GrassWithCenterTree.png
│ ├── GrassWithTwoTrees.png
│ ├── MinecraftDarkGrass.png
│ ├── MinecraftGrass.png
│ ├── MinecraftSnow.png
│ ├── MyGrass.png
│ ├── Sand.png
│ ├── Soil1.png
│ ├── Soil2.png
│ ├── Water.png
│ ├── baby_tree.png
│ └── cobble_left.png
├── LICENSE
├── Lumberjack.py
├── README.md
├── Tile.py
├── TileFuncs.py
├── UpdatingVillagerSim.py
├── VillagerSim.py
├── World.py
├── WorldGOAP.py
├── aitools
├── GoalMachine.py
├── StateMachine.py
└── __init__.py
├── gametools
├── ImageFuncs.py
├── MidpointDisplacement.py
├── PertTools.py
├── VoronoiMapGen.py
├── __init__.py
├── ani.py
├── util.py
└── vector2.py
├── gametools3
├── MidpointDisplacement3.py
└── __init__.py
└── misctools
├── NewIcon.py
└── __init__.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Screenshots
2 | Images/Screenshots/FULL_MAP_RENDER*
3 | Images/Screenshots/Minimap*
4 | Images/Screenshots/SCREENSHOT*
5 |
6 | # Created by .ignore support plugin (hsz.mobi)
7 | ### Python template
8 | # Byte-compiled / optimized / DLL files
9 | __pycache__/
10 | *.py[cod]
11 | *$py.class
12 |
13 | # C extensions
14 | *.so
15 |
16 | # Distribution / packaging
17 | .Python
18 | env/
19 | build/
20 | develop-eggs/
21 | dist/
22 | downloads/
23 | eggs/
24 | .eggs/
25 | lib/
26 | lib64/
27 | parts/
28 | sdist/
29 | var/
30 | *.egg-info/
31 | .installed.cfg
32 | *.egg
33 |
34 | # PyInstaller
35 | # Usually these files are written by a python script from a template
36 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
37 | *.manifest
38 | *.spec
39 |
40 | # Installer logs
41 | pip-log.txt
42 | pip-delete-this-directory.txt
43 |
44 | # Unit test / coverage reports
45 | htmlcov/
46 | .tox/
47 | .coverage
48 | .coverage.*
49 | .cache
50 | nosetests.xml
51 | coverage.xml
52 | *,cover
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 |
61 | # Sphinx documentation
62 | docs/_build/
63 |
64 | # PyBuilder
65 | target/
66 |
67 |
68 | ### Example user template template
69 | ### Example user template
70 |
71 | # IntelliJ project files
72 | .idea
73 | *.iml
74 | out
75 | gen
76 |
77 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | VillagerSim
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 |
15 | org.python.pydev.pythonNature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 | Default
4 | python 2.7
5 |
6 |
--------------------------------------------------------------------------------
/Angler.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | from Entities import *
3 | from GameEntity import *
4 | from gametools.vector2 import Vector2
5 | from gametools.ImageFuncs import *
6 | from gametools.ani import *
7 | import BaseFunctions
8 | import math
9 | import pygame
10 | import random
11 | import TileFuncs
12 | from World import *
13 | #TODO: Clean up imports and add docstrings
14 |
15 | class Angler(GameEntity):
16 |
17 | def __init__(self, world, image_string):
18 | # Initializing the class
19 | GameEntity.__init__(self, world, "Angler", "Entities/"+image_string)
20 |
21 | # Creating the states
22 | fishing_state = Fishing(self)
23 | exploring_state = Searching(self)
24 | delivering_state = Delivering(self)
25 |
26 | # Adding states to the brain
27 | self.brain.add_state(fishing_state)
28 | self.brain.add_state(exploring_state)
29 | self.brain.add_state(delivering_state)
30 |
31 | self.max_speed = 80.0 * (1.0 / 60.0)
32 | self.speed = self.max_speed
33 | self.base_speed = self.speed
34 | self.view_range = 2
35 | self.fish = 0
36 |
37 | self.worldSize = world.world_size
38 | self.TileSize = self.world.tile_size
39 |
40 | # animation variables
41 | self.animation = Ani(9, 10)
42 | self.pic = pygame.image.load("Images/Entities/map.png")
43 | self.img_func = ImageFuncs(18, 17,self.pic)
44 | self.sprites = self.img_func.get_images(9,0,2)
45 | self.hit = 0
46 | self.update()
47 |
48 | def update(self):
49 | self.image = self.sprites[self.animation.get_frame()]
50 | self.image.set_colorkey((255,0,255))
51 | if self.animation.finished:
52 | self.hit += 1
53 | self.animation.finished = False
54 |
55 |
56 | class Fishing(State):
57 |
58 | def __init__(self, angler):
59 |
60 | State.__init__(self, "Fishing")
61 | self.angler = angler
62 |
63 | def check_conditions(self):
64 |
65 | if self.angler.location.get_distance_to(self.angler.destination) <= self.angler.max_speed:
66 | self.angler.destination = Vector2(self.angler.location)
67 | self.angler.update()
68 |
69 | if self.angler.fish == 1:
70 | return "Delivering"
71 |
72 | def do_actions(self):
73 | if self.angler.location == self.angler.destination and self.angler.hit >= 4:
74 | # TODO: Why is this checking if the tile is fishable if it has been fishing there?
75 |
76 | for tile_location in TileFuncs.get_vnn_array(self.angler.world, self.angler.location, 2):
77 | if TileFuncs.get_tile(self.angler.world, tile_location).fishable:
78 | self.angler.hit = 0
79 | self.angler.fish = 1
80 |
81 | def entry_actions(self):
82 | BaseFunctions.random_dest(self.angler)
83 |
84 |
85 | class Searching(State):
86 |
87 | def __init__(self, angler):
88 | State.__init__(self, "Searching")
89 | self.angler = angler
90 |
91 | def entry_actions(self):
92 | BaseFunctions.random_dest(self.angler)
93 |
94 | def do_actions(self):
95 | pass
96 |
97 | def check_conditions(self):
98 | if self.angler.location.get_distance_to(self.angler.destination) < self.angler.max_speed:
99 | location_array = TileFuncs.get_vnn_array(self.angler.world,(self.angler.location), self.angler.view_range)
100 |
101 | for location in location_array:
102 | # TODO: This will make the angler go into the water, change this to go to the nearest walkable tile.
103 | test_tile = TileFuncs.get_tile(self.angler.world, location)
104 | if test_tile.__class__.__name__ == "WaterTile":
105 |
106 | self.angler.destination = location.copy()
107 | return "Fishing"
108 |
109 | BaseFunctions.random_dest(self.angler)
110 |
111 | def exit_actions(self):
112 | pass
113 |
114 | class Delivering(State):
115 |
116 | def __init__(self, angler):
117 | State.__init__(self, "Delivering")
118 | self.angler = angler
119 |
120 | def entry_actions(self):
121 | #TODO: Make dropoff point dynamic (e.g. it's own building)
122 |
123 | self.angler.destination = Vector2(self.angler.world.w/2, self.angler.world.h/2)
124 |
125 | def do_actions(self):
126 | pass
127 |
128 | def check_conditions(self):
129 |
130 | if self.angler.location.get_distance_to(self.angler.destination) < 15:
131 | self.angler.world.fish += self.angler.fish
132 | self.angler.fish = 0
133 | return "Searching"
134 |
135 | def exit_actions(self):
136 | pass
137 |
--------------------------------------------------------------------------------
/Arborist.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | from Entities import *
3 | from GameEntity import *
4 | from gametools.vector2 import Vector2
5 | from gametools.ImageFuncs import *
6 | from gametools.ani import *
7 | import math
8 | import pygame
9 | import random
10 | import TileFuncs
11 | import BaseFunctions
12 |
13 | class Arborist(GameEntity):
14 |
15 | def __init__(self, world, image_string):
16 | # Initializing the class
17 | GameEntity.__init__(self, world, "Arborist", "Entities/"+image_string)
18 |
19 | # Creating the states
20 | planting_state = Arborist_Planting(self)
21 |
22 | # Adding states to the brain
23 | self.brain.add_state(planting_state)
24 |
25 | self.max_speed = 80.0 * (1.0 / 60.0)
26 | self.speed = self.max_speed
27 | self.base_speed = self.speed
28 |
29 | self.worldSize = world.world_size
30 | self.TileSize = self.world.tile_size
31 |
32 | # animation variables
33 | self.animation = Ani(6,10)
34 | self.pic = pygame.image.load("Images/Entities/map.png")
35 | self.img_func = ImageFuncs(18, 17,self.pic)
36 | self.sprites = self.img_func.get_images(6,0,0)
37 | self.hit = 0
38 | self.update()
39 |
40 | def update(self):
41 | # Updates image every 10 cycles and adds 1 to the 4 hit dig
42 | self.image = self.sprites[self.animation.get_frame()]
43 | self.image.set_colorkey((255,0,255))
44 | if self.animation.finished == True:
45 | self.hit += 1
46 | self.animation.finished = False
47 |
48 |
49 | class Arborist_Planting(State):
50 |
51 | def __init__(self, Arborist):
52 |
53 | State.__init__(self, "Planting")
54 | self.arborist = Arborist
55 |
56 | def check_conditions(self):
57 |
58 | if self.arborist.location.get_distance_to(self.arborist.destination) < 15:
59 | self.arborist.destination = Vector2(self.arborist.location)
60 | self.arborist.update()
61 |
62 | def do_actions(self):
63 |
64 | if self.arborist.location == self.arborist.destination and self.arborist.hit >= 4 and TileFuncs.get_tile(
65 | self.arborist.world,self.arborist.location).plantable == 1:
66 | self.plant_seed()
67 |
68 | if self.arborist.location == self.arborist.destination and self.arborist.hit != 4 and TileFuncs.get_tile(
69 | self.arborist.world, self.arborist.location).plantable != 1:
70 | BaseFunctions.random_dest(self.arborist)
71 |
72 | def plant_seed(self):
73 | # Function for planting trees
74 |
75 | # Test to see if the tile the arborist is on is a tile that a tree can be planted on
76 | if TileFuncs.get_tile(self.arborist.world,self.arborist.location).plantable == 1:
77 | self.arborist.hit = 0
78 | self.arborist.update()
79 | old_tile = TileFuncs.get_tile(self.arborist.world,Vector2(self.arborist.location))
80 |
81 | darkness = pygame.Surface((32, 32))
82 | darkness.set_alpha(old_tile.darkness)
83 |
84 | new_tile = Tile.Baby_Tree(self.arborist.world, "GrassWithCenterTree")
85 |
86 | new_tile.darkness = old_tile.darkness
87 |
88 | new_tile.location = TileFuncs.get_tile_pos(self.arborist.world,self.arborist.destination)*32
89 | new_tile.rect.topleft = new_tile.location
90 | new_tile.color = old_tile.color
91 |
92 | self.arborist.world.tile_array[int(new_tile.location.y/32)][int(new_tile.location.x/32)] = new_tile
93 | self.arborist.world.world_surface.blit(new_tile.img, new_tile.location)
94 | self.arborist.world.world_surface.blit(darkness, new_tile.location)
95 |
96 | # Goes to a random destination no matter what
97 | self.arborist.hit = 0
98 | BaseFunctions.random_dest(self.arborist)
99 |
100 | def entry_actions(self):
101 | BaseFunctions.random_dest(self.arborist)
102 |
--------------------------------------------------------------------------------
/BaseFunctions.py:
--------------------------------------------------------------------------------
1 | import random
2 | import math
3 | from gametools.vector2 import Vector2
4 | import TileFuncs
5 |
6 | DEBUG = False
7 |
8 | def random_dest(entity, recurse=False, r_num=0, r_max=6):
9 | # Function for going to a random destination
10 | if recurse:
11 | entity.orientation += 30
12 | else:
13 | entity.orientation += random.randint(-30, 30)
14 | angle = math.radians(entity.orientation)
15 | distance = random.randint(50, 100)
16 | possible_dest = Vector2(entity.location.x + math.cos(angle) * distance, entity.location.y + math.sin(angle) * distance)
17 |
18 | # If the destination will go off the map, it is NOT a valid move under any circumstances.
19 | bad_spot = False
20 | if (0 > possible_dest.x > entity.world.world_size[0] or \
21 | 0 > possible_dest.y > entity.world.world_size[1]):
22 | bad_spot = True
23 | if DEBUG:
24 | "BAD SPOT IS TRUE"
25 |
26 | walk = TileFuncs.get_tile(entity.world, possible_dest).walkable == entity.land_based
27 | depth_max = r_num >= r_max
28 |
29 | if ((not walk and not depth_max) or bad_spot):
30 | random_dest(entity, True, r_num+1, r_max)
31 | return
32 |
33 | else:
34 | entity.destination = possible_dest
35 |
36 | if DEBUG:
37 | print("Current Tile: " + TileFuncs.get_tile(entity.world, entity.location).__class__.__name__)
38 | print("Destination Tile: " + TileFuncs.get_tile(entity.world, entity.destination).__class__.__name__)
39 | print("r_num: %d" % r_num)
40 | print("walk: ", walk)
41 | print("")
42 | if bad_spot: print("BAD SPOT, WTF")
43 |
--------------------------------------------------------------------------------
/Builder.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | from World import *
3 | from GameEntity import *
4 | from gametools.vector2 import Vector2
5 |
6 | from Buildings import *
7 |
8 | from random import *
9 |
10 | import pygame
11 |
12 |
13 | class Builder(GameEntity):
14 | def __init__(self, world, image, rest):
15 | GameEntity.__init__(self, world, "Builder", image)
16 |
17 | self.current_build = None
18 |
19 | self.speed = 100.0
20 |
21 | self.building_state = Builder_Building(self)
22 | self.Idle_state = Builder_Idle(self)
23 | self.Finding_state = Builder_Finding(self)
24 |
25 | self.brain.add_state(self.building_state)
26 | self.brain.add_state(self.Idle_state)
27 | self.brain.add_state(self.Finding_state)
28 |
29 | self.IdleLocation = rest.location.copy()
30 |
31 |
32 | class Builder_Building(State):
33 | def __init__(self, Builder):
34 | State.__init__(self, "Building")
35 | self.Builder = Builder
36 |
37 | def check_conditions(self):
38 | if self.building_complete >= 5.0:
39 | self.Builder.target.create()
40 |
41 | self.Builder.world.BuildingQueue.remove(self.Builder.target)
42 | return "Finding"
43 |
44 | def do_actions(self):
45 | self.building_complete += self.Builder.tp
46 |
47 | def entry_actions(self):
48 | self.Builder.destination = self.Builder.location.copy()
49 | self.building_complete = 0.0
50 |
51 |
52 | class Builder_Finding(State): # Finding a suitable place to build.
53 | """If:
54 | Lumber Yard - In the woods not near anything else
55 | Docks - Edge of the water, decently distanced from others
56 | House - Somewhere in the town area
57 | Manor - near top of the map or maybe replaces a house.
58 | """
59 |
60 | def __init__(self, Builder):
61 | State.__init__(self, "Finding")
62 | self.Builder = Builder
63 |
64 | def check_conditions(self):
65 | if len(self.Builder.world.BuildingQueue) == 0:
66 | return "Idle"
67 |
68 | if self.Builder.location.get_distance_to(self.Builder.destination) < 2:
69 | return "Building"
70 |
71 | def do_actions(self):
72 | pass
73 |
74 | def entry_actions(self):
75 | try:
76 | self.Builder.destination = self.Builder.world.BuildingQueue[0].location.copy()
77 | self.Builder.target = self.Builder.world.BuildingQueue[0]
78 |
79 | except IndexError:
80 | pass
81 |
82 |
83 | class Builder_Idle(State):
84 | def __init__(self, Builder):
85 | State.__init__(self, "Idle")
86 | self.Builder = Builder
87 |
88 | def entry_actions(self):
89 | self.Builder.destination = self.Builder.IdleLocation
90 |
91 | def check_conditions(self):
92 | if len(self.Builder.world.BuildingQueue) >= 1:
93 | return "Finding"
94 |
--------------------------------------------------------------------------------
/Buildings.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | import GameEntity
3 | from gametools.vector2 import Vector2
4 | import glob
5 |
6 | import ImageFuncs
7 | import pygame
8 |
9 |
10 | class Building(GameEntity.GameEntity):
11 | def __init(self, world, name, image_string="Inn"):
12 | GameEntity.__init__(self, world, name, "Buildings/"+image_string)
13 |
14 | self.image_funcs = ImageFuncs(32, 32, pygame.image.load("Images/Buildings/TotalImage.png"))
15 | self.tile_x, self.tile_y = pos
16 | self.cost = 100
17 | get_images(name)
18 |
19 | self.can_drop_food = False
20 | self.can_drop_wood = False
21 |
22 |
23 | class LumberYard(Building):
24 | def __init__(self, world, image_string="LumberYard"):
25 | Building.__init__(self, world, "Lumber Yard", image_string)
26 |
27 | self.image = self.image_funcs.get_irregular_image(2, 2, 2, 2)
28 | self.Held = 0
29 | self.HeldMax = 50
30 | self.cost = 100
31 |
32 | self.world.MAXwood += self.HeldMax
33 | self.can_drop_wood = True
34 |
35 |
36 | class Dock(Building):
37 |
38 | def __init__(self, world, image_string="Dock"):
39 | Building.__init__(self, world, "Dock", image_string)
40 |
41 | self.image = self.image_funcs.get_irregular_image(2, 2, 2, 0)
42 |
43 | self.Held = 0
44 | self.HeldMax = 25
45 | self.cost = 150
46 |
47 | self.can_drop_food = True
48 |
49 | self.world.MAXfood += self.HeldMax
50 |
51 | class House(Building):
52 | def __init__(self, world, image_string="House"):
53 | Building.__init__(self, world, "House", image_string)
54 |
55 | self.supports = 5
56 | self.cost = 30
57 |
58 | self.world.MAXpopulation += self.supports
59 |
60 |
61 | class Manor(Building):
62 | def __init__(self, world, image_string="Manor"):
63 | Building.__init__(self, world, "Manor", image_string)
64 |
65 | self.image = self.image_funcs.get_irregular_image(2, 2, 2, 4)
66 |
67 | self.supports = 15
68 | self.cost = 100
69 |
70 | self.world.MAXpopulation += self.supports
71 |
72 | class TownCenter(Building):
73 | def __init__(self, world, image_string="Manor"):
74 | Building.__init__(self, world, "Town Center", image_string)
75 |
76 | self.image = self.image_funcs.get_irregular_image(2, 2, 2, 6)
77 |
78 | self.can_drop_food = True
79 | self.can_drop_wood = True
80 |
81 | self.supports = 15
82 | self.cost = 500
83 |
84 | self.world.MAXpopulation += self.supports
85 | self.world.MAXWood += 50
86 | self.world.MAXFood += 50
87 |
88 |
89 | class UnderConstruction(Building):
90 | def __init__(self, world, image_string, will_be):
91 | Building.__init__(self, world, "Under Construction", image_string)
92 | self.will_be = will_be
93 | self.ttb = 30.0
94 | self.max_ttb = 30.0
95 |
96 | def create(self):
97 | self.world.add_built(self.will_be, self.location)
98 | self.world.remove_entity(self)
99 |
100 |
101 | class StoreShed(Building):
102 |
103 | def __init__(self, world, image_string):
104 | Building.__init__(self, world, "Store Shed", image_string)
105 |
--------------------------------------------------------------------------------
/Clips.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | dialol = pygame.image.load("Images/Dial/dial_outline2.png")
4 | dial = pygame.image.load("Images/Dial/dial.png")
5 | dialol.set_colorkey((255, 0, 255))
6 | dial.set_colorkey((255, 0, 255))
7 |
8 | buildings = ["House", "LumberYard", "Dock", "Manor", "Town Center"]
9 |
10 |
11 | class Clips(object):
12 | """
13 | ______________________
14 | | |
15 | | |
16 | | |
17 | | |
18 | | |
19 | | |
20 | | _____|
21 | | |MINI-|
22 | | |MAP |
23 | ----------------------
24 | """
25 |
26 | def __init__(self, world, screen_size):
27 | self.size = screen_size
28 | self.world = world
29 |
30 | # The minimap is 1/4 the size of the screen in each dimension (1/16 total size)
31 | self.minimap_size = int(self.size[0] / 4), int(self.size[1] / 4)
32 |
33 | # TODO: Is this necessary?
34 | self.minimap = pygame.transform.scale(
35 | self.world.minimap_img,
36 | self.minimap_size)
37 |
38 | # Ratio between the size of the tile array and the minimap size
39 | self.a = self.world.w / float(self.minimap_size[0])
40 | self.b = self.world.h / float(self.minimap_size[1])
41 |
42 | # Not quite sure what this does
43 | self.rect_view_w = (self.size[0] / self.a) - ((self.size[0] / self.a) / 5)
44 | self.rect_view_h = self.size[1] / self.b
45 |
46 | self.minimap_rect = pygame.Rect(self.size[0] - self.minimap_size[0], self.size[1] - self.minimap_size[1],
47 | self.minimap_size[0], self.minimap_size[1])
48 |
49 | def render(self, surface):
50 |
51 | rect_view_pos = (
52 | (-1 * self.world.world_position.x / self.a) + self.size[0] - self.minimap_size[0] + ((self.size[0] / 5) / self.a),
53 | (-1 * self.world.world_position.y / self.b) + self.size[1] - self.minimap_size[1])
54 |
55 | rect_view = (
56 | rect_view_pos,
57 | (self.rect_view_w,
58 | self.rect_view_h))
59 |
60 | self.world.render(surface)
61 | # self.update_dial(surface, tp)
62 |
63 | # Draw minimap below here ------------------
64 | surface.set_clip(self.minimap_rect)
65 |
66 | # Drawing the actual minimap
67 | surface.blit(self.minimap, self.minimap_rect)
68 |
69 | # Draw the white rectangle displaying where the user is located
70 | pygame.draw.rect(surface, (255, 255, 255), rect_view, 1)
71 |
72 | # Draw a black border
73 | pygame.draw.rect(surface, (0, 0, 0), self.minimap_rect, 2)
74 |
75 | surface.set_clip(None)
76 | # Draw minimap above here --------------------
77 |
78 | def update_dial(self, surface, tp): # Dial goes below here
79 | box = (self.size[0] - 55, self.size[1] / 50 - 40)
80 | boxtest = pygame.Rect((box[0] - 20, box[1] + 80), (50, 50))
81 | oldCenter = boxtest.center
82 | rotateddial = pygame.transform.rotate(dial, self.world.clock_degree)
83 | rotRect = rotateddial.get_rect()
84 | rotRect.center = oldCenter
85 | self.world.clock_degree += tp
86 | if self.world.clock_degree >= 360.0:
87 | self.world.clock_degree = 0.0
88 |
89 | surface.blit(rotateddial, rotRect)
90 | surface.blit(dialol, (box[0] - 44, box[1] + 55))
--------------------------------------------------------------------------------
/DebugTools.py:
--------------------------------------------------------------------------------
1 | import TileFuncs
2 |
3 | def print_surrounding_tiles(world, print_type="Name"):
4 | tile_range = 2
5 | location_array = TileFuncs.get_vnn_array(world, world.entities[0].location, tile_range)
6 |
7 | if print_type=="Name":
8 | tile_list = tile_array_from_location(world, location_array)
9 | else:
10 | tile_list = location_array
11 | # print "Length of tile_list: %d"%len(tile_list)
12 |
13 | print(tile_list[0])
14 | print(tile_list[1], tile_list[2], tile_list[3])
15 | print(tile_list[4])
16 | print("")
17 |
18 | def tile_array_from_location(world, array):
19 | return_array = []
20 | for i in array:
21 | return_array.append(TileFuncs.get_tile(world, i).name)
22 |
23 | return return_array
24 |
25 | def print_location_tile(world, location):
26 | print(TileFuncs.get_tile(world, location).__class__.__name__)
27 |
--------------------------------------------------------------------------------
/Entities.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | from World import *
3 | from GameEntity import *
4 | from gametools.vector2 import *
5 |
6 | from random import *
7 |
8 |
9 | class Tree(GameEntity):
10 | def __init__(self, world, image):
11 | GameEntity.__init__(self, world, "Tree", image)
12 |
13 |
14 | class Sapling(GameEntity):
15 | def __init__(self, world, image):
16 | GameEntity.__init__(self, world, "Sapling", image)
17 | growing_state = Growing(self)
18 | self.brain.add_state(growing_state)
19 | self.ttg = 30.0
20 |
21 |
22 | class Growing(State):
23 | def __init__(self, Sapling):
24 | State.__init__(self, "Growing")
25 | self.Sapling = Sapling
26 |
27 | def check_conditions(self):
28 | if self.Sapling.ttg <= 0:
29 | new_tree = Tree(self.Sapling.world, tree_image)
30 | new_tree.location = self.Sapling.location.copy()
31 | self.Sapling.world.add_entity(new_tree)
32 | self.Sapling.world.remove_entity(self.Sapling)
33 |
34 | def do_actions(self):
35 | self.Sapling.ttg -= self.Sapling.tp
36 | # print self.Sapling.ttg
37 |
--------------------------------------------------------------------------------
/Explorer.py:
--------------------------------------------------------------------------------
1 | """The explorer is a villager driven to the find the amazing by thier
2 | unwaivering curiosity for what is unknown. These will seek new land
3 | and features to help advance the civilization, though may at times
4 | pursure knowledge at other costs.
5 |
6 | Also this class was primarily developed to track down movement bugs."""
7 |
8 | import aitools.StateMachine
9 |
10 | import GameEntity
11 | import BaseFunctions
12 |
13 | class Explorer(GameEntity.GameEntity):
14 | """See file doctring for the description."""
15 |
16 |
17 | def __init__(self, world, image_string):
18 | """Basic initialization for the class."""
19 |
20 | GameEntity.GameEntity.__init__(self, world, "Explorer", "Entities/"+image_string)
21 |
22 | self.speed = 80.0 * (1.0 / 60.0)
23 | self.base_speed = self.speed
24 | self.view_range = 8
25 |
26 | self.exploring_state = Exploring(self)
27 |
28 | self.brain.add_state(self.exploring_state)
29 |
30 | self.worldSize = world.world_size
31 | self.TileSize = self.world.tile_size
32 |
33 | class Exploring(aitools.StateMachine.State):
34 | """The primary function of the explorer, to search for places previously
35 | unvisited or unfound. Eventually the explorer should keep track of
36 | and prioritize places it hasn't visited."""
37 |
38 | def __init__(self, this_explorer):
39 | aitools.StateMachine.State.__init__(self, "Exploring")
40 | self.explorer = this_explorer
41 |
42 | def entry_actions(self):
43 | """When the explorer starts exploring (enters exploring state)."""
44 | BaseFunctions.random_dest(self.explorer)
45 |
46 | def do_actions(self):
47 | """What should the explorer do while it is exploring"""
48 | pass
49 |
50 | def check_conditions(self):
51 | """Check if the explorer should still be exploring"""
52 | if self.explorer.location.get_distance_to(self.explorer.destination) <= self.explorer.speed:
53 | BaseFunctions.random_dest(self.explorer)
54 |
55 | def exit_actions(self):
56 | """What the explorer does as it stops exploring"""
57 | pass
58 |
--------------------------------------------------------------------------------
/Farmer.py:
--------------------------------------------------------------------------------
1 | """This class is going to be tasked with planting and harvesting crops. This
2 | class used to plant trees, however this has been moved to Arborist (which
3 | is the name of someone who takes care of trees you pleb)."""
4 |
5 | import aitools.StateMachine
6 | from Entities import *
7 | from GameEntity import *
8 | from gametools.vector2 import Vector2
9 | from gametools.ImageFuncs import *
10 | from gametools.ani import *
11 | import math
12 | import pygame
13 | import random
14 | import TileFuncs
15 | import BaseFunctions
16 |
17 | class Farmer(GameEntity):
18 | """The main class for Farmer. See above for the description"""
19 |
20 | def __init__(self, world, image_string):
21 | """Basic initialization"""
22 |
23 | # Initializing the class
24 | GameEntity.__init__(self, world, "Farmer", "Entities/"+image_string)
25 |
26 | # Creating the states
27 | tilling_state = Farmer_Tilling(self)
28 |
29 | # Adding states to the brain
30 | self.brain.add_state(tilling_state)
31 |
32 | self.max_speed = 80.0 * (1.0 / 60.0)
33 | self.speed = self.max_speed
34 | self.base_speed = self.speed
35 |
36 | self.worldSize = world.world_size
37 | self.TileSize = self.world.tile_size
38 |
39 | class Farmer_Tilling(aitools.StateMachine.State):
40 |
41 | def __init__(self, farmer):
42 | aitools.StateMachine.State.__init__(self, "Tilling")
43 | self.farmer = farmer
44 |
45 | def entry_actions(self):
46 | BaseFunctions.random_dest(self.farmer)
47 |
48 | def do_actions(self):
49 | current_tile = TileFuncs.get_tile(self.farmer.world, self.farmer.location)
50 | if current_tile.tillable:
51 | darkness = pygame.Surface((self.farmer.TileSize, self.farmer.TileSize))
52 | darkness.set_alpha(current_tile.darkness)
53 |
54 | new_tile = Tile.SoilTile(self.farmer.world, "Soil2")
55 | new_tile.darkness = darkness
56 |
57 | new_tile.location = current_tile.location
58 | new_tile.rect.topleft = new_tile.location
59 | new_tile.color = current_tile.color # TODO: Figure out what this does.
60 |
61 | self.farmer.world.tile_array[int(new_tile.location.y / 32)][int(new_tile.location.x / 32)] = new_tile
62 | self.farmer.world.world_surface.blit(new_tile.img, new_tile.location)
63 | self.farmer.world.world_surface.blit(darkness, new_tile.location)
64 | # TODO: Update the minimap
65 |
66 | BaseFunctions.random_dest(self.farmer)
67 |
68 | elif self.farmer.location.get_distance_to(self.farmer.destination) < self.farmer.speed:
69 | BaseFunctions.random_dest(self.farmer)
70 |
71 | def check_conditions(self):
72 | pass
73 |
74 | def exit_actions(self):
75 | pass
76 |
77 |
--------------------------------------------------------------------------------
/FishingShip.py:
--------------------------------------------------------------------------------
1 | import GameEntity
2 | import aitools.StateMachine as StateMachine
3 | import math, random
4 | from gametools.vector2 import Vector2
5 | import BaseFunctions
6 |
7 |
8 | class FishingShip(GameEntity.GameEntity):
9 |
10 | def __init__(self, world, img):
11 | GameEntity.GameEntity.__init__(self, world, "Fishing Ship", img)
12 |
13 | self.speed = 50.0 * (1.0 / 60.0)
14 | self.view_range = 5
15 |
16 | self.searching_state = Searching(self)
17 |
18 | self.brain.add_state(self.searching_state)
19 |
20 | class Searching(StateMachine.State):
21 | """Looking for something to gather"""
22 |
23 | def __init__(self, fishing_ship):
24 |
25 | StateMachine.State.__init__(self, "Searching")
26 | self.fishing_ship = fishing_ship
27 |
28 | def check_conditions(self):
29 | if self.fishing_ship.location.get_distance_to(self.fishing_ship.destination) < self.fishing_ship.speed:
30 | BaseFunctions.random_dest(self.fishing_ship)
31 |
32 | def do_actions(self):
33 | pass
34 |
35 | def entry_actions(self):
36 | BaseFunctions.random_dest()
37 |
38 | def exit_actions(self):
39 | pass
40 |
41 | class Gathering(StateMachine.State):
42 | """In the state of gathering"""
43 |
44 | def __init__(self, fishing_ship):
45 |
46 | StateMachine.State.__init__(self, "Gathering")
47 | self.fishing_ship = fishing_ship
48 |
49 | def check_conditions(self):
50 | pass
51 |
52 | def do_actions(self):
53 | pass
54 |
55 | def entry_actions(self):
56 | pass
57 |
58 | def exit_actions(self):
59 | pass
60 |
61 | class Returning(StateMachine.State):
62 | """Returning what is gathered to the dock"""
63 |
64 | def __init__(self, fishing_ship):
65 | StateMachine.State.__init__(self, "Returning")
66 | self.fishing_ship = fishing_ship
67 |
68 | def check_conditions(self):
69 | pass
70 |
71 | def do_actions(self):
72 | pass
73 |
74 | def entry_actions(self):
75 | pass
76 |
77 | def exit_actions(self):
78 | pass
79 |
--------------------------------------------------------------------------------
/GameEntity.py:
--------------------------------------------------------------------------------
1 | from World import *
2 | from aitools.StateMachine import *
3 | from gametools.vector2 import *
4 | import TileFuncs
5 | import pygame
6 | from pygame.locals import *
7 |
8 | # TODO: Clean and add doctrings
9 |
10 |
11 | class GameEntity(object):
12 | def __init__(self, world, name, image_string):
13 |
14 | self.world = world
15 | self.name = name
16 |
17 | self.image = pygame.image.load("Images/"+image_string+".png")
18 | self.orientation = 0
19 |
20 | try:
21 | self.image.set_colorkey((255, 0, 255))
22 | except AttributeError:
23 | pass
24 |
25 | self.location = Vector2(0, 0)
26 | self.world_location = Vector2(0, 0)
27 | self.destination = Vector2(0, 0)
28 |
29 | self.speed = 0.
30 |
31 | self.land_based = True
32 | self.base_speed = self.speed
33 |
34 | self.food = 70
35 | self.water = 70
36 | self.energy = 70
37 | self.active_info = False
38 |
39 | self.brain = StateMachine()
40 |
41 | self.id = 0
42 |
43 | self.tp = 1.0
44 |
45 | def render(self, surface):
46 | x, y = self.world_location
47 | w, h = self.image.get_size()
48 | pos = (x - (w / 2), y - (h / 2))
49 | surface.blit(self.image, pos)
50 |
51 | def check_speed(self):
52 | if TileFuncs.get_tile(self.world, self.location).name in ["AndrewSmoothStone", "MinecraftSnow"]:
53 | self.speed = 0.5 * self.base_speed
54 | else:
55 | self.speed = self.base_speed
56 |
57 | def process(self, time_passed):
58 | self.brain.think()
59 | self.world_location = self.location + self.world.world_position
60 |
61 |
62 | self.check_speed()
63 |
64 | if self.speed > 0. and self.location != self.destination:
65 | vec_to_destination = self.destination - self.location
66 | distance_to_destination = vec_to_destination.get_length()
67 | heading = vec_to_destination.get_normalized()
68 | travel_distance = min(distance_to_destination, self.speed)
69 | self.location += travel_distance * heading * self.speed
70 |
--------------------------------------------------------------------------------
/Images/AnimationsGIMPFiles/CropGrowth.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/AnimationsGIMPFiles/CropGrowth.xcf
--------------------------------------------------------------------------------
/Images/Buildings/Building1Test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Building1Test.png
--------------------------------------------------------------------------------
/Images/Buildings/Dock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Dock.png
--------------------------------------------------------------------------------
/Images/Buildings/Dock_Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Dock_Icon.png
--------------------------------------------------------------------------------
/Images/Buildings/House.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/House.png
--------------------------------------------------------------------------------
/Images/Buildings/House_Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/House_Icon.png
--------------------------------------------------------------------------------
/Images/Buildings/Inn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Inn.png
--------------------------------------------------------------------------------
/Images/Buildings/LumberYard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/LumberYard.png
--------------------------------------------------------------------------------
/Images/Buildings/LumberYard_Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/LumberYard_Icon.png
--------------------------------------------------------------------------------
/Images/Buildings/Manor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Manor.png
--------------------------------------------------------------------------------
/Images/Buildings/Manor_Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/Manor_Icon.png
--------------------------------------------------------------------------------
/Images/Buildings/TotalImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/TotalImage.png
--------------------------------------------------------------------------------
/Images/Buildings/TownHall_Icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/TownHall_Icon.png
--------------------------------------------------------------------------------
/Images/Buildings/UC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/UC.png
--------------------------------------------------------------------------------
/Images/Buildings/UC_Dock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/UC_Dock.png
--------------------------------------------------------------------------------
/Images/Buildings/UC_House.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Buildings/UC_House.png
--------------------------------------------------------------------------------
/Images/Dial/dial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Dial/dial.png
--------------------------------------------------------------------------------
/Images/Dial/dial_outline2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Dial/dial_outline2.png
--------------------------------------------------------------------------------
/Images/Entities/Angler.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Angler.png
--------------------------------------------------------------------------------
/Images/Entities/Arborist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Arborist.png
--------------------------------------------------------------------------------
/Images/Entities/BasicDemon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/BasicDemon.png
--------------------------------------------------------------------------------
/Images/Entities/BigTree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/BigTree.png
--------------------------------------------------------------------------------
/Images/Entities/Builder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Builder.png
--------------------------------------------------------------------------------
/Images/Entities/BuilderLarge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/BuilderLarge.png
--------------------------------------------------------------------------------
/Images/Entities/Explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Explorer.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer.png
--------------------------------------------------------------------------------
/Images/Entities/FarmerLarge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/FarmerLarge.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig1.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig2.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig3.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig4.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig5.png
--------------------------------------------------------------------------------
/Images/Entities/Farmer_dig6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Farmer_dig6.png
--------------------------------------------------------------------------------
/Images/Entities/Lumberjack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Lumberjack.png
--------------------------------------------------------------------------------
/Images/Entities/Lumberjack_chop1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Lumberjack_chop1.png
--------------------------------------------------------------------------------
/Images/Entities/Lumberjack_chop2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Lumberjack_chop2.png
--------------------------------------------------------------------------------
/Images/Entities/Lumberjack_chop3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Lumberjack_chop3.png
--------------------------------------------------------------------------------
/Images/Entities/Tree2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Tree2.png
--------------------------------------------------------------------------------
/Images/Entities/UsainBolt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/UsainBolt.png
--------------------------------------------------------------------------------
/Images/Entities/Villager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/Villager.png
--------------------------------------------------------------------------------
/Images/Entities/VillagerLarge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/VillagerLarge.png
--------------------------------------------------------------------------------
/Images/Entities/VillagerTest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/VillagerTest.png
--------------------------------------------------------------------------------
/Images/Entities/fishingship.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/fishingship.png
--------------------------------------------------------------------------------
/Images/Entities/info_bar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/info_bar.png
--------------------------------------------------------------------------------
/Images/Entities/map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Entities/map.png
--------------------------------------------------------------------------------
/Images/New folder/Clips.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/New folder/Clips.png
--------------------------------------------------------------------------------
/Images/New folder/LumberjackOptimization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/New folder/LumberjackOptimization.png
--------------------------------------------------------------------------------
/Images/Screenshots/README.md:
--------------------------------------------------------------------------------
1 | Folder for Screenshot
2 | ---------------------
3 |
--------------------------------------------------------------------------------
/Images/Screenshots/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Screenshots/Screenshot.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewCobble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewCobble.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewCobble2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewCobble2.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewDeepWater.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewDeepWater.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewGrass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewGrass.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewSmoothStone.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewSmoothStone.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewSmoothStone2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewSmoothStone2.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewWater.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewWater.png
--------------------------------------------------------------------------------
/Images/Tiles/AndrewWater2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/AndrewWater2.png
--------------------------------------------------------------------------------
/Images/Tiles/CarterTree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/CarterTree.jpg
--------------------------------------------------------------------------------
/Images/Tiles/CarterTree2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/CarterTree2.jpg
--------------------------------------------------------------------------------
/Images/Tiles/Cobble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/Cobble.png
--------------------------------------------------------------------------------
/Images/Tiles/GrassWithCenterTree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/GrassWithCenterTree.png
--------------------------------------------------------------------------------
/Images/Tiles/GrassWithTwoTrees.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/GrassWithTwoTrees.png
--------------------------------------------------------------------------------
/Images/Tiles/MinecraftDarkGrass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/MinecraftDarkGrass.png
--------------------------------------------------------------------------------
/Images/Tiles/MinecraftGrass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/MinecraftGrass.png
--------------------------------------------------------------------------------
/Images/Tiles/MinecraftSnow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/MinecraftSnow.png
--------------------------------------------------------------------------------
/Images/Tiles/MyGrass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/MyGrass.png
--------------------------------------------------------------------------------
/Images/Tiles/Sand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/Sand.png
--------------------------------------------------------------------------------
/Images/Tiles/Soil1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/Soil1.png
--------------------------------------------------------------------------------
/Images/Tiles/Soil2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/Soil2.png
--------------------------------------------------------------------------------
/Images/Tiles/Water.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/Water.png
--------------------------------------------------------------------------------
/Images/Tiles/baby_tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/baby_tree.png
--------------------------------------------------------------------------------
/Images/Tiles/cobble_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/najarvis/villager-sim/55fca98611bbbd927f8e6981a8e68040b03fd5e3/Images/Tiles/cobble_left.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/Lumberjack.py:
--------------------------------------------------------------------------------
1 | from aitools.StateMachine import *
2 | from Entities import *
3 | from GameEntity import *
4 | from gametools.vector2 import Vector2
5 | from gametools.ImageFuncs import *
6 | from gametools.ani import *
7 | import Tile
8 | import math
9 | import pygame
10 | import random
11 | import TileFuncs
12 | from World import *
13 | import BaseFunctions
14 |
15 | NoTreeImg = pygame.image.load("Images/Tiles/MinecraftGrass.png")
16 |
17 | class Lumberjack(GameEntity):
18 |
19 | def __init__(self, world, image_string):
20 | # Initializing the class
21 | GameEntity.__init__(self, world, "Lumberjack", "Entities/"+image_string)
22 |
23 | self.speed = 100.0 * (1.0 / 60.0)
24 | self.base_speed = self.speed
25 | self.view_range = 6
26 |
27 | # Creating the states
28 | self.searching_state = Searching(self)
29 | self.chopping_state = Chopping(self)
30 | self.delivering_state = Delivering(self)
31 |
32 | # Adding states to the brain
33 | self.brain.add_state(self.searching_state)
34 | self.brain.add_state(self.chopping_state)
35 | self.brain.add_state(self.delivering_state)
36 |
37 | self.worldSize = world.world_size
38 | self.TileSize = self.world.tile_size
39 |
40 | # animation variables
41 | self.animation = Ani(5,10)
42 | self.pic = pygame.image.load("Images/Entities/map.png")
43 | self.img_func = ImageFuncs(18, 17,self.pic)
44 | self.sprites = self.img_func.get_images(5,0,1)
45 | self.hit = 0
46 | self.update()
47 |
48 | def update(self):
49 | # Updates image every 10 cycles and adds 1 to the 4 hit dig
50 | self.image = self.sprites[self.animation.get_frame()]
51 | self.image.set_colorkey((255,0,255))
52 | if self.animation.finished == True:
53 | self.hit += 1
54 | self.animation.finished = False
55 |
56 |
57 | class Searching(State):
58 | """This state will be used to have the Lumberjack looking for
59 | trees to cut, It needs to be fast enough to have AT LEAST 20 Lumberjacks
60 | with little to no framerate loss.
61 |
62 | Perhaps it could be used to find a clump of trees. and then the Lumberjack
63 | wouldn't just wander around aimlessly searching for trees even though it
64 | saw some when it was just at another tree"""
65 |
66 | def __init__(self, Lumberjack):
67 | State.__init__(self, "Searching")
68 | self.lumberjack = Lumberjack
69 |
70 | def entry_actions(self):
71 | BaseFunctions.random_dest(self.lumberjack)
72 |
73 | def do_actions(self):
74 | pass
75 |
76 | def check_conditions(self):
77 | if self.lumberjack.location.get_distance_to(self.lumberjack.destination) < 15:
78 | location_array = TileFuncs.get_vnn_array(self.lumberjack.world,(self.lumberjack.location), self.lumberjack.view_range)
79 |
80 | for location in location_array:
81 | test_tile = TileFuncs.get_tile(self.lumberjack.world,location)
82 | if test_tile.name == "GrassWithCenterTree":
83 | self.lumberjack.Tree_tile = test_tile
84 | self.lumberjack.tree_id = test_tile.id
85 |
86 | self.lumberjack.destination = location.copy()
87 | return "Chopping"
88 |
89 | BaseFunctions.random_dest(self.lumberjack)
90 |
91 | def exit_actions(self):
92 | pass
93 |
94 |
95 | class Chopping(State):
96 | def __init__(self, Lumberjack):
97 | State.__init__(self, "Chopping")
98 | self.lumberjack = Lumberjack
99 |
100 | def entry_actions(self):
101 | pass
102 |
103 | def do_actions(self):
104 | pass
105 |
106 | def check_conditions(self):
107 | check = TileFuncs.get_tile(self.lumberjack.world,Vector2(self.lumberjack.location))
108 | if self.lumberjack.location.get_distance_to(self.lumberjack.destination) < 15:
109 | self.lumberjack.destination = Vector2(self.lumberjack.location)
110 |
111 | if check.name != "GrassWithCenterTree":
112 | self.lumberjack.hit = 0
113 | self.lumberjack.update()
114 | return "Searching"
115 |
116 | self.lumberjack.update()
117 |
118 | if self.lumberjack.hit >= 4:
119 | self.lumberjack.destination = Vector2(self.lumberjack.location)
120 | self.lumberjack.update()
121 |
122 | old_tile = TileFuncs.get_tile(self.lumberjack.world,Vector2(self.lumberjack.location))
123 |
124 | darkness = pygame.Surface((32, 32))
125 | darkness.set_alpha(old_tile.darkness)
126 |
127 | new_tile = Tile.TreePlantedTile(self.lumberjack.world, "MinecraftGrass")
128 |
129 | new_tile.darkness = old_tile.darkness
130 |
131 | new_tile.location = TileFuncs.get_tile_pos(self.lumberjack.world,self.lumberjack.destination)*32
132 | new_tile.rect.topleft = new_tile.location
133 | new_tile.color = old_tile.color
134 |
135 | self.lumberjack.world.tile_array[int(new_tile.location.y/32)][int(new_tile.location.x/32)] = new_tile
136 | self.lumberjack.world.world_surface.blit(new_tile.img, new_tile.location)
137 | self.lumberjack.world.world_surface.blit(darkness, new_tile.location)
138 |
139 | self.lumberjack.hit = 0
140 |
141 | # del self.lumberjack.world.TreeLocations[str(self.lumberjack.tree_id)]
142 | return "Delivering"
143 |
144 | def exit_actions(self):
145 | pass
146 |
147 |
148 | class Delivering(State):
149 | """This state will be used solely to deliver wood from wherever the Lumberjack
150 | got the wood to the closest Lumber yard. maybe all the lumber yards could
151 | be stored in a dictionary similar to trees, that would be much faster"""
152 |
153 | def __init__(self, Lumberjack):
154 | State.__init__(self, "Delivering")
155 | self.lumberjack = Lumberjack
156 |
157 | def entry_actions(self):
158 | self.lumberjack.destination = Vector2(self.lumberjack.world.w/2,self.lumberjack.world.h/2)
159 |
160 | def do_actions(self):
161 | pass
162 |
163 | def check_conditions(self):
164 |
165 | # if self.lumberjack.world.wood >= self.lumberjack.world.MAXwood:
166 | # return "IDLE"
167 |
168 | if self.lumberjack.location.get_distance_to(self.lumberjack.destination) < 15:
169 | self.lumberjack.world.wood += 5
170 | return "Searching"
171 |
172 | def exit_actions(self):
173 | pass
174 |
175 |
176 | class IDLE(State):
177 | def __init__(self, Lumberjack):
178 | State.__init__(self, "Delivering")
179 | self.lumberjack = Lumberjack
180 |
181 | def entry_actions(self):
182 | pass
183 |
184 | def do_actions(self):
185 | pass
186 |
187 | def check_conditions(self):
188 | pass
189 |
190 | def exit_actions(self):
191 | pass
192 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Villager-Sim
2 | ============
3 |
4 | A project we have been working on for a while. The end goal is to create a
5 | civilization that can grow and explore on it's own though artificial intelligence
6 | by setting goals for itself, learning what it needs to do to accomplish those goals.
7 |
8 | Start
9 | -----
10 |
11 | To run this you must Install PyGame - http://www.pygame.org/download.shtml
12 |
13 | Start with ```python UpdatingVillagerSim.py```
14 |
15 | Additional start flags:
16 |
17 | ```python UpdatingVillagerSim.py [fullscreen] [world size] [hard shadow]```
18 |
19 | ```fullscreen``` is a boolean value (0 / 1) that controls if the game will start fullscreen or not. WARNING: If running on linux, if the program crashes while in fullscreen mode it is difficult to close.
20 |
21 | ```world size``` is an integer (preferably an order of magnitude of 2) that controls the dimensions of the tile map of the game world. The game world is a square so you only need to supply the value of one side (e.g. 64).
22 |
23 | ```hard shadow``` is a boolean value (0 / 1) that controls if the shadow from elevation is rendered on the game world or just the minimap.
24 |
25 | Note, you cannot just select ```hard shadow``` without the other two, nor ```world size``` without ```fullscreen```.
26 |
27 | Licence
28 | -------
29 |
30 | GNU GENERAL PUBLIC LICENSE Version 2
31 |
--------------------------------------------------------------------------------
/Tile.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | from gametools.vector2 import Vector2
4 |
5 |
6 | class Tile(object):
7 | def __init__(self, world, tile_name="NULL"):
8 | self.world = world
9 | self.name = tile_name
10 | self.img = pygame.image.load("Images/Tiles/"+tile_name+".png").convert()
11 | self.location = Vector2(0, 0)
12 | self.walkable = False
13 | self.fishable = False
14 | self.plantable = False
15 | self.tillable = False
16 | self.crop_plantable = False
17 | self.buildable = False
18 | self.buildable_w = False
19 | self.darkness = 0
20 |
21 | self.id = 0
22 | self.rect = pygame.Rect((0, 0), self.img.get_size())
23 |
24 | def render(self, screen):
25 | screen.blit(self.img, self.location)
26 |
27 |
28 | class GrassTile(Tile):
29 | def __init__(self, world, tile_name):
30 | Tile.__init__(self, world, tile_name)
31 | self.walkable = True
32 | self.buildable = True
33 | self.plantable = True
34 | self.tillable = True
35 |
36 | class WaterTile(Tile):
37 | def __init__(self, world, tile_name):
38 | Tile.__init__(self, world, tile_name)
39 | self.buildable_w = True
40 | self.fishable = True
41 |
42 | class DeepWaterTile(Tile):
43 | def __init__(self, world, tile_name):
44 | Tile.__init__(self, world, tile_name)
45 | self.buildable_w = True
46 |
47 | class SmoothStoneTile(Tile):
48 | def __init__(self, world, tile_name):
49 | Tile.__init__(self, world, tile_name)
50 | self.walkable = True
51 | self.buildable = True
52 |
53 | class CobblestoneTile(Tile):
54 | def __init__(self, world, tile_name):
55 | Tile.__init__(self, world, tile_name)
56 | self.walkable = True
57 | self.buildable = True
58 |
59 | class DirtTile(Tile):
60 | def __init__(self, world, tile_name):
61 | Tile.__init__(self, world, tile_name)
62 | self.walkable = True
63 | self.buildable = True
64 | self.tillable = True
65 |
66 | class BeachTile(Tile):
67 | def __init__(self, world, tile_name):
68 | Tile.__init__(self, world, tile_name)
69 | self.walkable = True
70 | self.buildable = True
71 |
72 | class Baby_Tree(Tile):
73 | def __init__(self, world, tile_name):
74 | Tile.__init__(self, world, tile_name)
75 | self.walkable = True
76 |
77 | class TreePlantedTile(Tile):
78 | def __init__(self, world, tile_name):
79 | Tile.__init__(self, world, tile_name)
80 | self.walkable = True
81 | self.Taken = False
82 |
83 | class SnowTile(Tile):
84 | def __init__(self, world, tile_name):
85 | Tile.__init__(self, world, tile_name)
86 |
87 |
88 | class BuildingTile(Tile):
89 | def __init__(self, world, tile_name):
90 | Tile.__init__(self, world, tile_name)
91 | self.walkable = True
92 |
93 | class SoilTile(Tile):
94 | def __init__(self, world, tile_name):
95 | Tile.__init__(self, world, tile_name)
96 | self.walkable = True
97 | self.crop_plantable = True
98 |
--------------------------------------------------------------------------------
/TileFuncs.py:
--------------------------------------------------------------------------------
1 | from gametools import vector2
2 | import Tile
3 | import math
4 |
5 | def get_tile(world, location):
6 | tile = get_tile_pos(world, location)
7 | try:
8 | return world.tile_array[int(tile.y)][int(tile.x)]
9 | except IndexError:
10 | return Tile.Tile(world, "Sand")
11 |
12 | def get_tile_pos(world, location):
13 | return vector2.Vector2(int(location.x) >> 5, int(location.y) >> 5)
14 |
15 | def get_entity(world,location, radius = 20):
16 | for i in world.entities.items():
17 | ent_location = i[1].world_location
18 | if ((ent_location.x - location.x)**2 + (ent_location.y - location.y)**2) < radius**2:
19 | return i
20 | # print "no ents"
21 |
22 | def get_tile_array(world, start_pos, dimensions):
23 | dimensions = (int(dimensions[0]), int(dimensions[1]))
24 |
25 | start_tile = get_tile_pos(world,start_pos)
26 |
27 | array = [[None for i in xrange((dimensions[0] * 2) + 1)]
28 | for a in xrange((dimensions[1] * 2) + 1)]
29 |
30 | for i in xrange((dimensions[0] * 2) + 1):
31 | for a in xrange((dimensions[1] * 2) + 1):
32 | if start_tile.x + i < 0 or start_tile.y + a < 0:
33 | continue
34 |
35 | else:
36 | try:
37 | array[a][i] = world.tile_array[int((start_tile.y + a) - 1)][int((start_tile.x + i) - 1)]
38 | except IndexError:
39 | #print a, i, start_tile
40 | raise IndexError
41 | return array
42 |
43 | def get_vnn_array(world, location, r):
44 | """ Stands for Von Neumann Neighborhood.
45 | Simply returns a neighborhood of locations based
46 | on the initial location and range r"""
47 |
48 | return_array = []
49 |
50 | """
51 | range: 3
52 | num rows: 5 (number of rows is equal to (2 * r) - 1
53 | 0 * 1 left column is row_number
54 | 1 * * * 3 right column is num_in_row
55 | 2 * * * * * 5
56 | 3 * * * 3 middle is illustration of what is looks like
57 | 4 * 1 num_in_row is just how many spots are looked at in the current row.
58 | """
59 |
60 | for row_number in range((2 * r) - 1):
61 | if row_number >= r:
62 | num_in_row = (2 * row_number) - (4 * (row_number - r + 1) - 1)
63 | else:
64 | num_in_row = (2 * row_number) + 1
65 |
66 | for cell in range(num_in_row):
67 |
68 | """
69 | the y_offset goes from -(r - 1) to +(r - 1) (not affected by the inner loop)
70 |
71 | the x_offset goes from -math.floor(num_in_row / 2.0) to +math.floor(num_in_row / 2.0)
72 |
73 | 0 0 1 | (0, -2) x, y offset pairs of a range 3 vnn array
74 | 1 0 1 2 3 | (-1, -1) (0, -1) (1, -1)
75 | 2 0 1 2 3 4 5 | (-2, 0) (-1, 0 ) (0, 0 ) (1, 0 ) (2, 0) left column is row_number
76 | 3 0 1 2 3 | (-1, 1 ) (0, 1 ) (1, 1 ) right column is num_in_row
77 | 4 0 1 | (0, 2 ) middle is cell number
78 | """
79 |
80 | tile_size = world.tile_size
81 | x_offset = cell - math.floor(num_in_row / 2.0)
82 | y_offset = row_number - (r - 1)
83 |
84 | new_location = vector2.Vector2(location.x + (x_offset * tile_size), location.y + (y_offset * tile_size))
85 | return_array.append(new_location)
86 |
87 | return return_array
88 |
--------------------------------------------------------------------------------
/UpdatingVillagerSim.py:
--------------------------------------------------------------------------------
1 | #!python2
2 |
3 | """This will basically be a rewrite of the original file,
4 | but this time with a focus on clean code and commenting."""
5 |
6 | import sys
7 | import pygame
8 | import gametools.vector2
9 | import TileFuncs
10 | import World
11 | import DebugTools
12 |
13 | def run(fullscreen, world_size=64):
14 | """The main function to run the program.
15 |
16 | Args:
17 | fullscreen: Boolean value that determines if the program is
18 | in fullscreen mode.
19 |
20 | world_size: Integer (power of 2) value that determines the
21 | dimensions of the game world in terms of tiles.
22 |
23 | Returns:
24 | None
25 | """
26 |
27 | pygame.init()
28 | screen_size = (1280, 720)
29 | if fullscreen:
30 | screen_size = pygame.display.list_modes()[0]
31 | if screen_size[0] > 1920:
32 | screen_size = (1920, 1080)
33 | screen = pygame.display.set_mode(screen_size,
34 | pygame.FULLSCREEN | pygame.HWSURFACE)
35 | else:
36 | screen = pygame.display.set_mode(screen_size, 0)
37 |
38 | game_world = World.World((world_size, world_size), screen_size)
39 |
40 | pygame.display.set_caption("Villager Sim")
41 |
42 | # Tick the clock once to avoid one huge tick when the game starts
43 | game_world.clock.tick()
44 |
45 | pause = False
46 |
47 | done = False
48 | while not done:
49 |
50 | # Cap the game at 60 fps
51 | time_passed_seconds = game_world.clock.tick(60) / 1000.0
52 | pos = gametools.vector2.Vector2(*pygame.mouse.get_pos())
53 |
54 | for event in pygame.event.get():
55 |
56 | # Close button clicked
57 | if event.type == pygame.QUIT:
58 | done = True
59 |
60 | elif event.type == pygame.KEYDOWN:
61 |
62 | # Escape key pressed
63 | if event.key == pygame.K_ESCAPE:
64 | done = True
65 |
66 | elif event.key == pygame.K_SPACE:
67 | pause = not pause
68 |
69 | elif event.key == pygame.K_F3:
70 | pygame.image.save(game_world.world_surface, "FullScreenshot.png")
71 |
72 | elif event.type == pygame.MOUSEBUTTONDOWN:
73 | if event.button == 3:
74 | entity = TileFuncs.get_entity(game_world, pos)
75 | if entity is not None:
76 | # Toggle the entity info
77 | entity[1].active_info = not entity[1].active_info
78 |
79 | if pygame.mouse.get_pressed()[0]:
80 | # check to see if the user is clicking on the minimap and update position accordingly
81 | game_world.check_minimap_update(pos)
82 |
83 | # Process everything in the game world
84 | if not pause:
85 | game_world.process(time_passed_seconds)
86 |
87 | # Clear the screen, then draw the world onto it
88 | screen.fill((0, 0, 0))
89 | game_world.render_all(screen)
90 |
91 | # Update the screen
92 | pygame.display.update()
93 |
94 | pygame.quit()
95 |
96 | if __name__ == "__main__":
97 | if len(sys.argv) == 2:
98 | run(bool(int(sys.argv[1])))
99 | elif len(sys.argv) >= 3:
100 | run(bool(int(sys.argv[1])), int(sys.argv[2]))
101 | else:
102 | run(True, 128)
103 |
--------------------------------------------------------------------------------
/VillagerSim.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #-*- coding:utf-8 -*-
3 |
4 | """VillagerSim, a project aimed at creating an artificial intelligence, capable of exploring an island"""
5 |
6 | import pygame
7 |
8 | pygame.init()
9 |
10 | from gametools.vector2 import Vector2
11 | from World import World
12 | from datetime import datetime
13 | from Clips import Clips
14 |
15 |
16 | def run():
17 | """Simply runs the game."""
18 |
19 |
20 | font = pygame.font.SysFont("Terminal", 20)
21 | bool_full = False
22 | screen_size = (1280, 720)
23 |
24 | screen_width, screen_height = screen_size
25 |
26 | side_size = screen_width / 5.0
27 |
28 | if bool_full:
29 | screen = pygame.display.set_mode((1600, 900), pygame.FULLSCREEN | pygame.HWSURFACE, 32)
30 | else:
31 | screen = pygame.display.set_mode(screen_size, 0, 32)
32 |
33 | # For the selection
34 | draw = False
35 | held = False
36 |
37 | s_size = 128
38 | size = (s_size, s_size)
39 |
40 | seed = None
41 |
42 | world = World(size, font, seed, screen_size)
43 |
44 | # These are all loaded here to be used in the main file.
45 | # TODO: Move these somewhere else
46 | placing_lumberyard_img = pygame.image.load("Images/Buildings/Dark_LumberYard.png").convert()
47 | placing_lumberyard_img.set_colorkey((255, 0, 255))
48 |
49 | placing_house_img = pygame.image.load("Images/Buildings/Dark_House.png").convert()
50 | placing_house_img.set_colorkey((255, 0, 255))
51 |
52 | placing_dock_img = pygame.image.load("Images/Buildings/Dark_Dock.png").convert()
53 | placing_dock_img.set_colorkey((255, 0, 255))
54 |
55 | placing_manor_img = pygame.image.load("Images/Buildings/Dark_Manor.png").convert()
56 | placing_manor_img.set_colorkey((255, 0, 255))
57 |
58 | bad_lumberyard_img = pygame.image.load("Images/Buildings/Red_LumberYard.png").convert()
59 | bad_lumberyard_img.set_colorkey((255, 0, 255))
60 |
61 | world.clipper = Clips(world, (screen_width, screen_height))
62 | selected_building = "LumberYard"
63 | selected_img = pygame.image.load(
64 | "Images/Buildings/Dark_LumberYard.png").convert()
65 | selected_img.set_colorkey((255, 0, 255))
66 |
67 | world.clock.tick()
68 | done = False
69 | while not done:
70 |
71 | time_passed_seconds = world.clock.tick_busy_loop(60) / 1000.
72 | pos = Vector2(*pygame.mouse.get_pos())
73 |
74 | for event in pygame.event.get():
75 | if event.type == pygame.QUIT:
76 | done = True
77 |
78 | if event.type == pygame.MOUSEBUTTONDOWN:
79 | if (pos.x > world.clipper.minimap_rect.x and pos.y >
80 | world.clipper.minimap_rect.y):
81 | pass
82 | else:
83 | if event.button == 1 and selected_building is None:
84 | """This determines what icon you clicked on in the building selector"""
85 | held = True
86 | start = Vector2(*pygame.mouse.get_pos())
87 | draw = True
88 | if (pos.x < world.clipper.side.w) and (pos.y < world.clipper.side.top_rect.h):
89 | for tile_list in world.clipper.side.tiles:
90 | for tile in tile_list:
91 | if tile is None:
92 | continue
93 |
94 | if tile.rect.collidepoint((pos.x, pos.y)):
95 | if tile.selected:
96 | tile.selected = False
97 | else:
98 | tile.selected = True
99 |
100 | selected_building = tile.rep
101 | world.clipper.side.update(tile)
102 |
103 | else:
104 | world.clipper.side.update()
105 |
106 | elif event.button == 1 and selected_building is not None:
107 | if pos.x > world.clipper.side.w:
108 | world.add_building(selected_building, pos)
109 | if world.test_buildable(selected_building, 0, pos):
110 | selected_building = None
111 | world.clipper.side.update()
112 |
113 | if event.button == 3:
114 | selected_building = None
115 |
116 | if event.type == pygame.MOUSEBUTTONUP:
117 | draw = False
118 | held = False
119 |
120 | if event.type == pygame.KEYDOWN:
121 | if event.key == pygame.K_F2 or event.key == pygame.K_F3 or \
122 | event.key == pygame.K_F4:
123 | str1 = str(datetime.now())
124 | str1 = str1.split(".")
125 | str2 = str1[0] + str1[1]
126 | str2 = str2.split(":")
127 | str1 = ""
128 | for i in str2:
129 | str1 += i
130 |
131 | if event.key == pygame.K_F2:
132 | pygame.image.save(screen, "Images/Screenshots/SCREENSHOT%s.png" %str1)
133 |
134 | elif event.key == pygame.K_F3:
135 | pygame.image.save(world.clipper.minimap, "Images/Screenshots/MinimapSCREENSHOT%s.png" %str1)
136 |
137 | elif event.key == pygame.K_F4:
138 | pygame.image.save(world.full_surface, "Images/Screenshots/FULL_MAP_RENDER%s.png" %str1)
139 |
140 | if event.key == pygame.K_n:
141 | world.new_world()
142 |
143 | if event.key == pygame.K_ESCAPE:
144 | done = True
145 |
146 | # ------------------Keys Below--------------------------------------
147 | pressed_keys = pygame.key.get_pressed()
148 | if pressed_keys[pygame.K_ESCAPE]: # quits the game
149 | done = True
150 |
151 | if pressed_keys[pygame.K_d]: # Fast-forward function
152 | world.clock_degree += 5
153 |
154 | # Test to see what the first entity's current state is
155 | if pressed_keys[pygame.K_l]:
156 | print world.entities[0].brain.active_state
157 |
158 | # --------------Keys Above----------------------------------------
159 | # --------------Mouse Below---------------------------------------
160 |
161 | if int(pos.x) <= 15:
162 | if not bool_full:
163 | pygame.mouse.set_pos((15, pos.y))
164 | world.background_pos.x += 500 * time_passed_seconds
165 | if world.background_pos.x > side_size:
166 | world.background_pos.x = side_size
167 |
168 | elif int(pos.x) >= screen_width - 16:
169 | if not bool_full:
170 | pygame.mouse.set_pos((screen_width - 16, pos.y))
171 | world.background_pos.x -= 500 * time_passed_seconds
172 |
173 | if world.background_pos.x < -1 * (world.w - screen_width):
174 | world.background_pos.x = -1 * (world.w - screen_width)
175 |
176 | # print world.background_pos.x
177 |
178 | if int(pos.y) <= 15:
179 | if not bool_full:
180 | pygame.mouse.set_pos((pos.x, 15))
181 | world.background_pos.y += 500 * time_passed_seconds
182 |
183 | if world.background_pos.y > 0:
184 | world.background_pos.y = 0
185 |
186 | elif int(pos.y) >= screen_height - 16:
187 |
188 | if not bool_full:
189 | pygame.mouse.set_pos((pos.x, screen_height - 16))
190 |
191 | world.background_pos.y -= 500 * time_passed_seconds
192 |
193 | if world.background_pos.y < -1 * (world.h - screen_height):
194 | world.background_pos.y = -1 * (world.h - screen_height)
195 |
196 | if pygame.mouse.get_pressed()[0]:
197 | if pos.x > world.clipper.minimap_rect.x and pos.y > world.clipper.minimap_rect.y:
198 | """ If the player clicked on the mini map,
199 | go to that location with the view centered on the event position"""
200 | draw = False
201 | if not held:
202 | world.background_pos.x = (-1 * (pos.x - world.clipper.minimap_rect.x) * world.clipper.a) + (
203 | world.clipper.rect_view_w * world.clipper.a) / 2
204 |
205 | world.background_pos.y = (-1 * (pos.y - world.clipper.minimap_rect.y) * world.clipper.b) + (
206 | world.clipper.rect_view_h * world.clipper.b) / 2
207 |
208 | # --------------Mouse Above---------------------------------------
209 | # --------------Process below-------------------------------------
210 |
211 | world.process(time_passed_seconds)
212 |
213 | if selected_building == "House":
214 | selected_img = placing_house_img
215 | elif selected_building == "LumberYard":
216 | selected_img = placing_lumberyard_img
217 | elif selected_building == "Dock":
218 | selected_img = placing_dock_img
219 | elif selected_building == "Manor":
220 | selected_img = placing_manor_img
221 |
222 | # --------------Process above-------------------------------------
223 | # --------------Render Below------------------------
224 |
225 | screen.fill((0, 0, 0))
226 | world.render_all(screen, time_passed_seconds, pos)
227 |
228 | #world.grow_trees(world.baby_tree_locations)
229 |
230 | if selected_building is not None:
231 | if (pos.x > world.clipper.minimap_rect.x and pos.y > world.clipper.minimap_rect.y) or (
232 | pos.x < world.clipper.side.w + 32):
233 | pass
234 | else:
235 | if not world.test_buildable(selected_building, 0, pos):
236 | selected_img = bad_lumberyard_img
237 | blit_pos = world.get_tile_pos(pos - world.background_pos) * 32
238 | screen.blit(selected_img, ((blit_pos.x - (selected_img.get_width() - 32)) + world.background_pos.x,
239 | (blit_pos.y - (selected_img.get_height() - 32)) + world.background_pos.y))
240 |
241 | # ------------Render above----------------------------
242 | # This is for selecting-------------
243 | if draw and selected_building is None:
244 | current_mouse_pos = Vector2(*pygame.mouse.get_pos())
245 |
246 | lst = world.get_tile_array(start, ((current_mouse_pos.x - start.x) / 32, (current_mouse_pos.x - start.x) / 32))
247 | for i in lst:
248 | for j in i:
249 | j.selected = 1
250 |
251 | select_surface = pygame.Surface((abs(current_mouse_pos.x - start.x), abs(current_mouse_pos.y - start.y)))
252 | select_surface.set_alpha(25)
253 | select_surface.fill((255, 255, 255))
254 |
255 | if current_mouse_pos.x - \
256 | start.x <= 0 and current_mouse_pos.y < start.y and current_mouse_pos.x > start.x:
257 | newa = (current_mouse_pos.x - (current_mouse_pos.x - start.x), current_mouse_pos.y)
258 | screen.blit(select_surface, (newa))
259 | if current_mouse_pos.x - \
260 | start.x <= 0 and current_mouse_pos.y > start.y and current_mouse_pos.x < start.x:
261 | newa = (current_mouse_pos.x, current_mouse_pos.y - (current_mouse_pos.y - start.y))
262 | screen.blit(select_surface, (newa))
263 | if current_mouse_pos.x - \
264 | start.x > 0 and current_mouse_pos.y - start.y > 0:
265 | screen.blit(select_surface, (start))
266 | if current_mouse_pos.x - \
267 | start.x < 0 and current_mouse_pos.y - start.y < 0:
268 | screen.blit(select_surface, (current_mouse_pos))
269 | pygame.draw.rect(
270 | screen, (255, 255, 255), (start, (current_mouse_pos.x - start.x, current_mouse_pos.y - start.y)), 1)
271 | # Selecting Above------------------
272 |
273 | # --------------Render Above------------------------
274 |
275 | pygame.display.flip()
276 | pygame.display.set_caption("VillagerSim")
277 |
278 | pygame.quit()
279 |
280 | if __name__ == "__main__":
281 | run()
282 |
--------------------------------------------------------------------------------
/World.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import pygame
3 | from gametools import vector2, VoronoiMapGen, MidpointDisplacement, PertTools
4 | import math
5 | import Tile
6 | import Clips
7 | import Farmer
8 | import Lumberjack
9 | import Angler
10 | import Explorer
11 | import Arborist
12 |
13 | class World(object):
14 | """This class holds everything in the game. It also
15 | updates and renders it all each frame."""
16 |
17 | def __init__(self, tile_dimensions, screen_size):
18 | """Basic initialization.
19 |
20 | Args:
21 | tile_dimensions: The dimensions of the world in terms
22 | of tiles. default is 128x128 tiles.
23 |
24 | screen_size: The size of the window, this is used for scaling
25 | (mostly of the minimap).
26 |
27 | Returns:
28 | None
29 | """
30 |
31 | self.tile_size = 32
32 | self.w, self.h = self.world_size = (tile_dimensions[0] * self.tile_size, tile_dimensions[1] * self.tile_size)
33 | self.world_position = vector2.Vector2(-self.w / 2, -self.h / 2)
34 |
35 | self.clock = pygame.time.Clock()
36 |
37 | # Unused variables
38 | self.wood = 0
39 | self.fish = 0
40 |
41 | # Entities
42 | self.entities = {}
43 | self.buildings = {}
44 | self.entity_id = 0
45 | self.building_id = 0
46 |
47 | self.new_world(tile_dimensions)
48 | self.clipper = Clips.Clips(self, screen_size)
49 |
50 | # TODO (wazzup771@gmail.com | Nick Wayne): Not sure if these belong here either
51 | self.info_bar = pygame.image.load("Images/Entities/info_bar.png").convert()
52 | self.info_bar.set_colorkey((255, 0, 255))
53 | self.f_high = (50, 200, 50)
54 | self.f_low = (255, 0, 0)
55 | self.w_high = (0, 0, 255)
56 | self.w_low = (76, 70, 50)
57 | self.e_high = (0, 255, 0)
58 | self.e_low = (50, 50, 0)
59 |
60 | def new_world(self, array_size):
61 | """Creates a new world (including all of the entities)
62 |
63 | Args:
64 | array_size: The size of the tile array, same as tile_dimensions
65 | in the constructor.
66 |
67 | Returns:
68 | None
69 | """
70 |
71 | map_width, map_height = array_size
72 | map_generator = VoronoiMapGen.mapGen()
73 |
74 | # midpoint_generator = MidpointDisplacement.MidpointDisplacement()
75 | # mid_map = PertTools.scale_array(midpoint_generator.normalize(midpoint_generator.NewMidDis(int(math.log(map_width, 2)))), 255)
76 | # vor_map = map_generator.whole_new_updated(size=array_size, ppr=2, c1=-1, c2=1, c3=0)
77 |
78 | # combined_map = PertTools.combine_arrays(vor_map, mid_map, 0.33, 0.66)
79 |
80 | # pert_map = PertTools.scale_array(midpoint_generator.normalize(midpoint_generator.NewMidDis(int(math.log(map_width, 2)))), 255)
81 | # vor_map = map_generator.radial_drop(PertTools.pertubate(combined_map, pert_map), 1.5, 0.0)
82 | # vor_map = map_generator.radial_drop(mid_map, 1.5, 0.0)
83 |
84 |
85 | vor_map = map_generator.radial_drop(map_generator.negative(map_generator.reallyCoolFull(array_size, num_p=23)), max_scalar=1.5, min_scalar=0.0)
86 |
87 |
88 | # All grass map for testing
89 | # vor_map = [[150 for x in range(128)] for y in range(128) ]
90 |
91 | # Method without radial drop
92 | # vor_map = map_generator.negative(map_generator.reallyCoolFull(array_size, num_p=23))
93 |
94 | self.minimap_img = pygame.Surface((map_width, map_height))
95 | self.tile_array = [[0 for tile_x in range(map_width)] for tile_y in range(map_height)]
96 | self.world_surface = pygame.Surface(self.world_size, pygame.HWSURFACE)
97 |
98 | do_hard_shadow = True
99 | shadow_height = 255
100 | shadow_drop = 3
101 | for tile_x in range(map_width):
102 |
103 | for tile_y in range(map_height):
104 |
105 | color = vor_map[tile_x][tile_y]
106 |
107 | if do_hard_shadow:
108 | shaded = False
109 | if color < shadow_height and not shadow_height < 110:
110 | shaded = True
111 | shadow_height -= shadow_drop
112 |
113 | elif color >= 110 and color > shadow_height:
114 | shadow_height = color
115 | shadow_height -= shadow_drop
116 |
117 | else:
118 | shadow_height -= shadow_drop
119 |
120 | if color < 110:
121 | # Water tile
122 | new_tile = Tile.WaterTile(self, "AndrewWater")
123 |
124 | elif 120 > color >= 110:
125 | # Sand / Beach tile
126 | new_tile = Tile.BeachTile(self, "Sand")
127 |
128 | # TODO: Implement a humidity / temperature system
129 | elif 160 > color >= 120:
130 | # Grass
131 | new_tile = Tile.GrassTile(self, "MinecraftGrass")
132 |
133 | elif 170 > color >= 160:
134 | # Tree
135 | new_tile = Tile.TreePlantedTile(self, "GrassWithCenterTree")
136 |
137 | elif 190 > color >= 170:
138 | # Grass (again)
139 | new_tile = Tile.GrassTile(self, "MinecraftGrass")
140 |
141 | elif 220 > color >= 190:
142 | # Rock
143 | new_tile = Tile.SmoothStoneTile(self, "AndrewSmoothStone")
144 |
145 | else:
146 | # Snow
147 | new_tile = Tile.SnowTile(self, "MinecraftSnow")
148 |
149 | new_tile.location = vector2.Vector2(tile_x * self.tile_size, tile_y * self.tile_size)
150 |
151 | new_tile.rect.topleft = new_tile.location
152 | new_tile.color = color
153 |
154 | alph = 220 - color
155 | if 220 > color >= 190:
156 | alph = 330 - color
157 | new_tile.darkness = alph
158 |
159 | subtle_shadow = pygame.Surface((self.tile_size, self.tile_size))
160 | subtle_shadow.set_alpha(alph)
161 |
162 | if do_hard_shadow:
163 | hard_shadow = pygame.Surface((self.tile_size, self.tile_size))
164 | hard_shadow.set_alpha(128)
165 | if shaded:
166 | new_tile.img.blit(hard_shadow, (0, 0))
167 |
168 | self.world_surface.blit(new_tile.img, new_tile.location)
169 | self.world_surface.blit(subtle_shadow, new_tile.location)
170 |
171 | self.minimap_img.blit(
172 | new_tile.img.subsurface(
173 | (0, 0, 1, 1)), (tile_x, tile_y))
174 |
175 | self.minimap_img.blit(
176 | subtle_shadow.subsurface(
177 | (0, 0, 1, 1)), (tile_x, tile_y))
178 |
179 | self.tile_array[tile_y][tile_x] = new_tile
180 |
181 | self.populate()
182 |
183 | def populate(self):
184 | """Populates the world with entities.
185 |
186 | Currently just does a hard-coded a specific number of
187 | lumberjacks and farmers in the same position.
188 |
189 | Args:
190 | None
191 |
192 | Returns:
193 | None"""
194 |
195 | start = {"Lumberjack": {"count": 2,
196 | "state": "Searching",
197 | "class": Lumberjack.Lumberjack},
198 |
199 | "Angler": {"count": 1,
200 | "state": "Searching",
201 | "class": Angler.Angler},
202 |
203 | "Arborist": {"count": 1,
204 | "state": "Planting",
205 | "class": Arborist.Arborist},
206 |
207 | "Farmer": {"count": 0,
208 | "state": "Tilling",
209 | "class": Farmer.Farmer},
210 |
211 | "Explorer": {"count": 1,
212 | "state": "Exploring",
213 | "class": Explorer.Explorer}
214 | }
215 |
216 | for key in start.keys():
217 | for count in range(start[key]["count"]):
218 | new_ent = start[key]["class"](self, key)
219 | new_ent.location = vector2.Vector2(self.w / 2, self.h / 2)
220 | new_ent.brain.set_state(start[key]["state"])
221 | self.add_entity(new_ent)
222 |
223 | def add_entity(self, entity):
224 | """Maps the input entity to the entity hash table (dictionary)
225 | using the entity_id variable, then incriments entity_id.
226 |
227 | Args:
228 | entity: A GameEntity that will be added to the world
229 |
230 | Returns:
231 | None
232 | """
233 |
234 | self.entities[self.entity_id] = entity
235 | entity.id = self.entity_id
236 | self.entity_id += 1
237 |
238 | def add_building(self, building):
239 | self.buildings[self.building_id] = building
240 | building.id = self.building_id
241 | self.building_id += 1
242 |
243 | for tile_x in range(building.image.get_width()):
244 | for tile_y in range(building.image.get_height()):
245 | self.tile_array[building.location.y + tile_y][building.location.x + tile_x] = Tile.BuildingTile(self, "MinecraftGrass")
246 | self.world_surface.blit(building.image, building.location * self.tile_size)
247 |
248 | def process(self, delta):
249 | """Runs through each entity and runs their process function.
250 |
251 | Args:
252 | delta: Time passed since the last frame (in seconds)
253 |
254 | Returns:
255 | None
256 | """
257 |
258 | for entity in self.entities.values():
259 | entity.process(delta)
260 |
261 | def render(self, surface):
262 | """Blits the world_surface and all entities onto surface.
263 |
264 | Args:
265 | surface: The surface on which to blit everything
266 |
267 | Returns:
268 | None
269 | """
270 |
271 | surface.blit(self.world_surface, self.world_position)
272 |
273 | for entity in self.entities.values():
274 | entity.render(surface)
275 | if entity.active_info:
276 | self.render_info_bar(surface,entity)
277 |
278 | def render_all(self, surface):
279 | """Calls the clipper's render function, which also calls
280 | this class's render function. Used so the main file doesn't
281 | have to call the clipper.
282 |
283 | Args:
284 | surface: The Pygame.Surface on which to blit everything.
285 |
286 | delta: The time passed (in seconds) since the last frame.
287 |
288 | mouse_pos: tuple of length 2 containing the position of the mouse.
289 |
290 | Returns:
291 | None
292 | """
293 | self.clipper.render(surface)
294 |
295 | def check_minimap_update(self, mouse_pos):
296 | """This code moves the view to where the user is clicking in
297 | the minimap. Don't ask me how it works, I have no idea.
298 |
299 | Args:
300 | mouse_pos: Vector2 instance that contains the position of the mouse
301 |
302 | Returns:
303 | None
304 | """
305 |
306 | if (mouse_pos.x > self.clipper.minimap_rect.x and
307 | mouse_pos.y > self.clipper.minimap_rect.y):
308 |
309 | x_temp_1 = -self.clipper.a * (mouse_pos.x - self.clipper.minimap_rect.x)
310 | x_temp_2 = self.clipper.rect_view_w * self.clipper.a
311 | self.world_position.x = x_temp_1 + (x_temp_2 / 2)
312 |
313 | y_temp_1 = -self.clipper.b * (mouse_pos.y - self.clipper.minimap_rect.y)
314 | y_temp_2 = self.clipper.rect_view_h * self.clipper.b
315 | self.world_position.y = y_temp_1 + (y_temp_2 / 2)
316 |
317 | # TODO(wazzup771@gmail.com | Nick Wayne): This function doesn't belong in this class, perhaps the entity superclass.
318 | def render_info_bar(self, surface, entity):
319 | lst = [self.f_high, self.f_low, self.w_high, self.w_low, self.e_high, self.e_low]
320 | lst2 = [entity.food, entity.water, entity.energy]
321 | surface.blit(self.info_bar, (entity.world_location.x + 10, entity.world_location.y - 20))
322 | for i in range(3):
323 | t = lst2[i] / 100.
324 | r = self.lerp(lst[2 * i][0], lst[2 * i + 1][0], t)
325 | g = self.lerp(lst[2 * i][1], lst[2 * i + 1][1], t)
326 | b = self.lerp(lst[2 * i][2], lst[2 * i + 1][2], t)
327 | pygame.draw.rect(surface, (r, g, b),
328 | pygame.Rect((entity.world_location.x + 20, entity.world_location.y - 14 + (i * 7)),
329 | (int(40 * t), 4)))
330 |
331 | def lerp(self, v1, v2, t):
332 | return (1 - t) * v2 + t * v1
333 |
--------------------------------------------------------------------------------
/WorldGOAP.py:
--------------------------------------------------------------------------------
1 | from aitools import GoalMachine
2 |
3 | """This file will be the customized version of the goal machine for this world"""
4 |
5 | class WorldGOAP(GameMachine.GameMachine):
6 |
7 | def __init__(self, world):
8 | GameMachine.GameMachine.__init__(self)
9 | self.world = world
10 |
11 | self.expand_goal = GoalMachine.Goal("expand", 1)
12 | self.wood_goal = GoalMachine.Goal("wood", .5)
13 | self.food_goal = GoalMachine.Goal("food", .5)
14 | self.shelter_goal = GoalMachine.Goal("shelter", .75)
15 |
16 | self.add_goal(self.expand_goal)
17 | self.add_goal(self.wood_goal)
18 | self.add_goal(self.food_goal)
19 | self.add_goal(self.shelter_goal)
20 |
21 | self.spawn_lumberjack_action = GoalMachine.Action("spawn lumberjack", {"wood":-1})
22 | self.spawn_farmer_action = GoalMachine.Action("spawn farmer", {"wood":-1})
23 | self.build_house_action = GoalMachine.Action("build house", {"shelter":-1})
24 | self.build_dock_action = GoalMachine.Action("build dock", {"food":-1})
25 | self.spawn_fishing_ship_action = GoalMachine.Action("spawn fishing ship", {"food"-1})
26 |
27 | class SpawnLumberjack(GoalMachine.Action):
28 |
29 | def __init__(self, world):
30 | GoalMachine.Action.__init__("spawn lumberjack", {"wood":-1})
31 | self.world = world
32 |
33 | def execute(self):
34 | self.world.find_building("Town Center")
35 |
--------------------------------------------------------------------------------
/aitools/GoalMachine.py:
--------------------------------------------------------------------------------
1 | class GoalMachine(object):
2 | """Another method for AI, this way you can set general goals for the AI
3 | to accomplish and specific actions it can carry out, and the AI will
4 | determine which actions would make the most sense."""
5 |
6 | def __init__(self):
7 | self.discontentment = 0
8 | self.max_goal_discontentment = 10
9 | self.goals = {}
10 | self.actions = []
11 |
12 | def add_goal(self, goal):
13 | self.goals[goal.name] = goal
14 |
15 | def add_action(self, action):
16 | self.actions.append(action)
17 |
18 | def do_action(self, action):
19 | if action is not None:
20 | for effect in action.effects:
21 | self.goals[effect].necessity += action.effects[effect]
22 |
23 | for goal in self.goals:
24 | self.goals[goal].update(action.time)
25 | else:
26 | print "No action selected!"
27 |
28 | def do_reverse_action(self, action):
29 | for effect in action.effects:
30 | self.goals[effect].necessity -= action.effects[effect]
31 |
32 | for goal in self.goals:
33 | self.goals[goal].reverse_update(action.time)
34 |
35 | def calculate_discontentment(self):
36 | discontentment = 0
37 | for goal in self.goals:
38 | discontentment += (self.goals[goal].necessity * self.goals[goal].necessity)
39 |
40 | return discontentment
41 |
42 | def determine_best_action(self):
43 | """Goes through all the possible actions, and determines which would be the most effective"""
44 |
45 | lowest_discontentment = (len(self.goals) * self.max_goal_discontentment) ** 2
46 | best_action = None
47 | current_discontentment = self.calculate_discontentment()
48 |
49 | for possible_action in self.actions:
50 |
51 | self.do_action(possible_action)
52 |
53 | new_possible_discontentment = self.calculate_discontentment()
54 |
55 | if new_possible_discontentment < lowest_discontentment:# and new_possible_discontentment < current_discontentment:
56 | lowest_discontentment = new_possible_discontentment
57 | best_action = possible_action
58 |
59 | self.do_reverse_action(possible_action)
60 |
61 | """
62 | if best_action is not None:
63 | self.do_action(best_action)
64 | """
65 | return best_action
66 |
67 | class Goal(object):
68 | """One thing the AI is trying to accomplish."""
69 |
70 | def __init__(self, name, time_delta=0):
71 | """necessity is how bad the goal should be accomplished, time_delta
72 | is how much it should change over time"""
73 | self.name = name
74 | self.necessity = 0
75 | self.time_delta = time_delta
76 |
77 | def set_necessity(self, value):
78 | self.necessity = value
79 |
80 | def update(self, time_passed):
81 | self.necessity += self.time_delta * time_passed
82 |
83 | def reverse_update(self, time_passed):
84 | self.necessity -= self.time_delta * time_passed
85 |
86 | class Action(object):
87 | """One thing the AI can do to work towards it's goals."""
88 |
89 | def __init__(self, name, effects, time=0):
90 | """'effects' will be a dictionary of pairs of goal strings with
91 | values of how they will affect them. For example:
92 | {"eat": -2} will decrease the value of the "eat" goal by 2. Time
93 | is how long the action will take (all relative)"""
94 |
95 | self.name = name
96 | self.effects = effects
97 | self.time = time
98 |
99 | def set_time(self, value):
100 | self.time = time
101 |
102 | def execute(self):
103 | """Overwritable"""
104 | pass
105 |
106 | if __name__ == "__main__":
107 | gm = GoalMachine()
108 |
109 | goal1 = Goal("eat", .5)
110 | goal2 = Goal("bathroom", .5)
111 |
112 | goal1.set_necessity(2)
113 | goal2.set_necessity(2)
114 |
115 | action1 = Action("snack", {"eat":-1}, 0.25)
116 | action2 = Action("use_bathroom", {"eat":+2, "bathroom":-2}, 1)
117 | action3 = Action("do nothing", {}, .25)
118 |
119 | gm.add_goal(goal1)
120 | gm.add_goal(goal2)
121 |
122 | gm.add_action(action1)
123 | gm.add_action(action2)
124 | gm.add_action(action3)
125 |
126 | iterations = 10
127 | print "ITERATIONS: ", iterations
128 |
129 | for i in xrange(iterations):
130 | print "\nCURRENT ITERATION:", i+1
131 |
132 | for g in gm.goals:
133 | print gm.goals[g].name, gm.goals[g].necessity
134 |
135 | print "\nCurrent Discontentment:", gm.calculate_discontentment()
136 | best_action1 = gm.determine_best_action()
137 | print "Best Action would be:", best_action1.name
138 |
139 | print "Applying Best Action:"
140 | gm.do_action(best_action1)
141 |
142 | print "New discontentment:", gm.calculate_discontentment(), "\n"
143 |
144 | for g in gm.goals:
145 | print gm.goals[g].name, gm.goals[g].necessity
146 |
--------------------------------------------------------------------------------
/aitools/StateMachine.py:
--------------------------------------------------------------------------------
1 | class State(object):
2 | def __init__(self, name):
3 | self.name = name
4 |
5 | def do_actions(self):
6 | pass
7 |
8 | def check_conditions(self):
9 | pass
10 |
11 | def entry_actions(self):
12 | pass
13 |
14 | def exit_actions(self):
15 | pass
16 |
17 |
18 | class StateMachine(object):
19 | def __init__(self):
20 |
21 | self.states = {}
22 | self.active_state = None
23 |
24 | def add_state(self, state):
25 |
26 | self.states[state.name] = state
27 |
28 | def think(self):
29 |
30 | if self.active_state is None:
31 | return
32 |
33 | self.active_state.do_actions()
34 |
35 | new_state_name = self.active_state.check_conditions()
36 | if new_state_name is not None:
37 | self.set_state(new_state_name)
38 |
39 | def set_state(self, new_state_name):
40 |
41 | if self.active_state is not None:
42 | self.active_state.exit_actions()
43 |
44 | self.active_state = self.states[new_state_name]
45 | self.active_state.entry_actions()
46 |
--------------------------------------------------------------------------------
/aitools/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['GoalMachine', 'StateMachine']
2 |
--------------------------------------------------------------------------------
/gametools/ImageFuncs.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | """
4 | This is a class I wrote to handle cell-based image storage. Rather than store each image
5 | individually you store each image in one large image split up into self.cells, then use subsurfacing
6 | to get each individual image out. w and h are the individual cell width and height, as each image
7 | may take up more than one cell.
8 | """
9 |
10 |
11 | class ImageFuncs():
12 |
13 |
14 | def __init__(self, w_cell, h_cell, img):
15 | """
16 | :param w_cell: width of one cell
17 | :param h_cell: height of one cell
18 | :param img: the image to be divided into cells
19 | :return: nothing
20 | """
21 | self.w_cell = w_cell
22 | self.h_cell = h_cell
23 | self.img = img
24 | self.get_list(self.img)
25 |
26 | def get_list(self, pic):
27 | """
28 | :param pic: the picture
29 | :return: None
30 | """
31 | self.w_img, self.h_img = pic.get_size()
32 | cells = [[0 for i in range(self.w_img // self.w_cell)] for j in range(self.h_img // self.h_cell)]
33 | for i in range(self.w_img // self.w_cell):
34 | for a in range(self.h_img // self.h_cell):
35 | cells[i][a] = pic.subsurface((i*self.w_cell, a*self.h_cell, self.w_cell, self.h_cell))
36 | self.cells = cells
37 |
38 | def get_cell(self, row, column):
39 | """
40 | :param row: num of rows in cell
41 | :param column: num of columns in in the pic
42 | :return: The list of images
43 | """
44 | return self.cells[row][column]
45 |
46 | def get_image(self, x, y):
47 | """
48 | :param x: x location
49 | :param y: y location
50 | :return:
51 | """
52 | quick_image = pygame.Surface((self.w_cell, self.h_cell))
53 | quick_image.blit(self.get_cell(x, y), (0, 0))
54 | return quick_image
55 |
56 | def get_irregular_image(self, num_w, num_h, x, y):
57 | """
58 | :param num_w: number width
59 | :param num_h: number height
60 | :param x: x location
61 | :param y: y location
62 | :return: None
63 | """
64 | quick_image = pygame.Surface((self.w_cell*num_w, self.h_cell*num_h))
65 | for i in range(num_h):
66 | for g in range(num_w):
67 | quick_image.blit(self.get_cell(x+i, y+g), (i*self.w_cell, g*self.h_cell))
68 | return quick_image
69 |
70 | def get_images(self, num_images, x, y):
71 | """
72 | :param num_images: number of images
73 | :param x: x location
74 | :param y: y location
75 | :return: List of images at x,y that is number of images long
76 | """
77 | lst = []
78 | for i in range(num_images):
79 | lst.append(self.get_image(x,y))
80 | x+=1
81 | return lst
82 |
--------------------------------------------------------------------------------
/gametools/MidpointDisplacement.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | class MidpointDisplacement(object):
4 |
5 | def NewMidDis(self, N):
6 | WIDTH = HEIGHT = (2 ** N)
7 | to_return = [[0 for x in xrange(WIDTH + 1)] for y in xrange(HEIGHT + 1)]
8 |
9 | to_return[0][0] = random.random()
10 | to_return[WIDTH][0] = random.random()
11 | to_return[WIDTH][HEIGHT] = random.random()
12 | to_return[0][HEIGHT] = random.random()
13 |
14 | for r in xrange(N):
15 | for y in xrange(2 ** r):
16 | for x in xrange(2 ** r):
17 | self.diamond(to_return, r, x, y, N)
18 |
19 | # print r, "iterations done"
20 | # print "size was", ((2 ** N) / (2 ** r))
21 | # print "there were", 2 ** r, "iterations in each dimension"
22 | # print ""
23 |
24 | return to_return
25 |
26 | def rand_h(self, r):
27 | return (2 * (random.random() - 0.5)) / (2 ** (r + 1))
28 |
29 | def normalize(self, array):
30 | r_array = array
31 |
32 | min_val = r_array[0][0]
33 | max_val = r_array[0][0]
34 |
35 | for y in xrange(len(r_array)):
36 | for x in xrange(len(r_array[0])):
37 | min_val = min(r_array[x][y], min_val)
38 | max_val = max(r_array[x][y], max_val)
39 |
40 | for y in xrange(len(r_array)):
41 | for x in xrange(len(r_array[0])):
42 | r_array[x][y] -= min_val
43 | r_array[x][y] /= (max_val - min_val)
44 |
45 | return r_array
46 |
47 | def diamond(self, array, recursion_depth, iteration_x, iteration_y, N):
48 | size = ((2 ** N) / (2 ** recursion_depth))
49 | tl = array[size * iteration_x][size * iteration_y]
50 | tr = array[size * iteration_x + size][size * iteration_y]
51 | br = array[size * iteration_x + size][size * iteration_y + size]
52 | bl = array[size * iteration_x][size * iteration_y + size]
53 |
54 | array[size * iteration_x + size / 2][size * iteration_y + size / 2] = ((tl + tr + br + bl) / 4) + self.rand_h(recursion_depth + 1)
55 |
56 | # Square step
57 |
58 | mid = array[size * iteration_x + size / 2][size * iteration_y + size / 2]
59 |
60 | # top mid
61 | array[size * iteration_x + size / 2][size * iteration_y] = (tl + tr + mid) / 3 + self.rand_h(recursion_depth)
62 |
63 | # right mid
64 | array[size * iteration_x + size][size * iteration_y + size / 2] = (tr + br + mid) / 3 + self.rand_h(recursion_depth)
65 |
66 | # bottom mid
67 | array[size * iteration_x + size / 2][size * iteration_y + size] = (bl + br + mid) / 3 + self.rand_h(recursion_depth)
68 |
69 | # left mid
70 | array[size * iteration_x][size * iteration_y + size / 2] = (tl + bl + mid) / 3 + self.rand_h(recursion_depth)
71 |
72 | def square(self, array, recursion_depth, iteration, N):
73 | pass
74 |
75 |
--------------------------------------------------------------------------------
/gametools/PertTools.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Nick Jarvis'
2 |
3 | import math
4 |
5 | def combine_arrays(arr1, arr2, weight1, weight2):
6 | to_return = [[0 for i in xrange(len(arr1))] for j in xrange(len(arr1[0]))]
7 | for y in xrange(len(arr1)):
8 | for x in xrange(len(arr1[0])):
9 | to_return[x][y] = arr1[x][y] * weight1 + arr2[x][y] * weight2
10 |
11 | return to_return
12 |
13 | def clamp(val, low=0, high=255):
14 | return max(min(high, val), low)
15 |
16 | def scale_array(array, scalar):
17 | to_return = array
18 | for y in xrange(len(array)):
19 | for x in xrange(len(array[0])):
20 | to_return[x][y] = array[x][y] * scalar
21 |
22 | return to_return
23 |
24 | def pertubate(base_array, pert_array):
25 | to_return = [[0 for y in xrange(len(base_array))] for x in xrange(len(base_array[0]))]
26 | size = len(base_array) - 1
27 |
28 | magnitude = math.log(size + 1, 2) * ((size + 1) / 256)
29 |
30 | for y in xrange(len(base_array)):
31 | for x in xrange(len(base_array[0])):
32 | offset = int(((pert_array[x][y] - 128) / 128.0) * magnitude)
33 | to_return[x][y] = clamp(base_array[clamp(x + offset, high=size)][clamp(y + offset, high=size)], 0, 255)
34 |
35 | return to_return
36 |
37 |
--------------------------------------------------------------------------------
/gametools/VoronoiMapGen.py:
--------------------------------------------------------------------------------
1 | import functools
2 | import math
3 | import pygame
4 | from random import randint
5 |
6 | @functools.total_ordering
7 | class point(object):
8 |
9 | def __init__(self, pos, color=False):
10 | """Basic point, this will be used for the "feature points"
11 | these will hold their position, as well as a separate x and y
12 | variable for easy use. Also a distance variable will be assigned
13 | for when calculating the voronoi diagram"""
14 |
15 | self.pos = pos
16 | self.x = pos[0]
17 | self.y = pos[1]
18 | self.distance = 0
19 | self.color = None
20 | if color: self.color = randint(0, 255)
21 | self.current_point = None
22 |
23 | def get_distance(self, p2):
24 | """Basic distance formula. Doesn't square root everything
25 | in order to speed up the process (AKA Manhattan Distance) """
26 |
27 | try:
28 | distance = float((p2.x - self.x) ** 2) + ((p2.y - self.y) ** 2)
29 | except ZeroDivisionError:
30 | distance = 0
31 | except AttributeError:
32 | distance = 0
33 | self.distance = distance
34 | return distance
35 |
36 | def add_color(self):
37 | if randint(0, 1):
38 | self.color = randint(1, 10) * 10
39 | else:
40 | self.color = 0
41 |
42 | def __eq__(self, other):
43 | return self.x == other.x and self.y == other.y
44 |
45 | def __lt__(self, other):
46 | return self.get_distance(self.current_point) < other.get_distance(self.current_point)
47 |
48 |
49 | class mapGen:
50 |
51 | def lerp(self, c1, c2, a):
52 | return c1 + (c2 - c1) * a
53 |
54 | def whole_new(self, num_R, size=(256, 256), c1=0, c2=0, c3=0):
55 | """DEPRECATED
56 | Creates 1 image of the voronoi diagram. I only listed the first 3
57 | coefficients because that's all I will really need, but feel free
58 | to add more"""
59 |
60 | w, h = size #Very easy to use w and h instead of size[0] and size[1]
61 |
62 | toReturn = [[0 for _ in range(size[0])] for _ in range(size[1])]
63 |
64 | point_list = [point((randint(0, w), randint(0, h))) for i in range(num_R)]
65 | #Creates the random "interest" points,
66 |
67 | for y in range(h): #Do row-by-row instead of
68 | for x in range(w): #collumn-by-collumn
69 | currentPoint = point((x, y))
70 | for p in point_list:
71 | p.current_point = currentPoint
72 |
73 | point_list.sort() # sorted(point_list, key=lambda point: point.get_distance(currentPoint)) #sort the points in a new list by their distance from the current point
74 | #(new_pointlist)
75 |
76 | currentPoint.brightness = int(c1*point_list[0].distance+c2*point_list[1].distance+c3*point_list[2].distance)/(num_R*(size[0]/((512.0/size[0])*256)))
77 | #this uses the coefficients and the new list to find the brightness of the wanted pixel
78 | #the math at the end is something I came to after about a half hour of fiddling around
79 | #with values. This will keep the value at a constant and good level, and not flatten anything.
80 |
81 | #maxB = max(maxB, currentPoint.brightness)
82 | #minB = min(minB, currentPoint.brightness)
83 |
84 | clr = abs(currentPoint.brightness) #a lot of the times the values are negative!
85 | clr = min(255, clr) #Make sure we don't for some reason overflow
86 | toReturn[x][y] = clr
87 |
88 | return toReturn
89 |
90 | def whole_new_updated(self, size=(256, 256), rpd=4, ppr=3, c1=0, c2=0, c3=0):
91 | """Creates and returns an array of given size containing values calculated by a voronoi diagram.
92 |
93 | The updated version is more controlled, with regions per dimension (rpd) and points per region (ppr). The array
94 | is split up into rpd * rpd regions, while each region contains ppr interest points. These points are used along
95 | with coefficients c1, c2, and c3 to customize the array.
96 |
97 | Arguments:
98 | size:
99 | The size of the return array. This should probably just be an
100 | integer to keep the array square in the future.
101 | rpd:
102 | This is the amount of regions on each side of the diagram.
103 | A value of 4 would result in 16 regions, 4 on each side.
104 | ppr:
105 | The amount of interest points in a region. Randomly distributed
106 | c1, c2, c3:
107 | Coeffiecients that determine how the final outcome will be.
108 | A c1 of 1 and the rest 0's will result in 'bubbles', while
109 | a c1 of 1 and a c2 of -1 will result in straight lines that
110 | divide the diagram into regions
111 |
112 | Returns a 2-Dimensional array with size equal to the argument size."""
113 |
114 | w, h = size
115 | to_return = [[0 for i in range(w)] for j in range(h)]
116 | num_regions = rpd * rpd
117 | region_size = size[0] / rpd
118 | num_points = num_regions * ppr
119 |
120 | interest_points = []
121 |
122 | for region_y in range(rpd):
123 | for region_x in range(rpd):
124 |
125 | for p in range(ppr):
126 | rx = randint(region_x * region_size, (region_x + 1) * region_size)
127 | ry = randint(region_y * region_size, (region_y + 1) * region_size)
128 | interest_points.append(point((rx, ry)))
129 |
130 | max_val = 0
131 | min_val = 0
132 |
133 | for y in range(h):
134 | for x in range(w):
135 | current_point = point((x, y))
136 | for p in interest_points:
137 | p.current_point = interest_points
138 |
139 | #sort the points in a new list by their distance from the current point
140 | #new_pointlist = sorted(interest_points, key=lambda point: point.get_distance(current_point))
141 | interest_points.sort()
142 |
143 | current_point.brightness = c1 * interest_points[0].distance + \
144 | c2 * interest_points[1].distance + \
145 | c3 * interest_points[2].distance
146 |
147 | if y == x == 0:
148 | max_val = current_point.brightness
149 | min_val = current_point.brightness
150 |
151 | elif current_point.brightness > max_val:
152 | max_val = current_point.brightness
153 |
154 | elif current_point.brightness < min_val:
155 | min_val = current_point.brightness
156 |
157 | to_return[x][y] = current_point.brightness
158 |
159 | max_val -= min_val
160 | # print max_val, min_val
161 | for y in range(h):
162 | for x in range(w):
163 | to_return[x][y] -= min_val
164 |
165 | to_return[x][y] = int((to_return[x][y] / max_val) * 255)
166 |
167 | return to_return
168 |
169 | def flat(self, num_R, size=(256, 256)):
170 | """
171 | Creates 1 image of the voronoi diagram. I only listed the first 3
172 | coefficients because that's all I will really need, but feel free
173 | to add more"""
174 |
175 | w, h = size # Very easy to use w and h instead of size[0] and size[1]
176 |
177 | toReturn = [[0 for i in range(size[0])] for j in range(size[1])]
178 |
179 | point_list = [point((randint(0, w), randint(0, h)),True) for i in range(num_R)] #Creates the random "interest" points,
180 | for POINT in point_list:
181 | POINT.addColor()
182 |
183 | for y in range(h): #Do row-by-row instead of
184 | for x in range(w): #collumn-by-collumn
185 | currentPoint = point((x, y))
186 | for p in point_list:
187 | p.current_point = currentPoint
188 |
189 | point_list.sort() # = sorted(point_list, key=lambda point: point.get_distance(currentPoint)) #sort the points in a new list by their distance from the current point
190 |
191 | currentPoint.brightness = point_list[0].color
192 | clr = abs(currentPoint.brightness)
193 | clr = min(255, clr)
194 |
195 | toReturn[x][y] = clr
196 |
197 | return toReturn
198 |
199 | def lerp_two_images(self, pic1, pic2, a):
200 | w, h = len(pic1), len(pic1[0]) #pic1.get_size()
201 | surface = pygame.Surface((w, h))
202 |
203 | for y in range(h):
204 | for x in range(w):
205 | clr1 = pic1.get_at((x, y))
206 | clr2 = pic2.get_at((x, y))
207 | clrR = (clr1[0]*(1-a)+clr2[0]*a)
208 | clrG = (clr1[1]*(1-a)+clr2[1]*a)
209 | clrB = (clr1[2]*(1-a)+clr2[2]*a)
210 | try:
211 | surface.set_at((x, y), (clrR, clrG, clrB))
212 | except TypeError as e:
213 | print(clr)
214 | raise e
215 |
216 | return surface
217 |
218 | def combine_images(self, *pics):
219 | #Takes a list of images and combines them (grayscale).
220 | #All picture sizes must be of equal or less length
221 | #but it is reccomended to have the exact same size for each
222 |
223 | num_pics = len(pics)
224 | w, h= len(pics[0]), len(pics[0][0])#Again, this is very nice for keeping things quick
225 |
226 | total_map = [[0 for i in range(h)] for i in range(w)] #Create a 2D array to hold all the values
227 | for PIC in pics: #Loops through each of the given pictures
228 | for y in range(h): #Row-by-Row
229 | for x in range(w):
230 | try:
231 | total_map[x][y] += PIC[x][y] #Adds the current value at the map to the corresponding cell on the array
232 | except IndexError as err:
233 | print(x, y)
234 | print(len(total_map), len(total_map[0]))
235 | raise err
236 |
237 | to_return = [[0 for i in range(h)] for j in range(w)]
238 | for y in range(h): #Loop through again, row-by-row
239 | for x in range(w):
240 | total_map[x][y]/=num_pics #average out each cell
241 | clr = total_map[x][y] #use clr so we don't have to use 'total_map[x][y]' 3 times
242 | to_return[x][y] = clr
243 |
244 | return to_return
245 |
246 | def threshold(self, array, lower=100, upper=128):
247 | #returns a thresholded surface of the image provided
248 | #NOTE: array must have equal size dimensions
249 |
250 | w = h = len(array)
251 | toReturn = [[0 for x in range(w)] for y in range(h)]
252 | for y in range(h): #Row-by-Row
253 | for x in range(w):
254 | if lower <= array[x][y] <= upper: #Checks to see if the value is in the threshold
255 | toReturn[x][y] = 255 #Sets the pixel at that position to white if it is
256 |
257 | return toReturn
258 |
259 | def negative(self, ARRAY):
260 | w = h = len(ARRAY)
261 | toReturn = [[0 for x in range(w)]for y in range(h)]
262 | for y in range(h):
263 | for x in range(w):
264 | toReturn[x][y] = 255-ARRAY[x][y]
265 |
266 | return toReturn
267 |
268 | def radial_drop(self, array, max_scalar=1.0, min_scalar=0.5, fast=True):
269 | height, width = len(array), len(array[0])
270 | center_y, center_x = height / 2, width / 2
271 |
272 | if fast:
273 | max_dis = center_x ** 2 + center_y ** 2
274 | else:
275 | max_dis = math.sqrt(center_x ** 2 + center_y ** 2)
276 |
277 | to_return = array[:]
278 | for y in range(height):
279 | for x in range(width):
280 | if fast:
281 | t = ((x - center_x) ** 2 + (y - center_y) ** 2) / float(max_dis)
282 | else:
283 | t = math.sqrt((x - center_x) ** 2 + (y - center_y) ** 2) / max_dis
284 |
285 | to_return[x][y] *= self.lerp(max_scalar, min_scalar, t)
286 |
287 | return to_return
288 |
289 |
290 |
291 |
292 | def reallyCoolFull(self, total_size=(256,256), num_p=25):
293 | #Uses 4 (or as many as you make, but I have found this to look cool)
294 | #calls to "whole_new()" and averages them out to create one cool image
295 | #that can be used in map generation! :D
296 |
297 | pic1 = self.whole_new(num_p, total_size, c1=-1)
298 | pic2 = self.whole_new(num_p, total_size, c2=1)
299 | pic3 = self.whole_new(num_p, total_size, c3=1)
300 | pic4 = self.whole_new(num_p, total_size, c1=-1, c2=1)
301 |
302 | return self.combine_images(pic1, pic2, pic3, pic4)
303 |
304 | def full_updated(self, size=(256, 256), rpd=4, ppr=3):
305 | pic1 = self.whole_new_updated(size, rpd, ppr, c1=-1)
306 | pic2 = self.whole_new_updated(size, rpd, ppr, c2=1)
307 | pic3 = self.whole_new_updated(size, rpd, ppr, c3=1)
308 | pic4 = self.whole_new_updated(size, rpd, ppr, c1=-1, c2=1)
309 |
310 | return self.combine_images(pic1, pic2, pic3, pic4)
311 |
--------------------------------------------------------------------------------
/gametools/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['vector2', 'util', 'VoronoiMapGen', 'ImageLoader', 'ImageFuncs','ani']
2 |
--------------------------------------------------------------------------------
/gametools/ani.py:
--------------------------------------------------------------------------------
1 | class Ani(object):
2 | """
3 | Creates an animation given the cell width, height, and the image and it returns the image needed at the time passed
4 | in seconds
5 | """
6 |
7 | def __init__(self,num,counter):
8 | self.counter_max = counter
9 | self.counter = counter
10 | self.finished = False
11 | self.ani_num_max = num
12 | self.ani_num = 0
13 |
14 |
15 | def reset(self):
16 | self.counter = self.counter_max
17 | self.ani_num = 0
18 |
19 |
20 | def get_frame(self):
21 | self.counter -= 1
22 | if self.counter <= 0:
23 | self.counter = self.counter_max
24 | self.ani_num += 1
25 | if self.ani_num == self.ani_num_max:
26 | self.reset()
27 | self.finished = True
28 | return self.ani_num
29 |
30 |
31 |
--------------------------------------------------------------------------------
/gametools/util.py:
--------------------------------------------------------------------------------
1 | import math
2 |
3 | def format_number(n, accuracy=6):
4 | """Formats a number in a friendly manner
5 | (removes trailing zeros and unneccesary point.
6 | """
7 | fs = "%." + str(accuracy) + "f"
8 | str_n = fs % float(n)
9 | if '.' in str_n:
10 | str_n = str_n.rstrip('0').rstrip('.')
11 | if str_n == "-0":
12 | str_n = "0"
13 | #str_n = str_n.replace("-0", "0")
14 | return str_n
15 |
16 |
17 | def lerp(a, b, i):
18 | """Linear enterpolate from a to b."""
19 | return a + (b - a) * i
20 |
21 |
22 | def range2d(range_x, range_y):
23 | """Creates a 2D range.
24 | """
25 | range_x = list(range_x)
26 | return [(x, y) for y in range_y for x in range_x]
27 |
28 |
29 | def xrange2d(range_x, range_y):
30 | """Iterates over a 2D range.
31 | """
32 | range_x = list(range_x)
33 | for y in range_y:
34 | for x in range_x:
35 | yield (x, y)
36 |
37 |
38 | def saturate(value, low, high):
39 | return min(max(value, low), high)
40 |
41 |
42 | def is_power_of_2(n):
43 | """Returns True if a value is a power of 2."""
44 | return math.log(n, 2) % 1.0 == 0.0
45 |
46 |
47 | def next_power_of_2(n):
48 | """Returns the next power of 2 that is >= n"""
49 | return int(2 ** math.ceil(math.log(n, 2)))
50 |
51 | if __name__ == "__main__":
52 | pass
53 | #print list(xrange2d(xrange(3), xrange(3)))
54 | #print range2d(xrange(3), xrange(3))
55 | #print is_power_of_2(7)
56 | #print is_power_of_2(8)
57 | #print is_power_of_2(9)
58 | #print next_power_of_2(7)
59 |
--------------------------------------------------------------------------------
/gametools/vector2.py:
--------------------------------------------------------------------------------
1 | from math import sqrt
2 | from gametools.util import format_number
3 |
4 | class Vector2(object):
5 |
6 | __slots__ = ('_v', )
7 | _gameobjects_vector = 2
8 |
9 | def __init__(self, x=0., y=0.):
10 | """Initialise a vector
11 |
12 | @type x: number
13 | @param x: The x value (defaults to 0.), or a container of 2 values
14 | @type x: number
15 | @param y: The y value (defaults to 0.)
16 |
17 | """
18 | if hasattr(x, "__getitem__"):
19 | x, y = x
20 | self._v = [float(x), float(y)]
21 | else:
22 | self._v = [float(x), float(y)]
23 |
24 | def _get_length(self):
25 | x, y = self._v
26 | return sqrt(x * x + y * y)
27 |
28 | def _set_length(self, length):
29 | v = self._v
30 | try:
31 | x, y = v
32 | l = length / sqrt(x * x + y * y)
33 | except ZeroDivisionError:
34 | v[0] = 0.0
35 | v[1] = 0.0
36 | return self
37 | v[0] *= l
38 | v[1] *= l
39 | length = property(_get_length, _set_length, None, "Length of the vector")
40 |
41 | @classmethod
42 | def from_floats(cls, x, y):
43 | vec = cls.__new__(cls, object)
44 | vec._v = [x, y]
45 | return vec
46 |
47 | @classmethod
48 | def from_iter(cls, iterable):
49 | """Creates a Vector2 object from an iterable.
50 |
51 | @param iterable: An iterable of at least 2 numeric values
52 | """
53 | next = iter(iterable).next
54 | vec = cls.__new__(cls, object)
55 | vec._v = [float(next()), float(next())]
56 | return vec
57 |
58 | @classmethod
59 | def from_points(cls, p1, p2):
60 | """Creates a Vector2 object between two points.
61 | @param p1: First point
62 | @param p2: Second point
63 | """
64 | v = cls.__new__(cls, object)
65 | x, y = p1
66 | xx, yy = p2
67 | v._v = [float(xx - x), float(yy - y)]
68 | return v
69 |
70 | @classmethod
71 | def _from_float_sequence(cls, sequence):
72 | v = cls.__new__(cls, object)
73 | v._v = list(sequence[:2])
74 | return v
75 |
76 | def copy(self):
77 | """Returns a copy of this object."""
78 | vec = self.__new__(self.__class__, object)
79 | vec._v = self._v[:]
80 | return vec
81 |
82 | def get_x(self):
83 | return self._v[0]
84 |
85 | def set_x(self, x):
86 | try:
87 | self._v[0] = 1.0 * x
88 | except:
89 | raise TypeError("Must be a number")
90 | x = property(get_x, set_x, None, "x component.")
91 |
92 | def get_y(self):
93 | return self._v[1]
94 |
95 | def set_y(self, y):
96 | try:
97 | self._v[1] = 1.0 * y
98 | except:
99 | raise TypeError("Must be a number")
100 | y = property(get_y, set_y, None, "y component.")
101 |
102 | #u = property(get_x, set_y, None, "u component (alias for x).")
103 | #v = property(get_y, set_y, None, "v component (alias for y).")
104 |
105 | def __str__(self):
106 | x, y = self._v
107 | return "(%s, %s)" % (format_number(x), format_number(y))
108 |
109 | def __repr__(self):
110 | x, y = self._v
111 | return "Vector2(%s, %s)" % (x, y)
112 |
113 | def __iter__(self):
114 | return iter(self._v[:])
115 |
116 | def __len__(self):
117 | return 2
118 |
119 | def __getitem__(self, index):
120 | """Gets a component as though the vector were a list."""
121 | try:
122 | return self._v[index]
123 | except IndexError:
124 | raise IndexError(
125 | "There are 2 values in this object, index should be 0 or 1")
126 |
127 | def __setitem__(self, index, value):
128 | """Sets a component as though the vector were a list."""
129 |
130 | try:
131 | self._v[index] = 1.0 * value
132 | except IndexError:
133 | raise IndexError(
134 | "There are 2 values in this object, index should be 0 or 1!")
135 | except TypeError:
136 | raise TypeError("Must be a number")
137 |
138 | def __eq__(self, rhs):
139 | x, y = self._v
140 | xx, yy = rhs
141 | return x == xx and y == yy
142 |
143 | def __ne__(self, rhs):
144 | x, y = self._v
145 | xx, yy, = rhs
146 | return x != xx or y != yy
147 |
148 | def __hash__(self):
149 |
150 | return hash(self._v)
151 |
152 | def __add__(self, rhs):
153 | x, y = self._v
154 | xx, yy = rhs
155 | return Vector2.from_floats(x + xx, y + yy)
156 |
157 | def __iadd__(self, rhs):
158 | xx, yy = rhs
159 | v = self._v
160 | v[0] += xx
161 | v[1] += yy
162 | return self
163 |
164 | def __radd__(self, lhs):
165 | x, y = self._v
166 | xx, yy = lhs
167 | return self.from_floats(x + xx, y + yy)
168 |
169 | def __sub__(self, rhs):
170 | x, y = self._v
171 | xx, yy = rhs
172 | return Vector2.from_floats(x - xx, y - yy)
173 |
174 | def __rsub__(self, lhs):
175 | x, y = self._v
176 | xx, yy = lhs
177 | return self.from_floats(xx - x, yy - y)
178 |
179 | def _isub__(self, rhs):
180 | xx, yy = rhs
181 | v = self._v
182 | v[0] -= xx
183 | v[1] -= yy
184 | return self
185 |
186 | def __mul__(self, rhs):
187 | """Return the result of multiplying this vector with a
188 | scalar or a vector-list object."""
189 | x, y = self._v
190 | if hasattr(rhs, "__getitem__"):
191 | xx, yy = rhs
192 | return Vector2.from_floats(x * xx, y * yy)
193 | else:
194 | return Vector2.from_floats(x * rhs, y * rhs)
195 |
196 | def __imul__(self, rhs):
197 | """Multiplys this vector with a scalar or a vector-list object."""
198 | if hasattr(rhs, "__getitem__"):
199 | xx, yy = rhs
200 | v = self._v
201 | v[0] *= xx
202 | v[1] *= yy
203 | else:
204 | v = self._v
205 | v[0] *= rhs
206 | v[1] *= rhs
207 | return self
208 |
209 | def __rmul__(self, lhs):
210 |
211 | x, y = self._v
212 | if hasattr(lhs, "__getitem__"):
213 | xx, yy = lhs
214 | else:
215 | xx = lhs
216 | yy = lhs
217 | return self.from_floats(x * xx, y * yy)
218 |
219 | def __div__(self, rhs):
220 | """Return the result of dividing this vector by a scalar
221 | or a vector-list object.
222 | """
223 | x, y = self._v
224 | if hasattr(rhs, "__getitem__"):
225 | xx, yy, = rhs
226 | return Vector2.from_floats(x / xx, y / yy)
227 | else:
228 | return Vector2.from_floats(x / rhs, y / rhs)
229 |
230 | def __idiv__(self, rhs):
231 | """Divides this vector with a scalar or a vector-list object."""
232 | if hasattr(rhs, "__getitem__"):
233 | xx, yy = rhs
234 | v = self._v
235 | v[0] /= xx
236 | v[1] /= yy
237 | else:
238 | v = self._v
239 | v[0] /= rhs
240 | v[1] /= rhs
241 | return self
242 |
243 | def __rdiv__(self, lhs):
244 |
245 | x, y = self._v
246 | if hasattr(lhs, "__getitem__"):
247 | xx, yy = lhs
248 | else:
249 | xx = lhs
250 | yy = lhs
251 | return self.from_floats(xx / x, yy / x)
252 |
253 | def __neg__(self):
254 | """Return the negation of this vector."""
255 | x, y = self._v
256 | return Vector2.from_floats(-x, -y)
257 |
258 | def __pos__(self):
259 |
260 | return self.copy()
261 |
262 | def __nonzero__(self):
263 |
264 | x, y = self._v
265 | return bool(x or y)
266 |
267 | def __call__(self, keys):
268 |
269 | """Used to swizzle a vector.
270 |
271 | @type keys: string
272 | @param keys: A string containing a list of component names
273 | >>> vec = Vector(1, 2)
274 | >>> vec('yx')
275 | (1, 2)
276 |
277 | """
278 |
279 | ord_x = ord('x')
280 | v = self._v
281 | return tuple(v[ord(c) - ord_x] for c in keys)
282 |
283 | def as_tuple(self):
284 | """Converts this vector to a tuple.
285 |
286 | @rtype: Tuple
287 | @return: Tuple containing the vector components
288 | """
289 | return tuple(self._v)
290 |
291 | def get_length(self):
292 | """Returns the length of this vector."""
293 | x, y = self._v
294 | return sqrt(x * x + y * y)
295 | get_magnitude = get_length
296 |
297 | def normalise(self):
298 | """Normalises this vector."""
299 | v = self._v
300 | x, y = v
301 | l = sqrt(x * x + y * y)
302 | try:
303 | v[0] /= l
304 | v[1] /= l
305 | except ZeroDivisionError:
306 | v[0] = 0.
307 | v[1] = 0.
308 | return self
309 | normalize = normalise
310 |
311 | def get_normalised(self):
312 | x, y = self._v
313 | l = sqrt(x * x + y * y)
314 | return Vector2.from_floats(x / l, y / l)
315 | get_normalized = get_normalised
316 |
317 | def get_distance_to(self, p):
318 | """Returns the distance to a point.
319 |
320 | @param: A Vector2 or list-like object with at least 2 values.
321 | @return: distance
322 | """
323 | x, y = self._v
324 | xx, yy = p
325 | dx = xx - x
326 | dy = yy - y
327 | return sqrt(dx * dx + dy * dy)
328 |
329 | if __name__ == "__main__":
330 |
331 | v1 = Vector2(1, 2)
332 | #print v1('yx')
333 | #print Vector2.from_points((5, 5), (10, 10))
334 |
--------------------------------------------------------------------------------
/gametools3/MidpointDisplacement3.py:
--------------------------------------------------------------------------------
1 | #! python3
2 |
3 | __author__ = 'Nick Jarvis'
4 |
5 | import numpy as np
6 | import random
7 |
8 | v = np.random.rand(5, 5)
9 | u = np.full((5, 5), 3, dtype=np.dtype('d'))
10 |
11 | print(v * u)
12 |
--------------------------------------------------------------------------------
/gametools3/__init__.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Nick Jarvis'
2 |
--------------------------------------------------------------------------------
/misctools/NewIcon.py:
--------------------------------------------------------------------------------
1 | import pygame
2 |
3 | pygame.init()
4 |
5 | screen = pygame.display.set_mode((10, 10))
6 |
7 | red_color = (200, 50, 50)
8 | yellow_color = (128, 128, 0)
9 |
10 |
11 | class new_icon_maker(object):
12 | def __init__(self):
13 | pass
14 |
15 | def get_icon(self, big, tile, size, name):
16 | new_surface = pygame.Surface(big.get_size())
17 | x, y = big.get_size()[0]/int(size), big.get_size()[1]/int(size)
18 | for i in range(x):
19 | for a in range(y):
20 | new_surface.blit(tile, (i*size, a*size))
21 |
22 | new_surface.blit(big, (0, 0))
23 | pygame.image.save(new_surface, "Images/Buildings/%s_Icon.png"%name)
24 | return new_surface
25 |
26 | def color(self, big, tile, size, name, color):
27 | first_img = self.get_icon(big, tile, size, name)
28 |
29 | test_surface = pygame.Surface((64, 64))
30 | test_surface.set_alpha(128)
31 |
32 | if color == "RED":
33 | test_surface.fill(red_color)
34 | elif color == "SELECTED":
35 | test_surface.fill(yellow_color)
36 |
37 | final_icon = pygame.Surface((64, 64))
38 | final_icon.blit(first_img, (0, 0))
39 | final_icon.blit(test_surface, (0, 0))
40 |
41 | pygame.image.save(final_icon, "Images/Buildings/%s_%s_Icon.png"%(color, name))
42 |
43 |
44 | maker = new_icon_maker()
45 |
46 | big_img = pygame.image.load("Images/Buildings/TotalImage.png").convert().subsurface(64, 192, 64, 64)
47 | big_img.set_colorkey((255, 0, 255))
48 |
49 | tile_img = pygame.image.load("Images/Tiles/MinecraftGrass.png").convert()
50 | icon1 = maker.get_icon(big_img, tile_img, 32, "TownHall")
51 |
--------------------------------------------------------------------------------
/misctools/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['NewIcon']
2 |
--------------------------------------------------------------------------------