Class: Swarm::Map
Overview
Instance Attribute Summary collapse
-
#height ⇒ Integer
readonly
The
height
of theMap
. -
#width ⇒ Integer
readonly
The
width
of theMap
.
Instance Method Summary collapse
- #[](x, y) ⇒ Tile
- #[]=(x, y, tile) ⇒ Tile
-
#aggressive_moves(this, that) ⇒ Array<Symbol, ...>
Find the closest route from
this
tothat
based only on position (ignoring all obstacles betweenthis
andthat
). -
#available_moves(tile) ⇒ Array<Symbol, ...>
Find “open” (non-blocking) moves for a
worker
orsoldier
. -
#center ⇒ Tile
A center tile.
-
#column(tile) ⇒ Array<Tile, ...>
The column of tiles that the
tile
resides on. - #each(&block) ⇒ Object
-
#east(tile) ⇒ Array<Tile, ...>
column
orrow
of tiles starting withtile
headed east until the end of the map. -
#initialize(width, height, tile_width: 1, tile_height: 1) ⇒ Map
constructor
A 2 dimensional array of tiles.
-
#last ⇒ Tile
The last tile (highest
x
andy
value). -
#move(tile, direction) ⇒ Boolean
Move a
Tile
on theMap
. - #neighbors(tile) ⇒ Object
-
#north(tile) ⇒ Array<Tile, ...>
column
orrow
of tiles starting withtile
headed north until the end of the map. -
#row(tile) ⇒ Array<Tile, ...>
The row of tiles that the
tile
resides on. -
#sample ⇒ Tile
A random tile.
- #score(key) ⇒ Object
-
#south(tile) ⇒ Array<Tile, ...>
column
orrow
of tiles starting withtile
headed south until the end of the map. - #spawn(flag, percent = 0.0) ⇒ Object
- #update ⇒ Object
-
#west(tile) ⇒ Array<Tile, ...>
column
orrow
of tiles starting withtile
headed west until the end of the map.
Constructor Details
#initialize(width, height, tile_width: 1, tile_height: 1) ⇒ Map
A 2 dimensional array of tiles.
33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/swarm/map.rb', line 33 def initialize(width, height, tile_width: 1, tile_height: 1) @tiles = (0...height).step(tile_height).map.with_index do |console_y, map_y| (0...width).step(tile_width).map.with_index do |console_x, map_x| Tile.new map_x, map_y, [console_y, console_x] # reversed for Console::setpos end end @height = height / tile_height @width = width / tile_width end |
Instance Attribute Details
#height ⇒ Integer (readonly)
Returns the height
of the Map
.
30 31 32 |
# File 'lib/swarm/map.rb', line 30 def height @height end |
#width ⇒ Integer (readonly)
Returns the width
of the Map
.
27 28 29 |
# File 'lib/swarm/map.rb', line 27 def width @width end |
Instance Method Details
#[](x, y) ⇒ Tile
65 66 67 |
# File 'lib/swarm/map.rb', line 65 def [](x, y) @tiles.fetch(y, Array.new)[x] end |
#[]=(x, y, tile) ⇒ Tile
73 74 75 76 |
# File 'lib/swarm/map.rb', line 73 def []=(x, y, tile) @tiles[y] ||= Array.new @tiles[y][x] = tile end |
#aggressive_moves(this, that) ⇒ Array<Symbol, ...>
Find the closest route from this
to that
based only on position (ignoring all obstacles between this
and that
).
162 163 164 165 166 167 168 169 |
# File 'lib/swarm/map.rb', line 162 def aggressive_moves(this, that) directions = [] directions << :north if (this.y > that.y) && ((this.y - that.y) < 10) directions << :south if (that.y > this.y) && ((that.y - this.y) < 10) directions << :west if (this.x > that.x) && ((this.x - that.x) < 10) directions << :east if (that.x > this.x) && ((that.x - this.x) < 10) directions end |
#available_moves(tile) ⇒ Array<Symbol, ...>
Find “open” (non-blocking) moves for a worker
or soldier
.
180 181 182 183 184 185 186 187 188 |
# File 'lib/swarm/map.rb', line 180 def available_moves(tile) %i(north south east west).select do |direction| _, neighbor, _ = send(direction, tile) next if neighbor.nil? neighbor.player? || neighbor.empty? || (tile.queen? && neighbor.dirt?) end end |
#center ⇒ Tile
Returns a center tile.
53 54 55 |
# File 'lib/swarm/map.rb', line 53 def center @tiles[height / 2][width / 2] end |
#column(tile) ⇒ Array<Tile, ...>
Returns the column of tiles that the tile
resides on.
250 251 252 |
# File 'lib/swarm/map.rb', line 250 def column(tile) @tiles.map { |row| row[tile.x] } end |
#each(&block) ⇒ Object
48 49 50 |
# File 'lib/swarm/map.rb', line 48 def each(&block) @tiles.each { |row| row.each &block } end |
#east(tile) ⇒ Array<Tile, ...>
Returns column
or row
of tiles starting with tile
headed east until the end of the map.
229 230 231 232 |
# File 'lib/swarm/map.rb', line 229 def east(tile) tiles = row(tile) tiles.rotate(tiles.index tile) end |
#last ⇒ Tile
Returns the last tile (highest x
and y
value).
79 80 81 |
# File 'lib/swarm/map.rb', line 79 def last self[-1, -1] end |
#move(tile, direction) ⇒ Boolean
Move a Tile
on the Map
. This movement action causes a chain reaction potentially moving (or killing) tiles down the map in that same direction.
It does this by comparing each neighboring pair
tile_1 -> tile_2
tile_2 -> tile_3
tile_3 -> tile_4
And follows these rules
-
empty tiles don’t transfer movement
-
enemies block enemies
-
players are killed when touching enemies
-
enemies get squished by players
-
players get squished by queens
-
rocks block everything
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/swarm/map.rb', line 113 def move(tile, direction) tiles = send(direction, tile) move = [] tiles.each_cons(2) do |this, that| break if this.empty? # break move.clear if (tile == this) && this.enemy? && that.empty? break move.clear if this.enemy? && that.enemy? break move.clear if this.egg? && that.enemy? break move.clear if this.enemy? && that.egg? break this.destroy! if this.player? && (that.enemy? || that.egg?) break that.destroy! if (this.enemy? || this.egg?) && that.player? if (this.worker? || this.queen? || this.egg?) && tile.player? && (that.dirt? || that.rock?) this.destroy! break end if this.soldier? && tile.player? && that.rock? (neighbors(this) - neighbors(tile)).each &:worker! this.destroy! break end if this.player? && tile.queen? && !that.empty? this.destroy! break end break move.clear if that.rock? move << [that, this.type, this.age] end return if move.empty? tile.empty! move.each { |t, type, age| t.send(type, age) } end |
#neighbors(tile) ⇒ Object
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/swarm/map.rb', line 190 def neighbors(tile) [ [ 0, 1], [ 1, 0], [ 0,-1], [-1, 0], # [ 0, 0], <- self [ 1, 1], [-1,-1], [ 1,-1], [-1, 1] ].map do |x, y| self[tile.x + x, tile.y + y] end end |
#north(tile) ⇒ Array<Tile, ...>
Returns column
or row
of tiles starting with tile
headed north until the end of the map.
217 218 219 220 |
# File 'lib/swarm/map.rb', line 217 def north(tile) tiles = column(tile).reverse tiles.rotate(tiles.index tile) end |
#row(tile) ⇒ Array<Tile, ...>
Returns the row of tiles that the tile
resides on.
245 246 247 |
# File 'lib/swarm/map.rb', line 245 def row(tile) @tiles[tile.y] end |
#sample ⇒ Tile
Returns a random tile.
58 59 60 |
# File 'lib/swarm/map.rb', line 58 def sample @tiles.sample.sample end |
#score(key) ⇒ Object
83 84 85 |
# File 'lib/swarm/map.rb', line 83 def score(key) Catalog.fetch :destroyed, key, 0 end |
#south(tile) ⇒ Array<Tile, ...>
Returns column
or row
of tiles starting with tile
headed south until the end of the map.
223 224 225 226 |
# File 'lib/swarm/map.rb', line 223 def south(tile) tiles = column(tile) tiles.rotate(tiles.index tile) end |
#spawn(flag, percent = 0.0) ⇒ Object
87 88 89 90 91 |
# File 'lib/swarm/map.rb', line 87 def spawn(flag, percent = 0.0) total = ((percent.to_f / 100) * count) select(&:empty?).sample(total.to_i).each &flag end |
#update ⇒ Object
206 207 208 |
# File 'lib/swarm/map.rb', line 206 def update Console.update Catalog.flush(:changed) end |
#west(tile) ⇒ Array<Tile, ...>
Returns column
or row
of tiles starting with tile
headed west until the end of the map.
235 236 237 238 |
# File 'lib/swarm/map.rb', line 235 def west(tile) tiles = row(tile).reverse tiles.rotate(tiles.index tile) end |