Class: Unit

Inherits:
Object
  • Object
show all
Defined in:
lib/lib/units/unit.rb

Overview

Both capturable and movable game pieces

Direct Known Subclasses

Army, Ship, Town

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(x, y, faction, map, infopane) ⇒ Unit

Returns a new instance of Unit.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/lib/units/unit.rb', line 12

def initialize(x, y, faction, map, infopane)
  @x = x
  @y = y
  @faction = faction
  @map = map
  @infopane = infopane

  @armour_max = 1
  @armour_left = @armour_max
  @moves_max = 1
  @moves_left = @moves_max
  @cargo = [] # transported units
  @cargo_max = 0
  @function = UnitFunction.new(FUNCNONE, self)

  # Store yourself
  coords_unit = @map.get_unit(@x, @y)
  if !coords_unit
    @map.set_unit(@x, @y, self)
  else # some town has just built you
    coords_unit.cargo.insert(-1, self) # -1 = to the end
  end
end

Class Attribute Details

.map_symbolObject (readonly)

Returns the value of attribute map_symbol.



6
7
8
# File 'lib/lib/units/unit.rb', line 6

def map_symbol
  @map_symbol
end

.nameObject (readonly)

Returns the value of attribute name.



6
7
8
# File 'lib/lib/units/unit.rb', line 6

def name
  @name
end

.priceObject (readonly)

Returns the value of attribute price.



6
7
8
# File 'lib/lib/units/unit.rb', line 6

def price
  @price
end

.valueObject (readonly)

Returns the value of attribute value.



6
7
8
# File 'lib/lib/units/unit.rb', line 6

def value
  @value
end

Instance Attribute Details

#armour_leftObject (readonly)

Returns the value of attribute armour_left.



9
10
11
# File 'lib/lib/units/unit.rb', line 9

def armour_left
  @armour_left
end

#cargoObject

Returns the value of attribute cargo.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def cargo
  @cargo
end

#cargo_maxObject

Returns the value of attribute cargo_max.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def cargo_max
  @cargo_max
end

#factionObject

Returns the value of attribute faction.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def faction
  @faction
end

#functionObject

Returns the value of attribute function.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def function
  @function
end

#xObject

Returns the value of attribute x.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def x
  @x
end

#yObject

Returns the value of attribute y.



10
11
12
# File 'lib/lib/units/unit.rb', line 10

def y
  @y
end

Instance Method Details

#attack!(by_whom) ⇒ Object

Process attack targeted at this unit



60
61
62
63
# File 'lib/lib/units/unit.rb', line 60

def attack!(by_whom)
  puts PROMPT + by_whom.to_s + ' is attacking ' + to_s
  destroy! # TODO proper combat
end

#can_be_built?Boolean

Returns:

  • (Boolean)


197
198
199
# File 'lib/lib/units/unit.rb', line 197

def can_be_built?
  self.class.price > 0
end

#can_be_captured?Boolean

Returns:

  • (Boolean)


221
222
223
# File 'lib/lib/units/unit.rb', line 221

def can_be_captured?
  false
end

#can_build?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/lib/units/unit.rb', line 193

def can_build?
  false
end

#can_capture?Boolean

Returns:

  • (Boolean)


217
218
219
# File 'lib/lib/units/unit.rb', line 217

def can_capture?
  false
end

#can_fly?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/lib/units/unit.rb', line 181

def can_fly?
  false
end

#can_move?Boolean

Returns:

  • (Boolean)


177
178
179
# File 'lib/lib/units/unit.rb', line 177

def can_move?
  (can_fly? || can_sail? || can_ride?) && @moves_left > 0
end

#can_ride?Boolean

Returns:

  • (Boolean)


189
190
191
# File 'lib/lib/units/unit.rb', line 189

def can_ride?
  false
end

#can_sail?Boolean

Returns:

  • (Boolean)


185
186
187
# File 'lib/lib/units/unit.rb', line 185

def can_sail?
  false
end

