Class: Swarm::Map

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/swarm/map.rb

Overview

Examples:

The Map Layout

+-------------------------------------------+
|                                           |
| [0,0] [1,0] [2,0] [3,0] [4,0] [5,0] [6,0] |
|                                           |
| [0,1] [1,1] [2,1] [3,1] [4,1] [5,1] [6,1] |
|                                           |
| [0,2] [1,2] [2,2] [3,2] [4,2] [5,2] [6,2] |
|                                           |
| [0,3] [1,3] [2,3] [3,3] [4,3] [5,3] [6,3] |
|                                           |
| [0,4] [1,4] [2,4] [3,4] [4,4] [5,4] [6,4] |
|                                           |
| [0,5] [1,5] [2,5] [3,5] [4,5] [5,5] [6,5] |
|                                           |
| [0,6] [1,6] [2,6] [3,6] [4,6] [5,6] [6,6] |
|                                           |
+-------------------------------------------+

Instance Attribute Summary collapse

Instance Method Summary collapse

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

#heightInteger (readonly)

Returns the height of the Map.

Returns:

  • (Integer)

    the height of the Map.



30
31
32
# File 'lib/swarm/map.rb', line 30

def height
  @height
end

#widthInteger (readonly)

Returns the width of the Map.

Returns:

  • (Integer)

    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

Parameters:

  • x (Integer)
  • y (Integer)

Returns:



65
66
67
# File 'lib/swarm/map.rb', line 65

def [](x, y)
  @tiles.fetch(y, Array.new)[x]
end

#[]=(x, y, tile) ⇒ Tile

Parameters:

  • x (Integer)
  • y (Integer)
  • tile (Tile)

Returns:



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).

Parameters:

  • this (Tile)

    origin tile

  • that (Tile)

    destination tile

Returns:

  • (Array<Symbol, ...>)

    :north, :east, :west and/or :south



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.

Parameters:

  • tile (Tile)

    a worker or soldier

Returns:

  • (Array<Symbol, ...>)

    :north, :east, :west and/or :south

See Also:

  • Swarm::Map.{Map{Map#north}
  • Swarm::Map.{Map{Map#south}
  • Swarm::Map.{Map{Map#east}
  • Swarm::Map.{Map{Map#west}


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

#centerTile

Returns a center tile.

Returns:

  • (Tile)

    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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    column or row of tiles starting with tile headed east until the end of the map

See Also:



229
230
231
232
# File 'lib/swarm/map.rb', line 229

def east(tile)
  tiles = row(tile)
  tiles.rotate(tiles.index tile)
end

#lastTile

Returns the last tile (highest x and y value).

Returns:

  • (Tile)

    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

Parameters:

  • tile (Tile)
  • direction (Symbol)

    :north, :south, :east or :west

Returns:

  • (Boolean)

    true if the tile is moved successfully, false if it is not



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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    column or row of tiles starting with tile headed north until the end of the map

See Also:



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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    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

#sampleTile

Returns a random tile.

Returns:

  • (Tile)

    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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    column or row of tiles starting with tile headed south until the end of the map

See Also:



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

#updateObject



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.

Parameters:

Returns:

  • (Array<Tile, ...>)

    column or row of tiles starting with tile headed west until the end of the map

See Also:



235
236
237
238
# File 'lib/swarm/map.rb', line 235

def west(tile)
  tiles = row(tile).reverse
  tiles.rotate(tiles.index tile)
end