Skip to content

Commit

Permalink
Chopped trees leave wood piles
Browse files Browse the repository at this point in the history
  • Loading branch information
tredfern committed Nov 26, 2018
1 parent 1aebd1c commit 01411fb
Show file tree
Hide file tree
Showing 19 changed files with 262 additions and 22 deletions.
2 changes: 1 addition & 1 deletion ext/artemis
Submodule artemis updated 2 files
+10 −0 src/bag.lua
+7 −0 src/bag_spec.lua
28 changes: 28 additions & 0 deletions src/actions/chop_tree.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Copyright (c) 2018 Redfern, Trevor <trevorredfern@gmail.com>
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT

local systems = require "systems"
local wood_pile = require "entities.wood_pile"
local choptree = {
name = "chop_tree"
}

function choptree:new(owner, tree)
local ct = {
owner = owner,
target = tree
}
setmetatable(ct, self)
self.__index = self
return ct
end

function choptree:execute()
systems.entity_factory:create(wood_pile:new(self.target.position.x, self.target.position.y))
systems.entity_factory:remove(self.target)
self.done = true
end

return choptree
28 changes: 28 additions & 0 deletions src/actions/chop_tree_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Copyright (c) 2018 Redfern, Trevor <trevorredfern@gmail.com>
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT

describe("actions - chop_tree", function()
require "test_helpers.mock_love"
local systems = require "systems"
local actions = require "actions"
local tree = require "entities.tree"
local character = require "entities.character"
local tiny = require "ext.tiny-ecs"
tiny.world(systems.entity_factory)

it("chopping a tree turns it into a pile of wood", function()
systems.entity_factory.create = spy.new(function() end)
systems.entity_factory.remove = spy.new(function() end)
local t = tree:new(5, 5)
local c = character:new(5, 5)
local chop_tree = actions.chop_tree:new(c, t)

chop_tree:execute(0.2)
--somehow remove the old entity and replace with a new one representing wood
assert.spy(systems.entity_factory.create).was.called()
assert.spy(systems.entity_factory.remove).was.called_with(systems.entity_factory, t)
assert.is_true(chop_tree.done)
end)
end)
3 changes: 2 additions & 1 deletion src/actions/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
-- https://opensource.org/licenses/MIT

return {
move_to = require "actions.move_to"
chop_tree = require "actions.chop_tree",
move_to = require "actions.move_to",
}
5 changes: 5 additions & 0 deletions src/actions/move_to.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ function move_to:execute(dt)
local owner = self.owner
local target = self.target

if self.done or owner.position:same(target) then
self.done = true
return
end

self.progress = self.progress + dt
if self.progress >= owner.speed then
self.progress = 0
Expand Down
17 changes: 13 additions & 4 deletions src/actions/move_to_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,36 @@
-- https://opensource.org/licenses/MIT

