empi 0.24 → 0.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/empi.rb +5 -2
- data/lib/lib/game_states/build_state.rb +2 -2
- data/lib/lib/game_states/play_state.rb +19 -5
- data/lib/lib/game_states/quit_state.rb +1 -1
- data/lib/lib/game_states/set_state.rb +75 -0
- data/lib/lib/game_states/welcome_state.rb +39 -18
- data/lib/lib/game_states/win_state.rb +61 -0
- data/lib/lib/units/town.rb +1 -1
- data/lib/lib/units/unit.rb +16 -15
- data/lib/lib/units/{unitFunction.rb → unit_function.rb} +5 -5
- data/lib/lib/user_interface/cursor.rb +94 -32
- data/lib/lib/user_interface/infopane.rb +1 -1
- data/lib/lib/user_interface/map.rb +56 -24
- data/lib/lib/user_interface/tile.rb +7 -3
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abe9081612cf59f547e94e98d5ee4373fab6ded9298bfb20366bc3d67725c0cc
|
4
|
+
data.tar.gz: 7f7683c7a94d512965feed1617fc3cb700851e5444862a28069b8c2ddb76cecc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: feac436c82e490b978bac742c546816879fa7c32ef3e14410023078d83b1e8d5366d3ffa7ef051442cf84d5cef728f8c7ee2f2577ddce84c7f3ef16c2661def1
|
7
|
+
data.tar.gz: 73ade95b93a6b84b509ecb88ea545aaa80babbd007586bc4d5db52dee03a79eec15c9fd18f7a4422db265398921e1ab33701bd2c2230f9a7592fdc64cae64277
|
data/lib/empi.rb
CHANGED
@@ -19,7 +19,11 @@ class GameWindow < Gosu::Window
|
|
19
19
|
height = (MAPY + 2) * TILESIZE, \
|
20
20
|
fullscreen = false)
|
21
21
|
super
|
22
|
-
|
22
|
+
|
23
|
+
# Set version name
|
24
|
+
version = '0.25'
|
25
|
+
self.caption = "Empi: Ruby Edition #{version}"
|
26
|
+
WelcomeState.instance.version = version
|
23
27
|
|
24
28
|
# Activate first state
|
25
29
|
$window = self
|
@@ -46,7 +50,6 @@ class GameWindow < Gosu::Window
|
|
46
50
|
|
47
51
|
# Draw according to current state
|
48
52
|
def draw
|
49
|
-
|
50
53
|
@button = BUTTON_PROCESSED # draw just once after each button release
|
51
54
|
unless $window.state.nil?
|
52
55
|
@state.draw
|
@@ -6,7 +6,7 @@ require_relative './play_state'
|
|
6
6
|
require_relative './../units/army'
|
7
7
|
require_relative './../units/ship'
|
8
8
|
|
9
|
-
# Game state of
|
9
|
+
# Game state of selection of the build project
|
10
10
|
class BuildState < GameState
|
11
11
|
include Singleton
|
12
12
|
|
@@ -20,7 +20,7 @@ class BuildState < GameState
|
|
20
20
|
#def before_end
|
21
21
|
#end
|
22
22
|
|
23
|
-
# Process given button
|
23
|
+
# Process given button
|
24
24
|
def update(button)
|
25
25
|
newly_selected = nil
|
26
26
|
|
@@ -2,12 +2,12 @@ require 'singleton'
|
|
2
2
|
|
3
3
|
require_relative './game_state'
|
4
4
|
require_relative './welcome_state'
|
5
|
+
require_relative './win_state'
|
5
6
|
|
6
7
|
require_relative './../user_interface/cursor'
|
7
8
|
require_relative './../user_interface/infopane'
|
8
9
|
require_relative './../user_interface/map'
|
9
10
|
|
10
|
-
|
11
11
|
XTEXT = 5
|
12
12
|
YTEXT = 5
|
13
13
|
ZTILE = 0
|
@@ -32,6 +32,7 @@ class PlayState < GameState
|
|
32
32
|
# Load new scenario or resume game
|
33
33
|
def after_start
|
34
34
|
if @desired_new_map
|
35
|
+
WinState.instance.unset_victory!
|
35
36
|
load_new_map!
|
36
37
|
help # show help after each loading of a new map
|
37
38
|
@desired_new_map = nil
|
@@ -65,7 +66,11 @@ class PlayState < GameState
|
|
65
66
|
def update(button)
|
66
67
|
case(button)
|
67
68
|
when Gosu::KbEscape then
|
68
|
-
|
69
|
+
unless WinState.instance.faction
|
70
|
+
GameState.switch!(WelcomeState.instance)
|
71
|
+
else
|
72
|
+
GameState.switch!(WinState.instance)
|
73
|
+
end
|
69
74
|
when Gosu::KbPeriod then
|
70
75
|
next_faction_turn!
|
71
76
|
when Gosu::KbH then
|
@@ -120,6 +125,14 @@ class PlayState < GameState
|
|
120
125
|
}
|
121
126
|
all_faction_units.each { |uu| uu.reset_moves!}
|
122
127
|
|
128
|
+
# Win check: current faction has lost all units
|
129
|
+
if !WinState.instance.faction and all_faction_units.empty?
|
130
|
+
WinState.instance.set_victory!(
|
131
|
+
3 - @infopane.faction, # TODO more factions?
|
132
|
+
'Annihilation', @infopane.turn, @infopane.score
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
123
136
|
# Lock the cursor to the first waiting unit
|
124
137
|
@cursor.reset!
|
125
138
|
end
|
@@ -127,9 +140,10 @@ class PlayState < GameState
|
|
127
140
|
# Printout the controls
|
128
141
|
def help
|
129
142
|
puts "-----------\n" \
|
130
|
-
"
|
131
|
-
"
|
132
|
-
"
|
143
|
+
"H: help, Esc: menu, Enter: info, " \
|
144
|
+
".: end your turn, J: switch freeroam\n" \
|
145
|
+
"QWEADZXC or arrow keys: movement, K: previous unit, L: next unit\n" \
|
146
|
+
"functions: S sentry, B build, N none\n" \
|
133
147
|
"-----------\n"
|
134
148
|
end
|
135
149
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
require_relative './game_state'
|
4
|
+
require_relative './welcome_state'
|
5
|
+
|
6
|
+
# Game state of settings screen
|
7
|
+
class SetState < GameState
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
# TODO move out?
|
11
|
+
attr_reader :settings
|
12
|
+
|
13
|
+
# What to do just after state gets activated
|
14
|
+
#def after_start
|
15
|
+
#end
|
16
|
+
|
17
|
+
# What to do just before state gets deactivated
|
18
|
+
#def before_end
|
19
|
+
#end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
super
|
23
|
+
@settings = { # TODO move out?
|
24
|
+
'axis_top' => true,
|
25
|
+
'axis_bottom' => false,
|
26
|
+
'axis_left' => true,
|
27
|
+
'axis_right' => false
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
# Process given button
|
32
|
+
def update(button)
|
33
|
+
case(button)
|
34
|
+
when Gosu::Kb1, Gosu::Kb2, Gosu::Kb3, Gosu::Kb4 then
|
35
|
+
change_setting!(button)
|
36
|
+
when Gosu::KbEscape then
|
37
|
+
GameState.switch!(WelcomeState.instance)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def draw
|
42
|
+
header_text = '
|
43
|
+
/-- /// /-/ -/-
|
44
|
+
/-- ||| /-/ |
|
45
|
+
/-- ||| | -/-'
|
46
|
+
options_text = "
|
47
|
+
1 – show top axis: #{@settings['axis_top']}
|
48
|
+
2 – show bottom axis: #{@settings['axis_bottom']}
|
49
|
+
3 – show left axis: #{@settings['axis_left']}
|
50
|
+
4 – show right axis: #{@settings['axis_right']}\n
|
51
|
+
Esc – return to menu"
|
52
|
+
warning_text = '
|
53
|
+
Warning: settings are not saved
|
54
|
+
when Empi is closed'
|
55
|
+
|
56
|
+
menu = Gosu::Image.from_text(
|
57
|
+
header_text + "\n\n\n\n\n" + options_text + "\n\n\n" + warning_text, 20)
|
58
|
+
|
59
|
+
menu.draw((3*TILESIZE) + XTEXT, (2*TILESIZE) + YTEXT, ZTEXT)
|
60
|
+
end
|
61
|
+
|
62
|
+
def change_setting!(button)
|
63
|
+
changed_setting = {
|
64
|
+
Gosu::Kb1 => 'axis_top',
|
65
|
+
Gosu::Kb2 => 'axis_bottom',
|
66
|
+
Gosu::Kb3 => 'axis_left',
|
67
|
+
Gosu::Kb4 => 'axis_right'
|
68
|
+
}[button]
|
69
|
+
|
70
|
+
old_value = @settings[changed_setting]
|
71
|
+
@settings[changed_setting] = !@settings[changed_setting] # TODO other than boolean types?
|
72
|
+
puts "setting #{changed_setting} changed from #{old_value} " \
|
73
|
+
"to #{@settings[changed_setting]}"
|
74
|
+
end
|
75
|
+
end
|
@@ -3,11 +3,15 @@ require 'singleton'
|
|
3
3
|
require_relative './game_state'
|
4
4
|
require_relative './play_state'
|
5
5
|
require_relative './quit_state'
|
6
|
+
require_relative './set_state'
|
7
|
+
require_relative './win_state'
|
6
8
|
|
7
|
-
# Game state of
|
9
|
+
# Game state of main menu
|
8
10
|
class WelcomeState < GameState
|
9
11
|
include Singleton
|
10
12
|
|
13
|
+
attr_accessor :version
|
14
|
+
|
11
15
|
# What to do just after state gets activated
|
12
16
|
#def after_start
|
13
17
|
#end
|
@@ -16,14 +20,17 @@ class WelcomeState < GameState
|
|
16
20
|
#def before_end
|
17
21
|
#end
|
18
22
|
|
19
|
-
# Process given button
|
23
|
+
# Process given button
|
20
24
|
def update(button)
|
21
25
|
case(button)
|
22
|
-
when Gosu::Kb0, Gosu::KbQ then
|
23
|
-
GameState.switch!(QuitState.instance)
|
24
26
|
when Gosu::KbEscape then
|
27
|
+
# If there is active map go either to it or to its win screen
|
25
28
|
if PlayState.instance.map
|
26
|
-
|
29
|
+
unless WinState.instance.faction
|
30
|
+
GameState.switch!(PlayState.instance)
|
31
|
+
else
|
32
|
+
GameState.switch!(WinState.instance)
|
33
|
+
end
|
27
34
|
end
|
28
35
|
when Gosu::Kb1, Gosu::Kb2, Gosu::Kb3 then
|
29
36
|
PlayState.instance.desired_new_map = {
|
@@ -32,6 +39,10 @@ class WelcomeState < GameState
|
|
32
39
|
Gosu::Kb3 => 'm03'
|
33
40
|
}[button]
|
34
41
|
GameState.switch!(PlayState.instance)
|
42
|
+
when Gosu::Kb9, Gosu::KbS then
|
43
|
+
GameState.switch!(SetState.instance)
|
44
|
+
when Gosu::Kb0, Gosu::KbQ then
|
45
|
+
GameState.switch!(QuitState.instance)
|
35
46
|
end
|
36
47
|
end
|
37
48
|
|
@@ -41,24 +52,34 @@ class WelcomeState < GameState
|
|
41
52
|
/-- ||| /-/ |
|
42
53
|
/-- ||| | -/-'
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
55
|
+
# Is there active map? Is it won?
|
56
|
+
if PlayState.instance.map
|
57
|
+
unless WinState.instance.faction
|
58
|
+
resume_text = "
|
59
|
+
Esc – resume"
|
60
|
+
else
|
61
|
+
resume_text = "
|
62
|
+
Esc – return to victory screen"
|
63
|
+
end
|
48
64
|
else
|
49
|
-
|
50
|
-
options_text = ""
|
65
|
+
resume_text = "\n"
|
51
66
|
end
|
52
67
|
|
53
|
-
options_text
|
54
|
-
1 –
|
55
|
-
2 –
|
56
|
-
3 –
|
57
|
-
|
68
|
+
options_text = "
|
69
|
+
1 – start new: Map 01
|
70
|
+
2 – start new: Map 02
|
71
|
+
3 – start new: Map 03\n
|
72
|
+
9, S – settings
|
73
|
+
0, Q – quit"
|
58
74
|
|
59
|
-
|
60
|
-
|
75
|
+
version_text = "
|
76
|
+
version #{self.version}"
|
61
77
|
|
78
|
+
menu = Gosu::Image.from_text(
|
79
|
+
header_text + "\n\n\n" +
|
80
|
+
resume_text + "\n" +
|
81
|
+
options_text + "\n\n\n\n\n\n\n\n" +
|
82
|
+
version_text, 20)
|
62
83
|
menu.draw((3*TILESIZE) + XTEXT, (2*TILESIZE) + YTEXT, ZTEXT)
|
63
84
|
end
|
64
85
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
require_relative './game_state'
|
4
|
+
require_relative './play_state'
|
5
|
+
require_relative './welcome_state'
|
6
|
+
|
7
|
+
# Game state of summary of won game
|
8
|
+
class WinState < GameState
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
attr_reader :faction
|
12
|
+
|
13
|
+
# What to do just after state gets activated
|
14
|
+
#def after_start
|
15
|
+
#end
|
16
|
+
|
17
|
+
# What to do just before state gets deactivated
|
18
|
+
#def before_end
|
19
|
+
#end
|
20
|
+
|
21
|
+
# Process given button
|
22
|
+
def update(button)
|
23
|
+
case(button)
|
24
|
+
when Gosu::KbEscape then
|
25
|
+
GameState.switch!(WelcomeState.instance)
|
26
|
+
when Gosu::KbReturn then
|
27
|
+
GameState.switch!(PlayState.instance)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def draw
|
32
|
+
winner_text = "VICTORY FOR FACTION #{@faction}"
|
33
|
+
summary_text = "Summary:
|
34
|
+
victory type: #{@type}
|
35
|
+
won on turn: #{@turn}
|
36
|
+
ending score: #{@score}"
|
37
|
+
options_text = 'Do you want to continue playing?
|
38
|
+
Enter – resume
|
39
|
+
Esc – return to menu'
|
40
|
+
|
41
|
+
win_summary = Gosu::Image.from_text(
|
42
|
+
winner_text + "\n\n\n" + summary_text + "\n\n" + options_text, 20)
|
43
|
+
win_summary.draw((2*TILESIZE) + XTEXT, (2*TILESIZE) + YTEXT, ZTEXT)
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_victory!(faction, type, turn, score)
|
47
|
+
@faction = faction
|
48
|
+
@type = type
|
49
|
+
@turn = turn
|
50
|
+
@score = score.clone # separate object is neeeded
|
51
|
+
|
52
|
+
GameState.switch!(WinState.instance)
|
53
|
+
end
|
54
|
+
|
55
|
+
def unset_victory!()
|
56
|
+
@faction = nil
|
57
|
+
@type = nil
|
58
|
+
@turn = nil
|
59
|
+
@score = nil
|
60
|
+
end
|
61
|
+
end
|
data/lib/lib/units/town.rb
CHANGED
@@ -76,7 +76,7 @@ class Town < Unit
|
|
76
76
|
# Set desired project
|
77
77
|
def set_project!(desired_project)
|
78
78
|
unless price_list.key?(desired_project)
|
79
|
-
abort("
|
79
|
+
abort("Town.set_project!(): Unknown project (#{desired_project})")
|
80
80
|
end
|
81
81
|
@parts_needed = price_list[desired_project]
|
82
82
|
|
data/lib/lib/units/unit.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require_relative './
|
1
|
+
require_relative './unit_function'
|
2
2
|
|
3
3
|
# Both capturable and movable game pieces
|
4
4
|
class Unit
|
@@ -35,8 +35,8 @@ class Unit
|
|
35
35
|
|
36
36
|
# Process engagement targeted at this unit
|
37
37
|
def engage!(by_whom)
|
38
|
-
if by_whom == @faction
|
39
|
-
abort("
|
38
|
+
if by_whom.faction == @faction
|
39
|
+
abort("Unit.engage!(): Engaging unit is of the same faction as this one (#{@faction})")
|
40
40
|
end
|
41
41
|
|
42
42
|
# Can it be captured and is it without defenders?
|
@@ -46,7 +46,7 @@ class Unit
|
|
46
46
|
else # then capture it if you can
|
47
47
|
if by_whom.can_capture?
|
48
48
|
puts PROMPT + by_whom.to_s + ' is capturing ' + to_s
|
49
|
-
capture!(by_whom
|
49
|
+
capture!(by_whom)
|
50
50
|
else
|
51
51
|
puts PROMPT + by_whom.to_s + ' can\'t capture other units'
|
52
52
|
end
|
@@ -65,16 +65,16 @@ class Unit
|
|
65
65
|
# Process capture targeted at this unit
|
66
66
|
def capture!(by_whom)
|
67
67
|
unless can_be_captured?
|
68
|
-
abort("
|
68
|
+
abort("Unit.capture!(): This unit can\'t be captured")
|
69
69
|
end
|
70
70
|
|
71
|
-
if by_whom == @faction
|
72
|
-
abort("
|
71
|
+
if by_whom.faction == @faction
|
72
|
+
abort("Unit.capture!(): This unit already belongs to faction #{@faction}")
|
73
73
|
end
|
74
74
|
|
75
75
|
# Add <value> to the capturing faction
|
76
|
-
@infopane.add_score(by_whom - 1, self.class.value)
|
77
|
-
@faction = by_whom
|
76
|
+
@infopane.add_score(by_whom.faction - 1, self.class.value)
|
77
|
+
@faction = by_whom.faction
|
78
78
|
end
|
79
79
|
|
80
80
|
# Add <value> to the other faction and remove links to given unit
|
@@ -98,7 +98,7 @@ class Unit
|
|
98
98
|
def check_movement(old_x, old_y)
|
99
99
|
if @x != old_x || @y != old_y # only if it moved
|
100
100
|
if @moves_left <= 0
|
101
|
-
abort("
|
101
|
+
abort("Unit.check_movement(): Moving unit does not have enough move points (#{@moves_left} moves)")
|
102
102
|
end
|
103
103
|
|
104
104
|
oldcoords_unit = @map.get_unit(old_x, old_y)
|
@@ -121,17 +121,18 @@ class Unit
|
|
121
121
|
# Get to new coordinates
|
122
122
|
if !newcoords_unit
|
123
123
|
@map.set_unit(@x, @y, self)
|
124
|
-
@cargo.each { |uu|
|
125
|
-
uu.x = @x
|
126
|
-
uu.y = @y
|
127
|
-
}
|
128
|
-
|
129
124
|
else # if you are going to be transported
|
130
125
|
newcoords_unit.cargo.insert(-1, self) # -1 = to the end
|
131
126
|
puts PROMPT + to_s + ' got loaded into '+ newcoords_unit.to_s
|
132
127
|
@moves_left = 1 unless newcoords_unit.can_build? # use all your left moves unless you are getting loaded into a town
|
133
128
|
end
|
134
129
|
|
130
|
+
# Update position of your cargo
|
131
|
+
@cargo.each { |uu|
|
132
|
+
uu.x = @x
|
133
|
+
uu.y = @y
|
134
|
+
}
|
135
|
+
|
135
136
|
else # if there already is somebody that can't transport you (enemy or full friend)
|
136
137
|
# Stay on your original tile
|
137
138
|
@x = old_x
|
@@ -13,7 +13,7 @@ class UnitFunction
|
|
13
13
|
"no function"
|
14
14
|
when FUNCBUILD
|
15
15
|
unless @unit.project
|
16
|
-
abort("
|
16
|
+
abort("UnitFunction.info(): No project set (" + @unit.to_s + ")")
|
17
17
|
end
|
18
18
|
"building #{@unit.project.name} (#{@unit.build_info})"
|
19
19
|
when FUNCSENTRY
|
@@ -26,7 +26,7 @@ class UnitFunction
|
|
26
26
|
# Build given unit
|
27
27
|
when FUNCBUILD
|
28
28
|
unless @unit.project
|
29
|
-
abort("
|
29
|
+
abort("UnitFunction.func!(): No project set (" + @unit.to_s + ")")
|
30
30
|
end
|
31
31
|
|
32
32
|
@unit.parts_built += 1
|
@@ -39,9 +39,9 @@ class UnitFunction
|
|
39
39
|
@unit.project.new(@unit.x, @unit.y, @unit.faction, map, infopane)
|
40
40
|
end
|
41
41
|
|
42
|
-
# Wake when enemies are nearby
|
42
|
+
# Wake when enemies are nearby (checking just map units is enough)
|
43
43
|
when FUNCSENTRY
|
44
|
-
units_around = map.all_units.select { |uu|
|
44
|
+
units_around = map.all_units(0,0).select { |uu|
|
45
45
|
(uu.x - @unit.x).abs <= 1 &&
|
46
46
|
(uu.y - @unit.y).abs <= 1 &&
|
47
47
|
uu.faction != @unit.faction
|
@@ -55,7 +55,7 @@ class UnitFunction
|
|
55
55
|
end
|
56
56
|
|
57
57
|
unless ret
|
58
|
-
abort("
|
58
|
+
abort("UnitFunction.func!(): Functionable unit didn't function (" + @unit.to_s + ")")
|
59
59
|
end
|
60
60
|
|
61
61
|
ret
|
@@ -15,7 +15,7 @@ class Cursor
|
|
15
15
|
|
16
16
|
# Give to Infopane link to yourself (for freeroam marker)
|
17
17
|
if !@infopane
|
18
|
-
abort("Cursor.initialize
|
18
|
+
abort("Cursor.initialize(): Infopane is not set")
|
19
19
|
end
|
20
20
|
@infopane.cursor = self
|
21
21
|
end
|
@@ -53,6 +53,10 @@ class Cursor
|
|
53
53
|
# The rest
|
54
54
|
when Gosu::KbJ, Gosu::KB_NUMPAD_0 then
|
55
55
|
switch_freeroam!
|
56
|
+
when Gosu::KbK, Gosu::KB_NUMPAD_MINUS then
|
57
|
+
select_other_unit!(false)
|
58
|
+
when Gosu::KbL, Gosu::KB_NUMPAD_PLUS then
|
59
|
+
select_other_unit!(true)
|
56
60
|
when Gosu::KbReturn, Gosu::KB_NUMPAD_5 then
|
57
61
|
info
|
58
62
|
end
|
@@ -65,11 +69,11 @@ class Cursor
|
|
65
69
|
@image.draw(@x * TILESIZE, (@y + 1) * TILESIZE, ZCURSOR)
|
66
70
|
end
|
67
71
|
|
68
|
-
# Move to coordinates of unit the cursor is locked to
|
72
|
+
# Move to coordinates of map unit the cursor is locked to
|
69
73
|
def warp_to_locked!()
|
70
|
-
@x = @
|
71
|
-
@y = @
|
72
|
-
@
|
74
|
+
@x = @locked_unit.x
|
75
|
+
@y = @locked_unit.y
|
76
|
+
@selected_unit = @locked_unit
|
73
77
|
end
|
74
78
|
|
75
79
|
# Move by given change of coordinates
|
@@ -77,39 +81,39 @@ class Cursor
|
|
77
81
|
if freeroam
|
78
82
|
@x += xx
|
79
83
|
@y += yy
|
80
|
-
@
|
84
|
+
@selected_unit = @map.get_unit(@x, @y)
|
81
85
|
# TODO show some basic tile info in infopane
|
82
86
|
else
|
83
87
|
check_unit
|
84
88
|
|
85
89
|
# Move the unit first
|
86
|
-
@
|
87
|
-
@
|
88
|
-
@
|
90
|
+
@locked_unit.x += xx
|
91
|
+
@locked_unit.y += yy
|
92
|
+
@locked_unit.check_movement(@x, @y) # cursor coordinates work like old_x, old_y
|
89
93
|
|
90
94
|
# Is the unit still alive?
|
91
|
-
if @
|
95
|
+
if @locked_unit.armour_left > 0
|
92
96
|
warp_to_locked! # whether it moved or not
|
93
97
|
else
|
94
98
|
# It got destroyed so clear last links then so that (object of)
|
95
99
|
# given unit can be truly destroyed
|
96
|
-
@
|
97
|
-
@
|
100
|
+
@selected_unit = nil
|
101
|
+
@locked_unit = nil
|
98
102
|
end
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
102
|
-
# Tries to set function <func> to
|
106
|
+
# Tries to set function <func> to selected unit
|
103
107
|
def set_function_to_unit(func)
|
104
108
|
check_unit
|
105
109
|
|
106
|
-
if @
|
107
|
-
@
|
110
|
+
if @selected_unit
|
111
|
+
@selected_unit.set_function!(func, @infopane.faction)
|
108
112
|
|
109
113
|
# Update infopane with the new (possibly changed) state
|
110
114
|
# (visible only in freeroam mode as in locked one the infopane is
|
111
115
|
# overwritten as cursor either jumps away or switches to freeroam mode)
|
112
|
-
@infopane.text = @
|
116
|
+
@infopane.text = @selected_unit.info
|
113
117
|
else
|
114
118
|
puts "no unit to set that function to (at #{@x}-#{@y})"
|
115
119
|
end
|
@@ -119,19 +123,19 @@ class Cursor
|
|
119
123
|
def reset!
|
120
124
|
@freeroam = true
|
121
125
|
switch_freeroam!
|
122
|
-
@
|
123
|
-
@
|
126
|
+
@selected_unit = nil
|
127
|
+
@locked_unit = nil
|
124
128
|
to_next_unit!
|
125
129
|
end
|
126
130
|
|
127
131
|
# Find next unit which is still waiting for commands and lock to it
|
128
|
-
# (
|
132
|
+
# (selected -> last locked to -> next waiting) or switch (back) to freeroaming
|
129
133
|
def to_next_unit!
|
130
|
-
if @
|
134
|
+
if @selected_unit and @selected_unit.is_waiting_for_commands?
|
131
135
|
# Lock to such unit (though it may have already been locked)
|
132
|
-
@
|
136
|
+
@locked_unit = @selected_unit
|
133
137
|
else
|
134
|
-
unless @
|
138
|
+
unless @locked_unit and @locked_unit.is_waiting_for_commands?
|
135
139
|
waiting = @map.all_units.select { |uu| uu.is_waiting_for_commands? }
|
136
140
|
|
137
141
|
# Are there still some units of active faction waiting for commands?
|
@@ -141,7 +145,8 @@ class Cursor
|
|
141
145
|
return
|
142
146
|
end
|
143
147
|
|
144
|
-
|
148
|
+
# Pick the first waiting unit (leftmost of topmosts)
|
149
|
+
@locked_unit = waiting[0]
|
145
150
|
end
|
146
151
|
end
|
147
152
|
|
@@ -149,11 +154,68 @@ class Cursor
|
|
149
154
|
info unless @info_stopped # due to switching out of the play game state
|
150
155
|
end
|
151
156
|
|
152
|
-
#
|
153
|
-
|
157
|
+
# Skip or cycle units, depending on cursor mode
|
158
|
+
def select_other_unit!(search_forward)
|
159
|
+
unless @freeroam
|
160
|
+
skip_to_other_unit!(search_forward)
|
161
|
+
else
|
162
|
+
cycle_to_other_unit!(search_forward)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Skip from selected unit waiting for commands to the next/previous waiting one
|
167
|
+
def skip_to_other_unit!(search_forward = true)
|
168
|
+
if @freeroam
|
169
|
+
abort("Cursor.skip_to_other_unit!(): " \
|
170
|
+
"skipping to #{ search_forward ? 'next' : 'previous'} " \
|
171
|
+
"unit works only in locked mode, not in freeroam one")
|
172
|
+
end
|
173
|
+
|
174
|
+
waiting = @map.all_units.select { |uu| uu.is_waiting_for_commands? }
|
175
|
+
|
176
|
+
# Pick the previous/next waiting unit, relative to the current one
|
177
|
+
# (picking the previous of the first results in index -1 which is the last
|
178
|
+
# so there it is fine but taking the next of the last would go out of range)
|
179
|
+
current_index = waiting.index(@selected_unit)
|
180
|
+
other_index = search_forward ? current_index + 1 : current_index - 1
|
181
|
+
other_index = 0 if other_index >= waiting.size # == would be enough
|
182
|
+
|
183
|
+
@locked_unit = waiting[other_index]
|
184
|
+
warp_to_locked! # so that to_next_unit!() doesn't stay at @selected_unit
|
185
|
+
end
|
186
|
+
|
187
|
+
# Cycle from selected unit to the next/previous local one
|
188
|
+
def cycle_to_other_unit!(search_forward = true)
|
189
|
+
unless @freeroam
|
190
|
+
abort("Cursor.cycle_to_other_unit!():" \
|
191
|
+
"cycling to #{ search_forward ? 'next' : 'previous'} " \
|
192
|
+
"unit works only in freeroam mode, not in locked one")
|
193
|
+
end
|
194
|
+
|
195
|
+
unless @selected_unit
|
196
|
+
@infopane.text = ''
|
197
|
+
puts "no units to cycle through (at #{@x}-#{@y})"
|
198
|
+
return
|
199
|
+
end
|
200
|
+
|
201
|
+
local_pile = @map.all_units_from_tile(@x, @y)
|
202
|
+
|
203
|
+
# Pick the previous/next local unit, relative to the current one
|
204
|
+
# (picking the previous of the first results in index -1 which is the last
|
205
|
+
# so there it is fine but taking the next of the last would go out of range)
|
206
|
+
current_index = local_pile.index(@selected_unit)
|
207
|
+
other_index = search_forward ? current_index + 1 : current_index - 1
|
208
|
+
other_index = 0 if other_index >= local_pile.size # == would be enough
|
209
|
+
|
210
|
+
@selected_unit = local_pile[other_index]
|
211
|
+
info
|
212
|
+
end
|
213
|
+
|
214
|
+
# When cursor is in locked mode there needs to be unit it is locked to
|
215
|
+
# When cursor is in freeroam mode the locked unit should be kept
|
154
216
|
def check_unit
|
155
|
-
if !@freeroam and !@
|
156
|
-
abort("
|
217
|
+
if !@freeroam and !@locked_unit
|
218
|
+
abort("Cursor.check_unit(): Cursor is in locked mode " \
|
157
219
|
"but there is no unit it is locked to (at #{@x}-#{@y})")
|
158
220
|
end
|
159
221
|
end
|
@@ -175,12 +237,12 @@ class Cursor
|
|
175
237
|
def info
|
176
238
|
check_unit
|
177
239
|
|
178
|
-
if @
|
179
|
-
@infopane.text = @
|
180
|
-
puts @
|
240
|
+
if @selected_unit
|
241
|
+
@infopane.text = @selected_unit.info
|
242
|
+
puts @selected_unit.info
|
181
243
|
|
182
|
-
if @
|
183
|
-
@
|
244
|
+
if @selected_unit.is_transporting?
|
245
|
+
@selected_unit.cargo.each { |uu| puts '- cargo: ' + uu.info }
|
184
246
|
end
|
185
247
|
else
|
186
248
|
@infopane.text = ''
|
@@ -4,6 +4,8 @@ require_relative './../units/army'
|
|
4
4
|
require_relative './../units/ship'
|
5
5
|
require_relative './../units/town'
|
6
6
|
|
7
|
+
MAX_CARGO_LEVEL = 10
|
8
|
+
|
7
9
|
class Map
|
8
10
|
attr_accessor :name, :mapx, :mapy, :infopane
|
9
11
|
|
@@ -73,13 +75,13 @@ class Map
|
|
73
75
|
coords_y = coords[1].to_i
|
74
76
|
if (coords_x < 0 || coords_x >= @mapx ||
|
75
77
|
coords_y < 0 || coords_y >= @mapy)
|
76
|
-
abort("
|
78
|
+
abort("Map.load_unit!(): Unit out of map borders (#{coords_x}-#{coords_y})")
|
77
79
|
end
|
78
80
|
|
79
81
|
# Check faction
|
80
82
|
fac = unit[1].to_i
|
81
83
|
if(fac < 0 || fac > FACTIONS)
|
82
|
-
abort("
|
84
|
+
abort("Map.load_unit!(): Bad faction id (#{fac})")
|
83
85
|
end
|
84
86
|
|
85
87
|
# Create unit
|
@@ -87,7 +89,7 @@ class Map
|
|
87
89
|
if @known_unit_types.include?(unit_type)
|
88
90
|
@known_unit_types[unit_type].new(coords_x, coords_y, fac, self, @infopane)
|
89
91
|
else
|
90
|
-
abort("
|
92
|
+
abort("Map.load_unit!(): Unknown unit type symbol (#{unit_type})")
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
@@ -105,7 +107,7 @@ class Map
|
|
105
107
|
def all_tiles
|
106
108
|
ret = []
|
107
109
|
ii = 0
|
108
|
-
0.upto(
|
110
|
+
0.upto(MAPY) { |rr|
|
109
111
|
0.upto(MAPX) { |cc|
|
110
112
|
ret[ii] = @tiles[rr][cc]
|
111
113
|
ii += 1
|
@@ -124,34 +126,64 @@ class Map
|
|
124
126
|
@tiles[rr][cc].unit = uu
|
125
127
|
end
|
126
128
|
|
127
|
-
# Return
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# Return only units directly on map
|
133
|
-
def all_map_units
|
129
|
+
# Return all units with cargo level in given range
|
130
|
+
# CL0 = map units, CL1 = units in map units, CL2 = units in CL1 units...
|
131
|
+
# all_units() -> all units, all_units(0, 0) -> only map units
|
132
|
+
def all_units(min_cargo_level = 0, max_cargo_level = MAX_CARGO_LEVEL)
|
134
133
|
ret = []
|
135
|
-
|
136
|
-
|
134
|
+
|
135
|
+
unless min_cargo_level.between?(0, MAX_CARGO_LEVEL) and
|
136
|
+
max_cargo_level.between?(0, MAX_CARGO_LEVEL)
|
137
|
+
abort("Map.all_units(): Desired cargo levels need to be " \
|
138
|
+
"from 0 to #{MAX_CARGO_LEVEL}")
|
139
|
+
end
|
140
|
+
unless min_cargo_level <= max_cargo_level
|
141
|
+
abort("Map.all_units(): Min cargo level (#{min_cargo_level}) is higher " \
|
142
|
+
"than max cargo level (#{max_cargo_level})")
|
143
|
+
end
|
144
|
+
|
145
|
+
0.upto(MAPY) { |rr|
|
137
146
|
0.upto(MAPX) { |cc|
|
138
|
-
|
139
|
-
ret[ii] = get_unit(cc, rr)
|
140
|
-
ii += 1
|
141
|
-
end
|
147
|
+
ret += all_units_from_tile(cc, rr)
|
142
148
|
}
|
143
149
|
}
|
150
|
+
|
144
151
|
ret
|
145
152
|
end
|
146
153
|
|
147
|
-
# Return
|
148
|
-
def
|
154
|
+
# Return all units from given tile with cargo level in given range
|
155
|
+
def all_units_from_tile(cc, rr,
|
156
|
+
min_cargo_level = 0,
|
157
|
+
max_cargo_level = MAX_CARGO_LEVEL)
|
149
158
|
ret = []
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
159
|
+
|
160
|
+
uu = get_unit(cc, rr)
|
161
|
+
if uu
|
162
|
+
ret += add_unit_to_list(uu, 0, min_cargo_level, max_cargo_level)
|
163
|
+
end
|
164
|
+
|
165
|
+
ret
|
166
|
+
end
|
167
|
+
|
168
|
+
# Recursively add units to the list
|
169
|
+
def add_unit_to_list(unit, cargo_level = 0,
|
170
|
+
min_cargo_level = 0,
|
171
|
+
max_cargo_level = MAX_CARGO_LEVEL)
|
172
|
+
ret = []
|
173
|
+
|
174
|
+
# This unit
|
175
|
+
if cargo_level >= min_cargo_level
|
176
|
+
ret.append(unit)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Transported units
|
180
|
+
cargo_level += 1
|
181
|
+
if cargo_level <= max_cargo_level
|
182
|
+
unit.cargo.each { |uu|
|
183
|
+
ret += add_unit_to_list(uu, cargo_level, min_cargo_level, max_cargo_level)
|
184
|
+
}
|
185
|
+
end
|
186
|
+
|
155
187
|
ret
|
156
188
|
end
|
157
189
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative './../game_states/set_state'
|
2
|
+
|
1
3
|
TILE_SEA = 0
|
2
4
|
TILE_GROUND = 1
|
3
5
|
|
@@ -22,7 +24,7 @@ class Tile
|
|
22
24
|
@terrain = TILE_GROUND
|
23
25
|
@image = Gosu::Image.new(dir_path + '/../../media/ground.png')
|
24
26
|
else
|
25
|
-
abort("
|
27
|
+
abort("Tile.initialize(): Unknown terrain symbol (#{loaded_symbol})")
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -36,8 +38,10 @@ class Tile
|
|
36
38
|
end
|
37
39
|
|
38
40
|
# 3) axes
|
39
|
-
draw_axis_tick(@x, @y, 0) # TODO 0 -> viewport.y
|
40
|
-
draw_axis_tick(@
|
41
|
+
draw_axis_tick(@x, @y, 0) if SetState.instance.settings['axis_top'] # TODO 0 -> viewport.y
|
42
|
+
draw_axis_tick(@x, @y, MAPY) if SetState.instance.settings['axis_bottom']
|
43
|
+
draw_axis_tick(@y, @x, 0) if SetState.instance.settings['axis_left'] # TODO 0 -> viewport.x
|
44
|
+
draw_axis_tick(@y, @x, MAPX) if SetState.instance.settings['axis_right']
|
41
45
|
end
|
42
46
|
|
43
47
|
# Draw one tick of axis for appropriate tiles
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: empi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.25'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Detros
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: gosu
|
@@ -52,12 +52,14 @@ files:
|
|
52
52
|
- lib/lib/game_states/game_state.rb
|
53
53
|
- lib/lib/game_states/play_state.rb
|
54
54
|
- lib/lib/game_states/quit_state.rb
|
55
|
+
- lib/lib/game_states/set_state.rb
|
55
56
|
- lib/lib/game_states/welcome_state.rb
|
57
|
+
- lib/lib/game_states/win_state.rb
|
56
58
|
- lib/lib/units/army.rb
|
57
59
|
- lib/lib/units/ship.rb
|
58
60
|
- lib/lib/units/town.rb
|
59
61
|
- lib/lib/units/unit.rb
|
60
|
-
- lib/lib/units/
|
62
|
+
- lib/lib/units/unit_function.rb
|
61
63
|
- lib/lib/user_interface/cursor.rb
|
62
64
|
- lib/lib/user_interface/infopane.rb
|
63
65
|
- lib/lib/user_interface/map.rb
|