#can_transport?Boolean

Returns:

  • (Boolean)


201
202
203
# File 'lib/lib/units/unit.rb', line 201

def can_transport?
  @cargo_max > 0
end

#capture!(by_whom) ⇒ Object

Process capture targeted at this unit



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/lib/units/unit.rb', line 66

def capture!(by_whom)
  unless can_be_captured?
    abort("unit.capture!(): This unit can\'t be captured")
  end

  if by_whom == @faction
    abort("unit.capture!(): This unit already belongs to faction #{@faction}")
  end

  # Add <value> to the capturing faction
  @infopane.add_score(by_whom - 1, self.class.value)
  @faction = by_whom
end

#check_movement(old_x, old_y) ⇒ Object

Process move of unit and take care of its (un)loading or start of engagement



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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
155
156
157
158
159
160
161
162
163
164
# File 'lib/lib/units/unit.rb', line 98

def check_movement(old_x, old_y)
  if @x != old_x || @y != old_y # only if it moved
    if @moves_left <= 0
      abort("unit.check_movement(): Moving unit does not have enough move points (#{@moves_left} moves)")
    end

    oldcoords_unit = @map.get_unit(old_x, old_y)
    newcoords_unit = @map.get_unit(@x, @y)

    # If there is nobody or is there friendly unit with some cargo space (and bigger cargo space)
    if !newcoords_unit || \
      (newcoords_unit.faction == @faction && \
       newcoords_unit.can_transport? && \
       @cargo_max < newcoords_unit.cargo_max && \
       !newcoords_unit.is_full?)

      # Leave old coordinates
      if oldcoords_unit == self
        @map.set_unit(old_x, old_y, nil)
      else # if you have been transported
        oldcoords_unit.cargo.delete(self)
      end

      # Get to new coordinates
      if !newcoords_unit
        @map.set_unit(@x, @y, self)
        @cargo.each { |uu|
          uu.x = @x
          uu.y = @y
        }

      else # if you are going to be transported
        newcoords_unit.cargo.insert(-1, self) # -1 = to the end
        puts PROMPT + to_s + ' got loaded into '+ newcoords_unit.to_s
        @moves_left = 1 unless newcoords_unit.can_build? # use all your left moves unless you are getting loaded into a town
      end

    else # if there already is somebody that can't transport you (enemy or full friend)
      # Stay on your original tile
      @x = old_x
      @y = old_y

      # If it was a friend unit
      if newcoords_unit.faction == @faction
        if !newcoords_unit.can_transport?
          puts PROMPT + newcoords_unit.to_s + ' can\'t transport other units'
        else
          if @cargo_max >= newcoords_unit.cargo_max
            puts PROMPT + "#{self.class.name} can\'t fit in #{newcoords_unit.class.name}"
          else # thus newcoords_unit.is_full? is true
            puts PROMPT + newcoords_unit.to_s + ' is already full'
          end
        end
      else
        # Enemy!
        newcoords_unit.engage!(self)
      end
    end
    @moves_left -= 1

    # Check if you are on an invalid type of terrain (unless transported)
    unless is_terrain_suitable?
      puts PROMPT + to_s + " found itself in a bad place"
      destroy!
    end
  end
end

#destroy!Object

Add <value> to the other faction and remove links to given unit



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/lib/units/unit.rb', line 81

def destroy!
  @armour_left = 0 # for non-attack damage

  # If you are transporting somebody, destroy them first
  @cargo.each { |uu| uu.destroy! }

  @infopane.add_score(3 - @faction - 1, self.class.value) # TODO more factions?

  if is_transported?
    coords_unit = @map.get_unit(@x, @y)
    coords_unit.cargo -= [self]
  else
    @map.set_unit(@x, @y, nil)
  end
end

#drawObject



166
167
168
169
# File 'lib/lib/units/unit.rb', line 166

def draw
  @image.draw(@x * TILESIZE, (@y + 1) * TILESIZE, ZUNIT,
              scale_x = 1, scale_y = 1, color = COLOUR[@faction])
