178 lines
3.7 KiB
Crystal
178 lines
3.7 KiB
Crystal
require "./queue"
|
|
require "./map"
|
|
|
|
class Resources
|
|
def initialize
|
|
@wood = 0
|
|
end
|
|
|
|
def add_wood(x)
|
|
@wood += x
|
|
end
|
|
|
|
def wood
|
|
@wood
|
|
end
|
|
end
|
|
|
|
abstract class Command
|
|
abstract def start(world : World) : Int32
|
|
abstract def finish(world : World)
|
|
end
|
|
|
|
class BuildWoodMillCommand < Command
|
|
BASE_TIME = 30
|
|
|
|
def initialize(@point : Point)
|
|
end
|
|
|
|
def start(world : World) : Int32
|
|
printf " << start build mill at [%d:%d]\n", @point.x, @point.y
|
|
return BASE_TIME
|
|
end
|
|
|
|
def finish(world : World)
|
|
printf " << finish build mill at [%d,%d]\n", @point.x, @point.y
|
|
mill = WoodMillTile.new(@point)
|
|
world.map.set(mill)
|
|
world.push(GetWoodCommand.new(@point))
|
|
end
|
|
end
|
|
|
|
class GetWoodCommand < Command
|
|
BASE_TIME = 5
|
|
BASE_WOOD = 80
|
|
|
|
def initialize(@point : Point)
|
|
@wood = 0
|
|
end
|
|
|
|
def start(world : World) : Int32
|
|
wood_point = world.map.nearest_wood(@point)
|
|
if !wood_point.nil?
|
|
dist = @point.distance(wood_point)
|
|
tile = world.map.get(wood_point)
|
|
@wood = tile.withdraw(BASE_WOOD)
|
|
printf " << start cut down wood at [%d,%d] -> %d -> %d -> [%d,%d]\n",
|
|
@point.x, @point.y,
|
|
dist, @wood,
|
|
wood_point.x, wood_point.y
|
|
return BASE_TIME + 2 * dist
|
|
else
|
|
printf " << no wood tile\n"
|
|
@wood = 0
|
|
return BASE_TIME
|
|
end
|
|
end
|
|
|
|
def finish(world : World)
|
|
printf " << finish cut down wood at [%d,%d]\n", @point.x, @point.y
|
|
world.resources.add_wood(@wood)
|
|
world.push(GetWoodCommand.new(@point))
|
|
end
|
|
end
|
|
|
|
class BuildForesterHouseCommand < Command
|
|
BASE_TIME = 50
|
|
|
|
def initialize(@point : Point)
|
|
end
|
|
|
|
def start(world : World) : Int32
|
|
printf " >> start build forester house at [%d:%d]\n", @point.x, @point.y
|
|
return BASE_TIME
|
|
end
|
|
|
|
def finish(world : World)
|
|
printf " >> finish build forester house at [%d,%d]\n", @point.x, @point.y
|
|
tile = ForesterHouseTile.new(@point)
|
|
world.map.set(tile)
|
|
world.push(GrowWoodCommand.new(@point))
|
|
end
|
|
end
|
|
|
|
class GrowWoodCommand < Command
|
|
BASE_TIME = 15
|
|
BASE_WOOD = 30
|
|
|
|
@wood_point : Point | Nil
|
|
|
|
def initialize(@point : Point)
|
|
@wood_point = nil
|
|
end
|
|
|
|
def start(world : World) : Int32
|
|
wood_point = world.map.nearest_any_wood(@point)
|
|
if !wood_point.nil?
|
|
dist = @point.distance(wood_point)
|
|
@wood_point = wood_point
|
|
printf " >> start grow wood at [%d,%d] -> %d -> [%d,%d]\n",
|
|
@point.x, @point.y,
|
|
dist,
|
|
wood_point.x, wood_point.y
|
|
return BASE_TIME + 2 * dist
|
|
else
|
|
printf "no wood tile\n"
|
|
@wood = 0
|
|
return BASE_TIME
|
|
end
|
|
end
|
|
|
|
def finish(world : World)
|
|
printf " >> finish grow wood at [%d,%d]\n", @point.x, @point.y
|
|
if !@wood_point.nil?
|
|
tile = world.map.get(@wood_point.as(Point))
|
|
tile.charge(BASE_WOOD)
|
|
end
|
|
world.push(GrowWoodCommand.new(@point))
|
|
end
|
|
end
|
|
|
|
class World
|
|
def initialize
|
|
@ts = 0
|
|
@resources = Resources.new
|
|
@map = Map.new
|
|
@queue = App::CommandQueue.new
|
|
end
|
|
|
|
private def ts
|
|
@ts
|
|
end
|
|
|
|
def resources
|
|
@resources
|
|
end
|
|
|
|
def map
|
|
@map
|
|
end
|
|
|
|
def push(command : Command)
|
|
dur = command.start(self)
|
|
done_at = @ts + dur
|
|
printf "world : %d : plan `%s` at %d\n", @ts, typeof(command), done_at
|
|
@queue.push(done_at, command)
|
|
end
|
|
|
|
def run(ts : Int32)
|
|
loop do
|
|
item = @queue.pop(ts)
|
|
if item.nil?
|
|
break
|
|
end
|
|
cmd_ts, cmd = item[:ts], item[:cmd]
|
|
@ts = cmd_ts
|
|
printf "world : %d : finish `%s`\n", @ts, typeof(cmd)
|
|
cmd.finish(self)
|
|
end
|
|
end
|
|
end
|
|
|
|
w = World.new
|
|
w.map.print
|
|
w.push(BuildWoodMillCommand.new(Point.new(0, 0)))
|
|
w.push(BuildForesterHouseCommand.new(Point.new(0, 0)))
|
|
w.run(120)
|
|
printf "Wood: %d\n", w.resources.wood
|