describe("actions.move_to", function()
require "test_helpers.mock_love"
local actions = require "actions"
local components = require "components"

it("has a target position to move to", function()
local owner = { position = {x = 1, y = 3 } }
local owner = { position = components.position:new(1, 3) }
local a = actions.move_to:new(owner, {x = 3, y = 4})
assert.equals(owner, a.owner)
assert.equals(3, a.target.x)
assert.equals(4, a.target.y)
end)

it("will attempt to move the character based on it's speed to the target location", function()
local owner = { position = {x = 1, y = 3 }, speed = 0.1 }
local owner = { position = components.position:new(1, 3), speed = 0.1 }
local a = actions.move_to:new(owner, {x = 3, y = 4})
a:execute(0.1)
assert.equals(2, owner.position.x)
assert.equals(4, owner.position.y)
end)

it("will attempt to move the character based on it's speed to the target location - opposite direction", function()
local owner = { position = {x = 3, y = 4 }, speed = 0.1 }
local owner = { position = components.position:new(3, 4), speed = 0.1 }
local a = actions.move_to:new(owner, {x = 1, y = 3})
a:execute(0.1)
assert.equals(2, owner.position.x)
assert.equals(3, owner.position.y)
end)

it("will wait until enough time has passed based on character speed to move to the next tile", function()
local owner = { position = {x = 1, y = 3 }, speed = 0.3 }
local owner = { position = components.position:new(1, 3), speed = 0.3 }
local a = actions.move_to:new(owner, {x = 3, y = 4})
a:execute(0.1)
assert.equals(1, owner.position.x)
Expand All @@ -46,4 +48,11 @@ describe("actions.move_to", function()
assert.equals(4, owner.position.y)
assert.equals(0, a.progress)
end)

it("move to is done if the owner and target are the same coordinates", function()
local owner = { position = components.position:new(1, 3), speed = 0.3}
local a = actions.move_to:new(owner, { x = 1, y = 3 })
a:execute(0.3)
assert.is_true(a.done)
end)
end)
3 changes: 1 addition & 2 deletions src/entities/character.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

local tiny = require "ext.tiny-ecs"
local position = require "components.position"
local queue = require "ext.artemis.src.queue"

local character = {
is_character = true,
is_worker = true,
Expand All @@ -17,7 +17,6 @@ local character = {
function character:new(x, y)
local c = {
position = position:new(x, y),
action_queue = queue:new(),
speed = 0.2
}
setmetatable(c, self)
Expand Down
7 changes: 7 additions & 0 deletions src/entities/character_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
describe("character", function()
local character = require "entities.character"

it("is drawable", function()
local c = character:new(10, 10)
assert.is_not.equal(nil, c.position)
assert.is_not.equal(nil, c.symbol)
assert.is_not.equal(nil, c.color)
end)

it("has a filter that can find just characters", function()
local c = character:new(10, 10)
assert.is_true(character.filter(nil, c))
Expand Down
13 changes: 10 additions & 3 deletions src/entities/tasks/chopwood.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,29 @@ local chopwood = {
function chopwood:new(tree)
local c = {
target = tree,
completed = false
done = false
}
setmetatable(c, self)
self.__index = self
return c
end

function chopwood:done()
function chopwood:finish()
self.target = nil
self.completed = true
self.done = true
end

function chopwood:next_action()
if self.target.is_removed then
self:finish()
return nil
end

if self.current_worker then
if not position.same(self.current_worker.position, self.target.position) then
return actions.move_to:new(self.current_worker, self.target.position)
else
return actions.chop_tree:new(self.current_worker, self.target)
end
end
return nil
Expand Down
31 changes: 27 additions & 4 deletions src/entities/tasks/chopwood_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
-- https://opensource.org/licenses/MIT

describe("Task - Chop Wood", function()
require "test_helpers.mock_love"
local chopwood = require "entities.tasks.chopwood"
local tree = require "entities.tree"
local character = require "entities.character"

it("is flagged as a task", function()
local t = tree:new(1, 1)
Expand All @@ -17,15 +19,15 @@ describe("Task - Chop Wood", function()
local t = tree:new(12, 39)
local task = chopwood:new(t)
assert.equals(t, task.target)
assert.is_false(task.completed)
assert.is_false(task.done)
end)

it("when the task is done, the target is removed and flagged as completed", function()
local t = tree:new(32, 32)
local task = chopwood:new(t)
task:done()
task:finish()
assert.equals(nil, task.target)
assert.is_true(task.completed)
assert.is_true(task.done)
end)

it("next action is nil if no worker is assigned", function()
Expand All @@ -37,12 +39,33 @@ describe("Task - Chop Wood", function()
it("to perform the task, it first needs to move the character to the location", function()
local t = tree:new(32, 32)
local task = chopwood:new(t)
local worker = require "entities.character":new(20, 20)
local worker = character:new(20, 20)
task.current_worker = worker
local action = task:next_action()
assert.equals("move_to", action.name)
assert.equals(worker, action.owner)
assert.equals(32, action.target.x)
assert.equals(32, action.target.y)
end)

it("if the character is at the location and the tree still exists, then action is chop tree", function()
local t = tree:new(32, 32)
local task = chopwood:new(t)
local worker = character:new(32, 32)
task.current_worker = worker
local action = task:next_action()
assert.equals("chop_tree", action.name)
assert.equals(worker, action.owner)
assert.equals(t, action.target)
end)

it("after the tree is gone then the task is done", function()
local t = tree:new(32, 32)
t.is_removed = true
local task = chopwood:new(t)
local worker = character:new(32, 32)
task.current_worker = worker
task:next_action()
assert.is_true(task.done)
end)
end)
23 changes: 23 additions & 0 deletions src/entities/wood_pile.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- Copyright (c) 2018 Redfern, Trevor <trevorredfern@gmail.com>
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT

local colors = require "colors"
local components = require "components"
local wood_pile = {
symbol = "ʭ",
color = colors.golden_brown
}

function wood_pile:new(x, y)
local wp = {
position = components.position:new(x, y),
wood = 100
}
setmetatable(wp, self)
self.__index = self
return wp
end

return wood_pile
21 changes: 21 additions & 0 deletions src/entities/wood_pile_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Copyright (c) 2018 Redfern, Trevor <trevorredfern@gmail.com>
--
-- This software is released under the MIT License.
-- https://opensource.org/licenses/MIT

describe("Entity - wood_pile", function()
require "test_helpers.mock_love"
local wood_pile = require "entities.wood_pile"

it("should be drawable", function()
local wp = wood_pile:new(4, 8)
assert.not_equal(nil, wp.position)
assert.not_equal(nil, wp.color)
assert.not_equal(nil, wp.symbol)
end)

it("contains a count of the wood resources in the pile", function()
local wp = wood_pile:new(4, 5)
assert.equals(100, wp.wood)
end)
end)
5 changes: 3 additions & 2 deletions src/scenes/game.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
local Game = {}
local tiny = require "ext.tiny-ecs"
local systems = require "systems"
local world = tiny.world()
local settings = require "settings"
world:add(

local world = tiny.world(
systems.render_map,
systems.render_symbols,
systems.entity_factory,
systems.process_user_commands,
systems.assign_tasks,
systems.perform_actions
Expand Down
1 change: 1 addition & 0 deletions src/scenes/game_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe("Game", function()

it("configures systems used for updating", function()
assert.array_includes(systems.assign_tasks, game.world.systems)
assert.array_includes(systems.entity_factory, game.world.systems)
assert.array_includes(systems.perform_actions, game.world.systems)
assert.array_includes(systems.process_user_commands, game.world.systems)
end)
Expand Down
29 changes: 24 additions & 5 deletions src/systems/assign_tasks.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,33 @@ local function unassigned_worker(w)
return w.current_task == nil
end

local function assigned_worker(w)
return w.current_task ~= nil
end

function AssignTasks:update()
local w = self.workers:first(unassigned_worker)
self:check_for_completion()
self:assign_tasks()
end

function AssignTasks:check_for_completion()
local check_status = self.workers:where(assigned_worker)
for _, w in ipairs(check_status) do
if w.current_task.done then
self.world:removeEntity(w.current_task)
w.current_task = nil
end
end
end

while w ~= nil and not self.tasks:isempty() do
function AssignTasks:assign_tasks()
local check_status = self.workers:where(unassigned_worker)
for _, w in ipairs(check_status) do
local t = self.tasks:dequeue()
t.current_worker = w
w.current_task = t
w = self.workers:first(unassigned_worker)
if t then
t.current_worker = w
w.current_task = t
end
end
end

Expand Down
13 changes: 13 additions & 0 deletions src/systems/assign_tasks_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,17 @@ describe("System - Assign Tasks ", function()
AssignTasks:update()
assert.equals(nil, worker.current_task)
end)

it("removes a task if it is done and clears the worker so it's free to work on another task", function()
local worker = { is_worker = true }
local task1 = { is_task = true }
world:add(task1, worker)
world:refresh()
AssignTasks:update()
task1.done = true
AssignTasks:update()
world:refresh()
assert.equals(nil, worker.current_task)
assert.is_not.array_includes(task1, world.entities)
end)
end)
Loading

0 comments on commit 01411fb

Please sign in to comment.