empi 0.16.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/army.rb ADDED
@@ -0,0 +1,18 @@
1
+ require_relative './unit'
2
+
3
+ class Army < Unit
4
+ def initialize(x, y, faction, map, infopane)
5
+ super
6
+ dir_path = File.dirname(__FILE__)
7
+ @image = Gosu::Image.new(dir_path + '/media/army.png')
8
+
9
+ @name = 'army'
10
+ @value = 5
11
+ @armor_left = @armor_max = 3
12
+ @moves_max = 5
13
+ end
14
+
15
+ def can_ride?
16
+ true
17
+ end
18
+ end
data/lib/cursor.rb ADDED
@@ -0,0 +1,99 @@
1
+ class Cursor
2
+ attr_accessor :x, :y, :freeroam
3
+
4
+ def initialize(x, y, map, infopane)
5
+ dir_path = File.dirname(__FILE__)
6
+
7
+ @x = x
8
+ @y = y
9
+ @map = map
10
+ @infopane = infopane
11
+
12
+ @image = Gosu::Image.new(dir_path + '/media/cursor.png')
13
+ @freeroam = false
14
+ end
15
+
16
+ def update(key)
17
+ case key
18
+ # Cardinal directions
19
+ when Gosu::KbLeft, Gosu::KbA then
20
+ @x -= 1 unless @x <= 0
21
+ when Gosu::KbRight, Gosu::KbD then
22
+ @x += 1 unless @x >= MAPX
23
+ when Gosu::KbUp, Gosu::KbW then
24
+ @y -= 1 unless @y <= 0
25
+ when Gosu::KbDown, Gosu::KbX then
26
+ @y += 1 unless @y >= MAPY
27
+
28
+ # Intercardinal directions
29
+ when Gosu::KbQ then
30
+ unless @x <= 0 || @y <= 0
31
+ @x -= 1
32
+ @y -= 1
33
+ end
34
+ when Gosu::KbE then
35
+ unless @x >= MAPX || @y <= 0
36
+ @x += 1
37
+ @y -= 1
38
+ end
39
+ when Gosu::KbZ then
40
+ unless @x <= 0 || @y >= MAPY
41
+ @x -= 1
42
+ @y += 1
43
+ end
44
+ when Gosu::KbC then
45
+ unless @x >= MAPX || @y >= MAPY
46
+ @x += 1
47
+ @y += 1
48
+ end
49
+
50
+ # Functions
51
+ when Gosu::KbS then
52
+ uu = @map.get_unit(@x, @y)
53
+ if uu then uu.set_function(FUNCSENTRY) end
54
+ when Gosu::KbB then
55
+ uu = @map.get_unit(@x, @y)
56
+ if uu then uu.set_function(FUNCBUILD) end
57
+ when Gosu::KbN then
58
+ uu = @map.get_unit(@x, @y)
59
+ if uu then uu.set_function(FUNCNONE) end
60
+
61
+ when Gosu::KbReturn then
62
+ info
63
+ end
64
+ end
65
+
66
+ def draw
67
+ @image.draw(@x * TILESIZE, (@y + 1) * TILESIZE, ZCURSOR)
68
+ end
69
+
70
+ # Move to given coordinates
71
+ def warp(x, y)
72
+ @x = x
73
+ @y = y
74
+ end
75
+
76
+ # Switch between being attached to unit and being able to freeroam
77
+ def switch_freeroam
78
+ if freeroam == true
79
+ @infopane.text = 'freeroam disabled'
80
+ puts 'freeroam disabled'
81
+ else
82
+ @infopane.text = 'freeroam enabled'
83
+ puts 'freeroam enabled'
84
+ end
85
+ @freeroam = !@freeroam
86
+ end
87
+
88
+ # Find some info about unit in current tile
89
+ def info
90
+ uu = @map.get_unit(@x, @y)
91
+ if uu
92
+ @infopane.text = uu.info
93
+ puts uu.info
94
+ else
95
+ @infopane.text = ''
96
+ puts 'nothing here'
97
+ end
98
+ end
99
+ end
Binary file
data/lib/docu/info.txt ADDED
@@ -0,0 +1,149 @@
1
+ /-- /// /-/ -/-
2
+ /-- ||| /-/ |
3
+ /-- ||| | -/-
4
+
5
+ Empi: Ruby Edition
6
+ ====================
7
+
8
+
9
+ v16 dev
10
+ =========
11
+ - units on sentry duty say so when functioning
12
+ - neutral units can't have functions
13
+ - links to media and save files use full path
14
+ - towns build armies
15
+ ! hardcoded unit type to be built
16
+ - units can transport other units
17
+ - newly built units are stored in town instead of map
18
+ fixes: new units are saved in map instead of the towns that built them
19
+ ! transported units are not drawn
20
+ ! transported units show info of their transport instead when selected
21
+ ! all units can capture and visit towns
22
+
23
+ file changes
24
+ --------------
25
+ map
26
+ initialize() uses full paths to files
27
+ all_units renamed to all_map_units() - Return only units directly on map
28
+ +all_transported_units() - Return only units transported by other units
29
+ +all_units() - Return both map units and transported units
30
+ draw_units() draws only map units
31
+
32
+ unit
33
+ +@cargo, @cargo_max
34
+ +can_transport?() - Unit is able to both transport other units and currently has some space left
35
+ set_function() checks for @faction == 0
36
+ checking of movement separated from update()
37
+ +check_movement() - Processes move of unit and takes care of its (un)loading or attack
38
+ capture() makes newly captured towns start building
39
+
40
+ town
41
+ initialize() uses full path to file
42
+ +parts_built
43
+ +@cargo_max set to 10
44
+
45
+ army
46
+ initialize() uses full path to file
47
+
48
+ ship
49
+ initialize() uses full path to file
50
+ +@cargo_max set to 3
51
+
52
+ unitFunction
53
+ +FUNCBUILD case in func!()
54
+ FUNCSENTRY case in func!() sets "ret" even when unit keeps sentrying
55
+
56
+
57
+ v15 dev
58
+ =========
59
+ - units referenced only from map
60
+ fixed: no destruction of units
61
+ - loading of units from file
62
+ fixed: no loading
63
+ - checks of loaded terrain tiles and units
64
+ - map stored as [row, column], not [xx, yy]
65
+
66
+ file changes
67
+ --------------
68
+ empi.rb
69
+ -scenario_units() - Return list of units for given scenario
70
+
71
+ map.rb
72
+ load_map() now loads units too
73
+ load_head() now returns number of units to load too
74
+ load_map(), tile(), get_unit(), set_unit() use rr and cc instead of xx and yy
75
+ +load_unit() - Load one unit from given line
76
+ +draw_units() - Draw all units
77
+
78
+ save/m01.esf
79
+ 8 units from old empi.scenario_units()
80
+
81
+ save/m02.esf
82
+ 10 units similar to old empi.scenario_units()
83
+
84
+ save/m03.esf
85
+
86
+
87
+ v14 dev
88
+ =========
89
+ - loading of terrain tiles from file
90
+ fixed: hardcoded starting scenario
91
+ ! hardcoded save file name
92
+ ! hardcoded map size
93
+
94
+ file changes
95
+ --------------
96
+ empi.rb
97
+ TILE constants moved to map.rb
98
+
99
+ map.rb
100
+ -scenario_tiles() - Return map tile for given scenario
101
+ +load_map() - Load map from file (for now only terrain tiles)
102
+ +load_head() - Load head row of file
103
+
104
+ unit.rb
105
+ removed generic unit image
106
+
107
+ save/m01.esf
108
+ save/m02.esf
109
+
110
+
111
+ older versions
112
+ ================
113
+ - towns and armies
114
+ - functions none and sentry
115
+ - armor and movement points
116
+ - movement of units
117
+ - rudimentary terrain checking after move
118
+ - capturing of units
119
+ - turn and score counting
120
+ - commmand line and screen text output
121
+ - next avaiable unit / freeroam cursor
122
+
123
+ current state
124
+ ===============
125
+ old wishlist
126
+ ! no panning of map
127
+ !x no destruction of units
128
+ !x no building of units
129
+ ! no victory conditions
130
+ ! attacker always wins
131
+ ! player playing both factions at once
132
+ !x hardcoded starting scenario
133
+ ! no fog of war
134
+ ! no saving
135
+ !x no loading
136
+ ! no title screen
137
+ ! no highscore screen
138
+ ! no settings
139
+ ! no sound, no music
140
+
141
+ new problems
142
+ ! hardcoded save file name
143
+ ! hardcoded map size
144
+ ! hardcoded unit type to be built
145
+ ! transported units are not drawn
146
+ ! transported units show info of their transport instead when selected
147
+ ! all units can capture and visit towns
148
+
149
+ (! thing to fix, !x fixed thing)
data/lib/empi.rb ADDED
@@ -0,0 +1,143 @@
1
+ require 'rubygems'
2
+ require 'gosu'
3
+
4
+ require_relative './army'
5
+ require_relative './cursor'
6
+ require_relative './infopane'
7
+ require_relative './map'
8
+ require_relative './ship'
9
+ require_relative './town'
10
+
11
+ TILESIZE = 50
12
+ MAPX = 10
13
+ MAPY = 10
14
+
15
+ XTEXT = 5
16
+ YTEXT = 5
17
+
18
+ ZTILE = 0
19
+ ZUNIT = 1
20
+ ZTEXT = 2
21
+ ZCURSOR = 3
22
+
23
+ FACTIONS = 2
24
+ COLOUR = [0xff_ffffff, 0xff_ff3300, 0xff_ffcc00]
25
+
26
+ FUNCNONE = 'none'
27
+ FUNCSENTRY = 'sentry'
28
+ FUNCBUILD = 'build'
29
+
30
+ # Main class
31
+ class GameWindow < Gosu::Window
32
+ def initialize(width = (MAPX + 1) * TILESIZE, \
33
+ height = (MAPY + 2) * TILESIZE, \
34
+ fullscreen = false)
35
+ super
36
+ self.caption = 'Empi: Ruby Edition 0.16 dev'
37
+
38
+ @infopane = Infopane.new
39
+ @map = Map.new(@infopane)
40
+ @cursor = Cursor.new(5, 5, @map, @infopane)
41
+
42
+ new_turn
43
+ end
44
+
45
+ def button_up(key)
46
+ @button = key
47
+
48
+ case(key)
49
+ when Gosu::KbEscape then
50
+ close
51
+ when Gosu::KbPeriod then
52
+ new_turn
53
+ when Gosu::KbH then
54
+ help
55
+ when Gosu::KbJ then
56
+ unit_to_move = 0
57
+ @cursor.switch_freeroam
58
+ end
59
+ end
60
+
61
+ # Process given button to cursor
62
+ def update
63
+ if @button == -1 then return end
64
+
65
+ movable_units = @map.all_units.select { |uu| uu.can_move && uu.function == FUNCNONE}
66
+ # If there are any movable units without functions select one of them with the cursor
67
+ if @cursor.freeroam == false && movable_units.size > 0
68
+ unit_to_move = movable_units[0]
69
+ unit_to_move.update(@button)
70
+
71
+ # Can it still move?
72
+ if unit_to_move.can_move && unit_to_move.function == FUNCNONE
73
+ # Move the cursor to it unless it is already there
74
+ if (@cursor.x != unit_to_move.x \
75
+ || @cursor.y != unit_to_move.y)
76
+ @cursor.warp(unit_to_move.x, unit_to_move.y)
77
+ @cursor.info
78
+ end
79
+ else
80
+ # Was that the last currently avaiable non-function move?
81
+ movable_units = @map.all_units.select { |uu| uu.can_move && uu.function == FUNCNONE}
82
+ if movable_units.size == 0
83
+ puts 'all movable units without functions moved'
84
+ @cursor.switch_freeroam
85
+ else
86
+ # Move cursor to next avaiable unit
87
+ unit_to_move = movable_units[0]
88
+ @cursor.warp(unit_to_move.x, unit_to_move.y)
89
+ @cursor.info
90
+ end
91
+ end
92
+
93
+ else
94
+ # Cursor in freeroam mode
95
+ @cursor.update(@button)
96
+ end
97
+ end
98
+
99
+ # Draw only after some button was released and in the start
100
+ def needs_redraw?
101
+ @button != -1
102
+ end
103
+
104
+ def draw
105
+ @button = -1 # use each button just once
106
+
107
+ # Draw map tiles and units
108
+ @map.draw_tiles
109
+ @map.draw_units
110
+ # DEBUG @map.all_units.each { |uu| puts uu.info}
111
+
112
+ @cursor.draw
113
+ @infopane.draw
114
+
115
+ # @message = Gosu::Image.from_text(
116
+ # self, "Empire", Gosu.default_font_name, 20)
117
+ # @message.draw(10, 10, 2)
118
+ end
119
+
120
+ # End current turn and start next one
121
+ def new_turn
122
+ @cursor.freeroam = true
123
+ @cursor.switch_freeroam # so freeroam = false, with messages
124
+
125
+ functionable_units = @map.all_units.select { |uu| uu.function != FUNCNONE}
126
+ functionable_units.each { |uu| uu.function! }
127
+
128
+ @map.all_units.each { |uu| uu.reset_moves}
129
+ @infopane.next_turn
130
+ end
131
+
132
+ def help
133
+ puts "----------\n" \
134
+ "QWEADZXC movement, h help, Enter info, j switch freeroam\n" \
135
+ "functions: s sentry, n none\n" \
136
+ "----------\n"
137
+ end
138
+ end
139
+
140
+ # ---------------------------------------------------------------
141
+
142
+ window = GameWindow.new
143
+ window.show
data/lib/infopane.rb ADDED
@@ -0,0 +1,36 @@
1
+ # Score, turn and event texts
2
+ class Infopane
3
+ attr_writer :text, :act_fact
4
+
5
+ def initialize
6
+ @score = [0, 0]
7
+ @turn = 0
8
+ @act_fact = 0 # active faction
9
+ @text = 'ready'
10
+ end
11
+
12
+ def update
13
+ end
14
+
15
+ def draw
16
+ turnscore = Gosu::Image.from_text(
17
+ self, "Turn: #{@turn}, Score: #{@score[0]} - #{@score[1]}", Gosu.default_font_name, 20)
18
+ turnscore.draw(XTEXT, YTEXT, ZTEXT)
19
+
20
+ text = Gosu::Image.from_text(self, "#{@text}", Gosu.default_font_name, 20)
21
+ text.draw(XTEXT, (TILESIZE / 2) + YTEXT, ZTEXT)
22
+ end
23
+
24
+ def next_faction
25
+
26
+ end
27
+
28
+ def next_turn
29
+ @turn += 1
30
+ puts "Turn: #{@turn}, Score: #{@score[0]} - #{@score[1]}"
31
+ end
32
+
33
+ def add_score(to_whom, how_much)
34
+ @score[to_whom] += how_much
35
+ end
36
+ end
data/lib/map.rb ADDED
@@ -0,0 +1,172 @@
1
+ TILE_SEA = 0
2
+ TILE_GROUND = 1
3
+
4
+ SYMBOL_SEA = '.'
5
+ SYMBOL_GROUND = '#'
6
+ SYMBOL_TOWN = 'T'
7
+ SYMBOL_ARMY = 'A'
8
+ SYMBOL_SHIP = 'S'
9
+
10
+ class Map
11
+ attr_accessor :name, :mapx, :mapy, :infopane
12
+
13
+ # Fill tile map and prepare
14
+ def initialize(infopane)
15
+ dir_path = File.dirname(__FILE__)
16
+
17
+ @infopane = infopane
18
+ @sea_image = Gosu::Image.new(dir_path + '/media/sea.png')
19
+ @ground_image = Gosu::Image.new(dir_path + '/media/ground.png')
20
+ load_map(dir_path + '/save/m03.esf')
21
+ end
22
+
23
+ # Load map from file
24
+ def load_map(filename)
25
+ input = File.open(filename, 'r')
26
+ unit_count = load_head(input.gets)
27
+
28
+ # Load tiles
29
+ @tiles = []
30
+ @units = []
31
+ 0.upto(@mapy - 1) { |rr|
32
+ @tiles[rr] = []
33
+ @units[rr] = []
34
+ map_row = input.gets
35
+ 0.upto(@mapx - 1) { |cc|
36
+ case(map_row[cc])
37
+ when SYMBOL_SEA then
38
+ @tiles[rr][cc] = TILE_SEA
39
+ when SYMBOL_GROUND then
40
+ @tiles[rr][cc] = TILE_GROUND
41
+ else
42
+ abort("map.load_map(): Unknown terrain symbol (#{map_row[cc]})")
43
+ end
44
+ }
45
+ }
46
+
47
+ # Load units
48
+ unit_count.times { load_unit(input.gets) }
49
+
50
+ puts("Save loaded: #{@name} with #{unit_count} units")
51
+ input.close
52
+ end
53
+
54
+ # Load core info from given head row of file
55
+ # Return number of units to be loaded
56
+ def load_head(row)
57
+ head = []
58
+ size = []
59
+
60
+ head = row.split(' ')
61
+ size = head[1].split('x')
62
+
63
+ @name = head[0]
64
+ @mapx = size[0].to_i
65
+ @mapy = size[1].to_i
66
+
67
+ head[2].to_i # unit_count
68
+ end
69
+
70
+ # Load one unit from given line
71
+ def load_unit(row)
72
+ unit = []
73
+ coords = []
74
+
75
+ unit = row.split(' ')
76
+ coords = unit[2].split('-')
77
+
78
+ # Check faction
79
+ fac = unit[1].to_i
80
+ if(fac < 0 || fac > FACTIONS)
81
+ abort("map.load_unit(): Bad faction id (#{fac})")
82
+ end
83
+
84
+ # Check coordinates
85
+ coords_x = coords[0].to_i
86
+ coords_y = coords[1].to_i
87
+ if (coords_x < 0 || coords_x >= @mapx ||
88
+ coords_y < 0 || coords_y >= @mapy)
89
+ abort("map.load_unit(): Unit out of map borders (#{coords_x}-#{coords_y})")
90
+ end
91
+
92
+ # Create unit
93
+ case(unit[0])
94
+ when SYMBOL_TOWN then
95
+ Town.new(coords_x, coords_y, fac, self, @infopane)
96
+ when SYMBOL_ARMY then
97
+ Army.new(coords_x, coords_y, fac, self, @infopane)
98
+ when SYMBOL_SHIP then
99
+ Ship.new(coords_x, coords_y, fac, self, @infopane)
100
+ else
101
+ abort("map.load_unit(): Unknown unit type symbol (#{unit[0]})")
102
+ end
103
+ end
104
+
105
+ # Draw all tiles
106
+ def draw_tiles
107
+ # TODO combine with draw_units()
108
+
109
+ 0.upto(MAPX) { |rr|
110
+ 0.upto(MAPX) { |cc|
111
+ if @tiles[rr][cc] == TILE_SEA
112
+ # TODO tiles (z1) and units (z2) together
113
+ im = @sea_image
114
+ else
115
+ im = @ground_image
116
+ end
117
+ im.draw(cc * TILESIZE, (rr + 1) * TILESIZE, ZTILE)
118
+ }
119
+ }
120
+ end
121
+
122
+ # Draw all map units
123
+ def draw_units
124
+ all_map_units.each { |uu| uu.draw} # TODO do not draw transported units? only draw them on selection (with their tile)?
125
+ end
126
+
127
+ # Getter for tile type in given coordinates
128
+ def tile(cc, rr)
129
+ @tiles[rr][cc]
130
+ end
131
+
132
+ # Getter for unit in given coordinates
133
+ def get_unit(cc, rr)
134
+ @units[rr][cc]
135
+ end
136
+
137
+ # Setter for tile type in given coordinates
138
+ def set_unit(cc, rr, uu)
139
+ @units[rr][cc] = uu
140
+ end
141
+
142
+ # Return both map units and transported units
143
+ def all_units
144
+ all_map_units + all_transported_units
145
+ end
146
+
147
+ # Return only units directly on map
148
+ def all_map_units
149
+ ret = []
150
+ ii = 0
151
+ 0.upto(MAPX) { |rr|
152
+ 0.upto(MAPX) { |cc|
153
+ if @units[rr][cc]
154
+ ret[ii] = @units[rr][cc]
155
+ ii += 1
156
+ end
157
+ }
158
+ }
159
+ ret
160
+ end
161
+
162
+ # Return only units transported by other units
163
+ def all_transported_units
164
+ ret = []
165
+ all_map_units.each { |uu|
166
+ if uu.is_transporting?
167
+ ret += uu.cargo
168
+ end
169
+ }
170
+ ret
171
+ end
172
+ end
Binary file
Binary file
Binary file
data/lib/media/sea.png ADDED
Binary file
Binary file
Binary file
data/lib/save/m01.esf ADDED
@@ -0,0 +1,20 @@
1
+ mission01 11x11 8
2
+ #####..####
3
+ ####....###
4
+ ###......##
5
+ ##........#
6
+ #...###...#
7
+ ....##....#
8
+ ....#....##
9
+ #.......###
10
+ ##.....####
11
+ ###...#####
12
+ ###########
13
+ T 0 1-3
14
+ T 0 3-1
15
+ T 0 6-9
16
+ T 0 9-6
17
+ T 1 8-1
18
+ A 1 9-1
19
+ T 2 1-8
20
+ A 2 1-9
data/lib/save/m02.esf ADDED
@@ -0,0 +1,22 @@
1
+ mission02 11x11 10
2
+ ###########
3
+ #..###..###
4
+ #....#...##
5
+ ##...#....#
6
+ ##....#...#
7
+ ####...####
8
+ #...#....##
9
+ #....#....#
10
+ ##...#....#
11
+ ###..##..##
12
+ ###########
13
+ T 0 1-3
14
+ T 0 3-1
15
+ T 0 6-9
16
+ T 0 9-6
17
+ T 1 8-1
18
+ T 1 9-2
19
+ A 1 10-0
20
+ T 2 1-8
21
+ T 2 2-9
22
+ A 2 0-10
data/lib/save/m03.esf ADDED
@@ -0,0 +1,24 @@
1
+ mission03 11x11 11
2
+ .....###...
3
+ ..#######..
4
+ .#.##.##.#.
5
+ #.#....#.##
6
+ ##...##.###
7
+ #..#####..#
8
+ ###.##...##
9
+ ##.#....#.#
10
+ .#.##.##.#.
11
+ ..#######..
12
+ ...###.....
13
+ T 0 3-8
14
+ T 0 10-4
15
+ T 0 5-1
16
+ T 0 5-5
17
+ T 0 5-9
18
+ T 0 7-2
19
+ T 0 0-6
20
+ T 1 2-3
21
+ A 1 1-2
22
+ T 2 8-7
23
+ A 2 9-8
24
+
data/lib/ship.rb ADDED
@@ -0,0 +1,19 @@
1
+ require_relative './unit'
2
+
3
+ class Ship < Unit
4
+ def initialize(x, y, faction, map, infopane)
5
+ super
6
+ dir_path = File.dirname(__FILE__)
7
+ @image = Gosu::Image.new(dir_path + '/media/ship.png')
8
+
9
+ @name = 'ship'
10
+ @value = 10
11
+ @armor_left = @armor_max = 1
12
+ @moves_max = 2
13
+ @cargo_max = 3
14
+ end
15
+
16
+ def can_sail?
17
+ true
18
+ end
19
+ end
data/lib/town.rb ADDED
@@ -0,0 +1,24 @@
1
+ require_relative './unit'
2
+
3
+ class Town < Unit
4
+ attr_accessor :parts_built
5
+
6
+ def initialize(x, y, faction, map, infopane)
7
+ super
8
+ dir_path = File.dirname(__FILE__)
9
+ @image = Gosu::Image.new(dir_path + '/media/town.png')
10
+
11
+ @name = 'town'
12
+ @value = 20
13
+ @armor_left = @armor_max = 1
14
+ @moves_max = 0
15
+
16
+ @parts_built = 0
17
+ @cargo_max = 10
18
+ set_function(FUNCBUILD)
19
+ end
20
+
21
+ def can_build?
22
+ true
23
+ end
24
+ end
data/lib/unit.rb ADDED
@@ -0,0 +1,244 @@
1
+ require_relative './unitFunction'
2
+
3
+ # All capturable game pieces
4
+ class Unit
5
+ attr_accessor :x, :y, :faction, :function, :cargo
6
+
7
+
8
+ def initialize(x, y, faction, map, infopane)
9
+ @x = x
10
+ @y = y
11
+ @faction = faction
12
+ @map = map
13
+ @infopane = infopane
14
+
15
+ @name = 'unit'
16
+ @value = 1
17
+ @armor_max = 1
18
+ @armor_left = @armor_max
19
+ @moves_max = 1
20
+ @moves_left = @moves_max
21
+ @cargo = [] # transported units
22
+ @cargo_max = 0
23
+ @function = UnitFunction.new(FUNCNONE)
24
+
25
+
26
+
27
+ # Store yourself
28
+ coords_unit = @map.get_unit(@x, @y)
29
+ if !coords_unit
30
+ @map.set_unit(@x, @y, self)
31
+ else # some town has just built you
32
+ coords_unit.cargo.insert(-1, self) # -1 = to the end
33
+ end
34
+ end
35
+
36
+ # Add <value> to the other faction
37
+ def destroy
38
+ @infopane.add_score(3 - @faction - 1, @value) # TODO more factions?
39
+ # TODO is this deleted enough?
40
+ @map.set_unit(@x, @y, nil)
41
+ end
42
+
43
+ def capture(by_whom)
44
+ # add <value> to the capturing faction
45
+ @infopane.add_score(by_whom - 1, @value)
46
+ @faction = by_whom
47
+
48
+ # if you are a town, start building units
49
+ if can_build?
50
+ set_function(FUNCBUILD)
51
+ end
52
+ end
53
+
54
+ def update(key)
55
+ old_x = @x
56
+ old_y = @y
57
+
58
+ case key
59
+ # Cardinal directions
60
+ when Gosu::KbLeft, Gosu::KbA then
61
+ @x -= 1 unless @x <= 0
62
+ when Gosu::KbRight, Gosu::KbD then
63
+ @x += 1 unless @x >= MAPX
64
+ when Gosu::KbUp, Gosu::KbW then
65
+ @y -= 1 unless @y <= 0
66
+ when Gosu::KbDown, Gosu::KbX then
67
+ @y += 1 unless @y >= MAPY
68
+
69
+ # Intercardinal directions
70
+ when Gosu::KbQ then
71
+ unless @x <= 0 || @y <= 0
72
+ @x -= 1
73
+ @y -= 1
74
+ end
75
+ when Gosu::KbE then
76
+ unless @x >= MAPX || @y <= 0
77
+ @x += 1
78
+ @y -= 1
79
+ end
80
+ when Gosu::KbZ then
81
+ unless @x <= 0 || @y >= MAPY
82
+ @x -= 1
83
+ @y += 1
84
+ end
85
+ when Gosu::KbC then
86
+ unless @x >= MAPX || @y >= MAPY
87
+ @x += 1
88
+ @y += 1
89
+ end
90
+
91
+ # Functions
92
+ when Gosu::KbS then
93
+ set_function(FUNCSENTRY)
94
+ when Gosu::KbB then
95
+ set_function(FUNCBUILD)
96
+ end
97
+
98
+ check_movement(old_x, old_y)
99
+ end
100
+
101
+
102
+ # Processes move of unit and takes care of its (un)loading or attack
103
+ def check_movement(old_x, old_y)
104
+ if @x != old_x || @y != old_y
105
+ oldcoords_unit = @map.get_unit(old_x, old_y)
106
+ newcoords_unit = @map.get_unit(@x, @y)
107
+
108
+ # If there is nobody or is there friendly unit with some cargo space
109
+ if !newcoords_unit || \
110
+ (newcoords_unit.faction == @faction && newcoords_unit.can_transport?)
111
+
112
+ # Leave old coordinates
113
+ if oldcoords_unit == self
114
+ @map.set_unit(old_x, old_y, nil)
115
+ else # if you have been transported
116
+ puts "oldcoords_unit.cargo = \"#{oldcoords_unit.cargo}\""
117
+ oldcoords_unit.cargo.delete(self)
118
+ puts "oldcoords_unit.cargo = \"#{oldcoords_unit.cargo}\""
119
+ end
120
+
121
+ # Get to new coordinates
122
+ if newcoords_unit == nil
123
+ @map.set_unit(@x, @y, self)
124
+ else # if you are going to be transported
125
+ newcoords_unit.cargo.insert(-1, self) # -1 = to the end
126
+ end
127
+
128
+ else # if there already is somebody
129
+ # Stay on your original tile
130
+ @x = old_x
131
+ @y = old_y
132
+
133
+ # Don't capture allies
134
+ if newcoords_unit.faction != @faction
135
+ puts to_s + ' is capturing ' + newcoords_unit.to_s # TODO capture only towns, do combat otherwise
136
+ newcoords_unit.capture(@faction)
137
+ end
138
+ end
139
+ @moves_left -= 1
140
+
141
+ # Check if unit is on invalid type of tile
142
+ if tile_check == false
143
+ puts to_s + " found itself in a bad place"
144
+ destroy
145
+ end
146
+ end
147
+ end
148
+
149
+
150
+ def draw
151
+ @image.draw(@x * TILESIZE, (@y + 1) * TILESIZE, ZUNIT,
152
+ scale_x = 1, scale_y = 1, color = COLOUR[@faction])
153
+ end
154
+
155
+ def can_move
156
+ (can_fly? || can_sail? || can_ride?) && @moves_left > 0
157
+ end
158
+
159
+ def can_fly?
160
+ false
161
+ end
162
+
163
+ def can_sail?
164
+ false
165
+ end
166
+
167
+ def can_ride?
168
+ false
169
+ end
170
+
171
+ def can_build?
172
+ false
173
+ end
174
+
175
+ # Unit is able to both transport other units and currently has some space left
176
+ def can_transport?
177
+ @cargo_max > 0 && @cargo.size < @cargo_max
178
+ end
179
+
180
+ def is_transporting?
181
+ @cargo.size > 0
182
+ end
183
+
184
+ def tile_check
185
+ case @map.tile(@x, @y)
186
+ when TILE_SEA
187
+ return can_fly? || can_sail?
188
+ when TILE_GROUND
189
+ return can_fly? || can_ride?
190
+ end
191
+ true
192
+ end
193
+
194
+ def function
195
+ @function.func
196
+ end
197
+
198
+ def set_function(func)
199
+ unless @faction == 0 # neutral faction doesn't need functions
200
+ if (func == FUNCBUILD && !can_build?)
201
+ puts to_s + ": this unit can't build other units"
202
+ end
203
+
204
+ if @function == func
205
+ puts to_s + ": function already set to #{@function.func}"
206
+ else
207
+ @function.func = func
208
+ puts to_s + ": function set to #{@function.func}"
209
+ end
210
+ end
211
+ end
212
+
213
+
214
+ def function!
215
+ ret = @function.func!(@x, @y, @map, @infopane)
216
+ puts to_s + ret
217
+ end
218
+
219
+ # Set short info string: type, faction, coordinates
220
+ def to_s
221
+ "#{@name} (FAC#{@faction} #{@x}-#{@y})"
222
+ end
223
+
224
+ # Set long info string: short info string, armor, moves, function, cargo
225
+ def info
226
+ ret = to_s + ": armor #{@armor_left}/#{@armor_max}"
227
+
228
+ if can_move
229
+ ret = ret + ", moves #{@moves_left}/#{@moves_max}"
230
+ end
231
+
232
+ ret = ret + ", func #{@function.func}"
233
+
234
+ if @cargo.size > 0
235
+ ret = ret + ", transports #{@cargo.size} units"
236
+ end
237
+
238
+ ret
239
+ end
240
+
241
+ def reset_moves
242
+ @moves_left = @moves_max
243
+ end
244
+ end
@@ -0,0 +1,47 @@
1
+ PARTS = 3
2
+
3
+ class UnitFunction
4
+ attr_accessor :func
5
+
6
+ def initialize(function = FUNCNONE)
7
+ @func = function
8
+ end
9
+
10
+ def func!(xx, yy, map, infopane)
11
+ ret = " didn't actually do anything (ERROR)"
12
+
13
+ unit = map.get_unit(xx, yy)
14
+ if unit == nil
15
+ abort("unitFunction.func!(): Functioning unit not found at given coordinates (#{xx}-#{yy})")
16
+ end
17
+
18
+ case @func
19
+ # Build given unit
20
+ when FUNCBUILD
21
+ if(unit.parts_built >= PARTS) # just == should be enough
22
+ ret = " completed building of army"
23
+ unit.parts_built = 0
24
+ Army.new(unit.x, unit.y, unit.faction, map, infopane) # TODO allow setting what to build
25
+ else
26
+ ret = " built next part of army"
27
+ unit.parts_built = unit.parts_built + 1
28
+ end
29
+
30
+ # Wake up when enemies are nearby
31
+ when FUNCSENTRY
32
+ units_around = map.all_units.select { |uu|
33
+ (uu.x - xx).abs <= 1 &&
34
+ (uu.y - yy).abs <= 1 &&
35
+ uu.faction != unit.faction
36
+ }
37
+ if units_around.size > 0
38
+ ret = " woke up"
39
+ @func = FUNCNONE
40
+ else
41
+ ret = " was on sentry duty"
42
+ end
43
+ end
44
+
45
+ ret
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: empi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.16.6
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Detros
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-04-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: gosu
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '10.0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '10.0'
46
+ description: ! 'Empi: Ruby Edition is a turn based wargame, currently deep in development.
47
+ While learning Ruby I have found there are hardly any strategic games avaiable.
48
+ So this should be Ruby version of Classic Empire, wargame from old times.'
49
+ email: rasunadon@seznam.cz
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/docu/Empi v14.png
55
+ - lib/docu/info.txt
56
+ - lib/media/town.png
57
+ - lib/media/ship.png
58
+ - lib/media/army.png
59
+ - lib/media/cursor.png
60
+ - lib/media/sea.png
61
+ - lib/media/ground.png
62
+ - lib/save/m02.esf
63
+ - lib/save/m01.esf
64
+ - lib/save/m03.esf
65
+ - lib/ship.rb
66
+ - lib/unit.rb
67
+ - lib/unitFunction.rb
68
+ - lib/town.rb
69
+ - lib/map.rb
70
+ - lib/army.rb
71
+ - lib/cursor.rb
72
+ - lib/infopane.rb
73
+ - lib/empi.rb
74
+ homepage: http://www.bay12forums.com/smf/index.php?topic=157538.0
75
+ licenses:
76
+ - CC-BY-SA 3.0
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 1.8.23
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Turn-based wargame
99
+ test_files: []