From 33b8e08f8c82f552292ebf7bff7d17740b99a0c7 Mon Sep 17 00:00:00 2001 From: Anton Vakhrushev Date: Tue, 15 Oct 2019 15:21:55 +0300 Subject: [PATCH] Add produce command --- spec/command_spec.cr | 18 +++++++++++++++++ src/game/command.cr | 48 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/spec/command_spec.cr b/spec/command_spec.cr index 38f5f1f..f7c9a5e 100644 --- a/spec/command_spec.cr +++ b/spec/command_spec.cr @@ -37,6 +37,11 @@ module Game::TestCommand ts: 20, resource: Resource.new(Resource::Type::Crystals, 40), input: ResourceBag.new({Resource::Type::Crystals => 5}) + ), + production: Production.new( + ts: 20, + input: ResourceBag.new({Resource::Type::Crystals => 40}), + output: ResourceBag.new({Resource::Type::Terraformation => 20}) ) ) ) @@ -104,5 +109,18 @@ module Game::TestCommand tile = world.map.get(1, 0).as(DepositTile) tile.dep.cur.should eq 40 end + + it "should complete produce command" do + world = World.new create_map_with_resource + world.resources.inc(Resource::Type::Crystals, 100) + command = ProduceCommand.new Point.new(0, 1), once: true + time_point = (20 + 1 * 2 + 1 * 2).to_i64 + done_at = world.push command + done_at.should eq time_point + world.run time_point + # Check world resources + world.resources[Resource::Type::Crystals].should eq 60 + world.resources[Resource::Type::Terraformation].should eq 20 + end end end diff --git a/src/game/command.cr b/src/game/command.cr index a5c8d3a..69e5689 100644 --- a/src/game/command.cr +++ b/src/game/command.cr @@ -154,6 +154,54 @@ module Game end end + class ProduceCommand < Command + @holded : ResourceBag? = nil + + def initialize(@point : Point, *, @once = false) + end + + def desc : String + if @holded + sprintf "Produce at %d,%d", @point.x, @point.y + else + sprintf "Wait for resources at %d,%d", @point.x, @point.y + end + end + + def start(world : World) : TimeSpan + tile = world.map.get(@point).as(BuildingTile) + building = tile.building + production = building.production.as(Production) + if !world.resources.has(production.input) + return production.ts + end + stock_tile = nearest_stock(world) + if stock_tile + world.resources.dec production.input + @holded = production.output + production.ts + 4 * tile.point.distance(stock_tile.point) + else + production.ts + end + end + + def finish(world : World) + if @holded + world.resources.inc @holded.as(ResourceBag) + end + if !@once + world.push(ProduceCommand.new(@point)) + end + end + + private def nearest_stock(world : World) : BuildingTile? + tile = world.map.nearest_tile @point do |t| + t.is_a?(BuildingTile) && t.building.has_role Building::Role::Storehouse + end + tile.as?(BuildingTile) + end + end + # class BuildCrystalHarvesterCommand < Command # BUILD_TIME = 30