diff --git a/spec/building_spec.cr b/spec/building_spec.cr index 54cf767..0c13e82 100644 --- a/spec/building_spec.cr +++ b/spec/building_spec.cr @@ -10,9 +10,9 @@ describe Game::Building do bg = Game::Building.new Game::Building::Type::CrystalMiner, **{ production: Game::Production.new( ts: 20, - input: Game::Resources.new, - output: Game::Resources.new({ - Game::Resources::Type::Crystals => 100, + input: Game::ResourceBag.new, + output: Game::ResourceBag.new({ + Game::Resource::Type::Crystals => 100, }) ), } diff --git a/spec/command_spec.cr b/spec/command_spec.cr index 5937af4..1ddbc44 100644 --- a/spec/command_spec.cr +++ b/spec/command_spec.cr @@ -22,8 +22,8 @@ describe Game::Command do building = Game::Building.new Game::Building::Type::StartPoint, **{ construction: Game::Construction.new( ts: 10, - cost: Game::Resources.new({ - Game::Resources::Type::Crystals => 100, + cost: Game::ResourceBag.new({ + Game::Resource::Type::Crystals => 100, }) ), } diff --git a/spec/deposit_spec.cr b/spec/deposit_spec.cr index 83ba11c..0f3bf51 100644 --- a/spec/deposit_spec.cr +++ b/spec/deposit_spec.cr @@ -3,34 +3,34 @@ require "./spec_helper" module Game::Test describe Deposit do it "should be created fulfilled" do - dep = Deposit.new(Resources::Type::Crystals, 100) + dep = Deposit.new(Resource::Type::Crystals, 100) dep.cap.should eq 100 dep.cur.should eq 100 end it "can be created partially filled" do - dep = Deposit.new(Resources::Type::Crystals, 100, 20) + dep = Deposit.new(Resource::Type::Crystals, 100, 20) dep.cap.should eq 100 dep.cur.should eq 20 end it "should be decreased with span" do - dep = Deposit.new(Resources::Type::Crystals, 100) - dep.dec Deposit::Span.new(Resources::Type::Crystals, 20) + dep = Deposit.new(Resource::Type::Crystals, 100) + dep.dec Resource.new(Resource::Type::Crystals, 20) dep.cap.should eq 100 dep.cur.should eq 80 end it "should not be increased above capacity" do - dep = Deposit.new(Resources::Type::Crystals, 100, 20) - dep.inc Deposit::Span.new(Resources::Type::Crystals, 100) + dep = Deposit.new(Resource::Type::Crystals, 100, 20) + dep.inc Resource.new(Resource::Type::Crystals, 100) dep.cap.should eq 100 dep.cur.should eq 100 end it "should not be decreased below zero" do - dep = Deposit.new(Resources::Type::Crystals, 100) - dep.dec Deposit::Span.new(Resources::Type::Crystals, 120) + dep = Deposit.new(Resource::Type::Crystals, 100) + dep.dec Resource.new(Resource::Type::Crystals, 120) dep.cap.should eq 100 dep.cur.should eq 0 end diff --git a/spec/resources_spec.cr b/spec/resources_spec.cr index 261e60c..9d7bf88 100644 --- a/spec/resources_spec.cr +++ b/spec/resources_spec.cr @@ -1,10 +1,10 @@ require "./spec_helper" -module Test::GameResources - alias Res = Game::Resources - alias ResType = Game::Resources::Type +module Game::TestResourceBag + alias Res = ResourceBag + alias ResType = Resource::Type - describe Game::Resources do + describe ResourceBag do it "should be created from hash" do res = Res.new({ResType::Crystals => 100}) res[ResType::Crystals].should eq 100 diff --git a/src/game/building.cr b/src/game/building.cr index 2ea5d7a..5abd976 100644 --- a/src/game/building.cr +++ b/src/game/building.cr @@ -1,6 +1,6 @@ module Game class Production - def initialize(@ts : TimeSpan, @input : Resources, @output : Resources) + def initialize(@ts : TimeSpan, @input : ResourceBag, @output : ResourceBag) end getter ts @@ -9,17 +9,17 @@ module Game end class Mining - def initialize(@ts : TimeSpan, @dep : Deposit::Span) + def initialize(@ts : TimeSpan, @resource : Resource) end getter ts - getter dep + getter resource end class Construction def initialize( @ts : TimeSpan, - @cost : Resources, + @cost : ResourceBag, @requirements : Array(Building::Type) = [] of Building::Type ) end @@ -29,11 +29,11 @@ module Game getter requirements def self.immediatly - Construction.new 0, Resources.new + Construction.new 0, ResourceBag.new end def self.free(ts : TimeSpan) - Construction.new ts, Resources.new + Construction.new ts, ResourceBag.new end end diff --git a/src/game/building_factory.cr b/src/game/building_factory.cr index 79de342..3e73bd0 100644 --- a/src/game/building_factory.cr +++ b/src/game/building_factory.cr @@ -11,7 +11,7 @@ module Game Building.new Building::Type::CrystalMiner, **{ mining: Mining.new( ts: 20, - dep: Deposit::Span.new(Resources::Type::Crystals, 40) + resource: Resource.new(Resource::Type::Crystals, 40) ), } ) @@ -20,14 +20,14 @@ module Game Building.new Building::Type::CrystalRestorer, **{ construction: Construction.new( ts: 30, - cost: Resources.new({ - Resources::Type::Crystals => 100, + cost: ResourceBag.new({ + Resource::Type::Crystals => 100, }), requirements: [] of Game::Building::Type ), restoration: Mining.new( ts: 30, - dep: Deposit::Span.new(Resources::Type::Crystals, 20) + resource: Resource.new(Resource::Type::Crystals, 20) ), } ) @@ -36,18 +36,18 @@ module Game Building.new Building::Type::Terraformer, **{ construction: Construction.new( ts: 120, - cost: Resources.new({ - Resources::Type::Crystals => 300, + cost: ResourceBag.new({ + Resource::Type::Crystals => 300, }), requirements: [] of Game::Building::Type ), production: Production.new( ts: 60, - input: Resources.new({ - Resources::Type::Crystals => 50, + input: ResourceBag.new({ + Resource::Type::Crystals => 50, }), - output: Resources.new({ - Resources::Type::Terraformation => 5, + output: ResourceBag.new({ + Resource::Type::Terraformation => 5, }) ), } diff --git a/src/game/command.cr b/src/game/command.cr index a6b05bb..84c6f8c 100644 --- a/src/game/command.cr +++ b/src/game/command.cr @@ -27,47 +27,46 @@ module Game def finish(world : World) world.map.set(BuildingTile.new(@point, @building)) - # world.push(MineCommand.new(@point)) + if @building.mining + world.push(MineCommand.new(@point)) + end end end - # class MineCommand < Command - # @output : Resources | Nil + class MineCommand < Command + @holded : Resource | Nil = nil - # def initialize(@point : Point) - # end + def initialize(@point : Point) + end - # def start(world : World) : TimeSpan - # tile = world.map.get(@point).as(BuildingTile) - # building = tile.building - # production = building.production - # if !world.resources.has(production.input) - # return production.ts - # end - # target_resource = production.type - # world.resources.dec(production.input) - # @output = production.output - # production.ts - # end + def start(world : World) : TimeSpan + tile = world.map.get(@point).as(BuildingTile) + building = tile.building + mining = building.mining.as(Mining) + # deposit_tile = nearest_deposit(world, mining.resource.type) + # if deposit_tile + # @holded = deposit_tile.dep.dec(mining.resource) + # end + mining.ts + end - # def finish(world : World) - # if @output.nil? - # return - # end - # world.resources.inc(output) - # world.push(MineCommand.new(@point)) - # end + def finish(world : World) + if @holded + # world.resources.inc(@holded) + end + world.push(MineCommand.new(@point)) + end - # def desc : String - # sprintf "Build harvester site at %d,%d", @point.x, @point.y - # end + def desc : String + sprintf "Mine `smth` from %d,%d", @point.x, @point.y + end - # # private def nearest_deposit(world : World, res : Resources::Type) - # # world.map.nearest_tile @point do |tile| - # # tile.has_role(TileRole::Deposit) && tile.cur > 0 - # # end - # # end - # end + # private def nearest_deposit(world : World, res_type : Resource::Type) + # world.map.nearest_tile @point do |tile| + # tile.is_a?(DepositTile) && tile.dep.type == res_type && tile.dep.cur > 0 + # end + # end + end # class BuildCrystalHarvesterCommand < Command # BUILD_TIME = 30 diff --git a/src/game/deposit.cr b/src/game/deposit.cr index 96c42ff..622b165 100644 --- a/src/game/deposit.cr +++ b/src/game/deposit.cr @@ -1,40 +1,30 @@ -module Game - class Deposit - class Span - def initialize(@res : Resources::Type, @cap : Capacity) - end +class Game::Deposit + @cur : Capacity = 0 - getter res - getter cap - end + def initialize(@type : Resource::Type, @cap : Capacity) + @cur = @cap + end - @cur : Capacity = 0 + def initialize(@type : Resource::Type, @cap : Capacity, @cur : Capacity) + end - def initialize(@res : Resources::Type, @cap : Capacity) - @cur = @cap - end + getter type + getter cap + getter cur - def initialize(@res : Resources::Type, @cap : Capacity, @cur : Capacity) - end + def inc(resource : Resource) + check_res resource.type + @cur = Math.min(@cap, @cur + resource.amount) + end - getter res - getter cap - getter cur + def dec(resource : Resource) + check_res resource.type + @cur = Math.max(0, @cur - resource.amount) + end - def inc(span : Span) - check_res span.res - @cur = Math.min(@cap, @cur + span.cap) - end - - def dec(span : Span) - check_res span.res - @cur = Math.max(0, @cur - span.cap) - end - - private def check_res(other_res : Resources::Type) - if @res != other_res - raise ResourceMismatch.new - end + private def check_res(other_res_type : Resource::Type) + if @type != other_res_type + raise ResourceMismatch.new end end end diff --git a/src/game/resources.cr b/src/game/resources.cr index b794dc1..d2126dd 100644 --- a/src/game/resources.cr +++ b/src/game/resources.cr @@ -1,19 +1,27 @@ require "./exception" -class Game::Resources +struct Game::Resource enum Type Crystals Terraformation end - alias ResourceBag = Hash(Type, Capacity) + def initialize(@type : Type, @amount : Capacity) + end - @values : ResourceBag + getter type + getter amount +end - def initialize(vals : ResourceBag | Nil = nil) - @values = {} of Type => Capacity - Type.each { |t, v| @values[t] = 0 } - if vals.is_a?(ResourceBag) +class Game::ResourceBag + alias ResourceHash = Hash(Resource::Type, Capacity) + + @values : ResourceHash + + def initialize(vals : ResourceHash | Nil = nil) + @values = ResourceHash.new + Resource::Type.each { |t, v| @values[t] = 0 } + if vals.is_a?(ResourceHash) vals.each do |i| t, v = i @values[t] = v @@ -21,15 +29,15 @@ class Game::Resources end end - def [](t : Type) + def [](t : Resource::Type) @values.fetch(t, 0) end - def has(t : Type, value : Capacity) : Bool + def has(t : Resource::Type, value : Capacity) : Bool @values[t] >= value end - def has(vs : ResourceBag) : Bool + def has(vs : ResourceHash) : Bool vs.reduce true do |acc, entry| t = entry[0] v = entry[1] @@ -41,7 +49,7 @@ class Game::Resources has vs.to_hash end - def inc(t : Type, value : Capacity) + def inc(t : Resource::Type, value : Capacity) new_value = @values.fetch(t, 0) + value if new_value < 0 raise NotEnoughtResources.new @@ -57,11 +65,11 @@ class Game::Resources true end - def dec(t : Type, value : Capacity) + def dec(t : Resource::Type, value : Capacity) inc(t, -value) end - def to_hash : ResourceBag + def to_hash : ResourceHash @values.clone end end diff --git a/src/game/tile.cr b/src/game/tile.cr index 4449406..05d3e01 100644 --- a/src/game/tile.cr +++ b/src/game/tile.cr @@ -10,7 +10,9 @@ module Game getter cap getter cur - abstract def has_role(role : TileRole) : Bool + def has_role(role : TileRole) : Bool + false + end def letter : Char ' ' @@ -124,14 +126,9 @@ module Game end class DepositTile < Tile - def initialize(@point : Point, @res : Resources::Type, @cap : Capacity) + def initialize(@point : Point, @dep : Deposit) end - def has_role(role : TileRole) : Bool - role == TileRole::Deposit - end - - getter res - getter cap + getter dep end end diff --git a/src/game/world.cr b/src/game/world.cr index 5416312..a0c8175 100644 --- a/src/game/world.cr +++ b/src/game/world.cr @@ -5,7 +5,7 @@ class Game::World def initialize(@map : Map, @ts : TimePoint = 0_i64) @start_ts = @ts - @resources = Resources.new + @resources = ResourceBag.new @queue = Queue.new @finished = false @score = 0 @@ -41,6 +41,6 @@ class Game::World end def win? - @resources[Resources::Type::Terraformation] >= 100 + @resources[Resource::Type::Terraformation] >= 100 end end