end

#engage!(by_whom) ⇒ Object

Process engagement targeted at this unit



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/lib/units/unit.rb', line 37

def engage!(by_whom)
  if by_whom == @faction
    abort("unit.engage!(): Engaging unit is of the same faction as this one (#{@faction})")
  end

  # Can it be captured and is it without defenders?
  if can_be_captured?
    if is_transporting?
      cargo[0].attack!(by_whom)
    else # then capture it if you can
      if by_whom.can_capture?
        puts PROMPT + by_whom.to_s + ' is capturing ' + to_s
        capture!(by_whom.faction)
      else
        puts PROMPT + by_whom.to_s + ' can\'t capture other units'
      end
    end
  else
    attack!(by_whom) # uncapturable transporters can't get help from their cargo
  end
end

#function!Object



271
272
273
274
# File 'lib/lib/units/unit.rb', line 271

def function!
  ret = @function.func!(@map, @infopane)
  puts to_s + ret
end

#infoObject

Set long info string: short info string, armour, moves, function, cargo



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# File 'lib/lib/units/unit.rb', line 282

def info
  ret = to_s + ": armour #{@armour_left}/#{@armour_max}"

  if @moves_max > 0
    ret = ret + ", moves #{@moves_left}/#{@moves_max}"
  end

  ret = ret + ", #{@function.info}"

  if @cargo_max > 0
    ret = ret + ", cargo #{@cargo.size}/#{@cargo_max}"
  end

  ret
end

#is_full?Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/lib/units/unit.rb', line 205

def is_full?
   @cargo.size >= @cargo_max # just == should be enough
end

#is_terrain_suitable?Boolean

Checks if unit is on the right type of terrain (not for transported units)

Returns:

  • (Boolean)


226
227
228
229
230
231
232
233
234
235
236
# File 'lib/lib/units/unit.rb', line 226

def is_terrain_suitable?
  unless is_transported?
    case @map.tile(@x, @y).terrain
    when TILE_SEA
      return can_fly? || can_sail?
    when TILE_GROUND
      return can_fly? || can_ride?
    end
  end
  true
end

#is_transported?Boolean

Returns:

  • (Boolean)


213
214
215
# File 'lib/lib/units/unit.rb', line 213

def is_transported?
  @map.get_unit(@x, @y) != self
end

#is_transporting?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/lib/units/unit.rb', line 209

def is_transporting?
  @cargo.size > 0
end

#is_waiting_for_commands?Boolean

Returns:

  • (Boolean)


171
172
173
174
175
# File 'lib/lib/units/unit.rb', line 171

def is_waiting_for_commands?
  @faction == @infopane.faction and
  function == FUNCNONE and
  can_move?
end

#reset_moves!Object



298
299
300
# File 'lib/lib/units/unit.rb', line 298

def reset_moves!
  @moves_left = @moves_max
end

#set_function!(func, commanding_faction) ⇒ Object

Set desired function



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/lib/units/unit.rb', line 243

def set_function!(func, commanding_faction)
  # Check your neutrality
  if @faction == 0
    puts PROMPT + to_s + ": neutral units can't have functions set"
    return
  end

  # Check origin of command
  if commanding_faction != @faction
    puts PROMPT + to_s + ": this unit does not take commands from other factions"
    return
  end

  # Check your abilities
  if func == FUNCBUILD and !can_build?
    puts PROMPT + to_s + ": this unit can't build other units"
    return
  end

  # Check current function and set the new one
  if @function.func == func
    puts PROMPT + to_s + ": function is already set to #{@function.func}"
  else
    @function.func = func
    puts PROMPT + to_s + ": function set to #{@function.func}"
  end
end

#to_sObject

Set short info string: type, faction, coordinates



277
278
279
# File 'lib/lib/units/unit.rb', line 277

def to_s
  "#{self.class.name} (FAC#{@faction} #{@x}-#{@y})"
end