164 lines
2.5 KiB
Crystal
164 lines
2.5 KiB
Crystal
struct Point
|
|
def initialize(@x : Int32, @y : Int32)
|
|
end
|
|
|
|
def x
|
|
@x
|
|
end
|
|
|
|
def y
|
|
@y
|
|
end
|
|
|
|
def distance(p : Point) : Int32
|
|
return (p.x - @x).abs + (p.y - @y).abs
|
|
end
|
|
end
|
|
|
|
abstract class Tile
|
|
def initialize(@point : Point)
|
|
@cap = 0
|
|
@cur = 0
|
|
end
|
|
|
|
def point
|
|
@point
|
|
end
|
|
|
|
def cap
|
|
@cap
|
|
end
|
|
|
|
def cur
|
|
@cur
|
|
end
|
|
|
|
def withdraw(value)
|
|
if value >= @cur
|
|
wd = @cur
|
|
@cur = 0
|
|
return wd
|
|
else
|
|
@cur -= value
|
|
return value
|
|
end
|
|
end
|
|
|
|
def charge(value)
|
|
if value + @cur > @cap
|
|
@cur = @cap
|
|
else
|
|
@cur += value
|
|
end
|
|
end
|
|
|
|
abstract def letter : Char
|
|
end
|
|
|
|
class GrassTile < Tile
|
|
def letter : Char
|
|
'.'
|
|
end
|
|
end
|
|
|
|
class WoodTile < Tile
|
|
def initialize(@point : Point, cap : Int32)
|
|
@cap = cap
|
|
@cur = cap
|
|
end
|
|
|
|
def letter : Char
|
|
'f'
|
|
end
|
|
end
|
|
|
|
class WoodMillTile < Tile
|
|
def letter : Char
|
|
'm'
|
|
end
|
|
end
|
|
|
|
class ForesterHouseTile < Tile
|
|
def letter : Char
|
|
'h'
|
|
end
|
|
end
|
|
|
|
class Map
|
|
SIZE = 4
|
|
|
|
def initialize
|
|
@data = {} of String => Tile
|
|
(0...SIZE).each do |x|
|
|
(0...SIZE).each do |y|
|
|
self.set(GrassTile.new(Point.new(x, y)))
|
|
end
|
|
end
|
|
self.set(WoodTile.new(Point.new(1, 1), 100))
|
|
self.set(WoodTile.new(Point.new(3, 1), 200))
|
|
self.set(WoodTile.new(Point.new(2, 2), 100))
|
|
end
|
|
|
|
def get(point : Point) : Tile
|
|
@data[key(point)]
|
|
end
|
|
|
|
def set(tile : Tile)
|
|
@data[key(tile.point)] = tile
|
|
end
|
|
|
|
def set(point : Point, tile : Tile)
|
|
@data[key(point)] = tile
|
|
end
|
|
|
|
def tiles
|
|
(0...SIZE).each do |x|
|
|
(0...SIZE).each do |y|
|
|
point = Point.new(x, y)
|
|
tile = self.get(point)
|
|
yield point, tile
|
|
end
|
|
end
|
|
end
|
|
|
|
def nearest_point(point : Point, &block) : Point | Nil
|
|
p = nil
|
|
d = Int32::MAX
|
|
tiles do |tile_point, tile|
|
|
if (yield tile)
|
|
tile_dist = tile_point.distance(point)
|
|
if tile_dist < d
|
|
d = tile_dist
|
|
p = tile_point
|
|
end
|
|
end
|
|
end
|
|
p
|
|
end
|
|
|
|
def nearest_wood(point : Point) : Point | Nil
|
|
nearest_point point do |tile|
|
|
tile.letter == 'f' && tile.cur > 0
|
|
end
|
|
end
|
|
|
|
def nearest_any_wood(point : Point) : Point | Nil
|
|
nearest_point point do |tile|
|
|
tile.letter == 'f' && tile.cur < tile.cap
|
|
end
|
|
end
|
|
|
|
def print
|
|
(0...SIZE).each do |x|
|
|
(0...SIZE).each do |y|
|
|
printf "%c", @data[key(Point.new(x, y))].letter
|
|
end
|
|
printf "\n"
|
|
end
|
|
end
|
|
|
|
private def key(p : Point) : String
|
|
return sprintf "%d:%d", p.x, p.y
|
|
end
|
|
end
|