terminal_chess 0.1.2 → 0.2.0

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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: terminal_chess
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Willems
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-03 00:00:00.000000000 Z
11
+ date: 2017-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -24,6 +24,48 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: em-websocket
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: eventmachine
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: faye-websocket
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
27
69
  - !ruby/object:Gem::Dependency
28
70
  name: bundler
29
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +94,20 @@ dependencies:
52
94
  - - "~>"
53
95
  - !ruby/object:Gem::Version
54
96
  version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: minitest
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
55
111
  description: Two player chess game through the terminal
56
112
  email: hello@jasonwillems.com
57
113
  executables:
@@ -60,14 +116,19 @@ extensions: []
60
116
  extra_rdoc_files: []
61
117
  files:
62
118
  - Gemfile
119
+ - Gemfile.lock
63
120
  - LICENSE
64
121
  - README.md
65
122
  - Rakefile
66
123
  - bin/terminal_chess
67
- - lib/Board.rb
124
+ - lib/board.rb
125
+ - lib/local_chess_client.rb
68
126
  - lib/move.rb
127
+ - lib/network_chess_client.rb
69
128
  - lib/printer.rb
129
+ - lib/server.rb
70
130
  - lib/terminal_chess.rb
131
+ - lib/terminal_chess/messages.rb
71
132
  - lib/terminal_chess/version.rb
72
133
  - terminal_chess.gemspec
73
134
  - test/test_terminal_chess.rb
@@ -91,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
152
  version: '0'
92
153
  requirements: []
93
154
  rubyforge_project:
94
- rubygems_version: 2.2.2
155
+ rubygems_version: 2.6.8
95
156
  signing_key:
96
157
  specification_version: 4
97
158
  summary: Chess game playable via the terminal
@@ -1,266 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- load 'printer.rb'
4
- load 'move.rb'
5
- require 'colorize'
6
-
7
- class Board
8
-
9
- include PRINTER
10
- include MOVE
11
-
12
- def initialize
13
- @@piece_locations = Hash.new
14
- @@piece_locations_buffer = Hash.new
15
- @@row_mappings = Hash[("A".."H").zip(1..8)]
16
- @@taken_pieces = []
17
- @@player_turn = "black"
18
- @@checkmate = false
19
- end
20
-
21
-
22
- # Game logic
23
- def move(p1, p2)
24
- manifest = piece_manifest
25
- p1 = get_index_from_rowcol(p1.to_s)
26
- p2 = get_index_from_rowcol(p2.to_s)
27
- valid_positions = possible_moves(p1, manifest, true)
28
-
29
- ##Subtract king current position from valid positions
30
- valid_positions -= king_positions
31
-
32
- # Allow piece movements, unless in checkmate
33
- if !@@checkmate
34
- # Ensure player is moving in turn
35
- if @@player_turn == @@piece_locations[p1]["color"]
36
-
37
- @@piece_locations_buffer = @@piece_locations.clone
38
-
39
- # Chosen destination is within the list of valid destinations
40
- if ([p2] - valid_positions).empty?
41
-
42
- @@piece_locations_buffer[p2] = @@piece_locations_buffer[p1]
43
- @@piece_locations_buffer[p2]["moved"] = true
44
- @@piece_locations_buffer[p1] = {"type" => " ", "number" => nil, "color" => nil}
45
-
46
- # If the current player is not in check at the end of the turn, allow them to proceed
47
- if !check?(@@player_turn, @@piece_locations_buffer)
48
-
49
- @@taken_pieces << @@piece_locations[p2] if !@@piece_locations[p2]["number"].nil?
50
-
51
- # Check for Pawn Promotion (if pawn reaches end of the board, promote it)
52
- if @@piece_locations_buffer[p2]["type"] == "pawn"
53
- if p2 < 9 && @@piece_locations_buffer[p2]["color"] == "red"
54
- promote(p2)
55
- elsif p2 > 56 && @@piece_locations_buffer[p2]["color"] == "black"
56
- promote(p2)
57
- end
58
- end
59
-
60
- # Check for Castling
61
- if @@piece_locations_buffer[p2]["type"] == "king" && (p2 - p1).abs == 2
62
-
63
- p2 < 9 ? y_offset = 0 : y_offset = 56
64
-
65
- if p2 > p1
66
- @@piece_locations_buffer[6+y_offset] = @@piece_locations_buffer[8+y_offset]
67
- @@piece_locations_buffer[8+y_offset] = {"type" => " ", "number" => nil, "color" => nil}
68
- else
69
- @@piece_locations_buffer[4+y_offset] = @@piece_locations_buffer[1+y_offset]
70
- @@piece_locations_buffer[1+y_offset] = {"type" => " ", "number" => nil, "color" => nil}
71
- end
72
- end
73
-
74
- # Clean Up
75
- @@piece_locations = @@piece_locations_buffer
76
- @@player_turn = (["black", "red"] - [@@player_turn]).first
77
- board_refresh
78
- else
79
- p "Please move #{@@player_turn} king out of check to continue"
80
- end
81
- else p "Please select a valid destination." end
82
- else p "It is #{@@player_turn}'s turn. Please move a #{@@player_turn} piece." end
83
- else p "Checkmate! Game Over." end
84
- end
85
-
86
- # Return the valid positions for piece at current_pos to move in readable format [A-H][1-8]
87
- def valid_destinations(current_pos)
88
- readable_positions = []
89
- manifest = piece_manifest
90
- p1 = get_index_from_rowcol(current_pos.to_s)
91
-
92
- valid_positions = possible_moves(p1, manifest, true)
93
- valid_positions.each do |pos|
94
- grid_pos = get_rowcol_from_index(pos)
95
- # Map first string character 1-8 to [A-H], for column, and then add second string character as [1-8]
96
- readable_positions << (@@row_mappings.key(grid_pos[0].to_i) + grid_pos[1].to_s)
97
- end
98
- return readable_positions.sort
99
- end
100
-
101
- # Search piece manifest for kings. Remove them from the list of positions returned
102
- # from the MOVE module (so that players cannot take the "king" type piece)
103
- def king_positions
104
- king_locations = []
105
- @@piece_locations.each do |piece, details|
106
- if details["type"] == "king"
107
- king_locations << piece
108
- end
109
- end
110
- return king_locations
111
- end
112
-
113
-
114
- # Once a pawn reaches the end, this method is called to swap the pawn
115
- # for another piece (from the list below)
116
- def promote(p1)
117
- puts "Promote to: [Q]ueen, [K]night, [R]ook, [B]ishop"
118
- while true
119
- promo_piece = gets.chomp.downcase
120
- if promo_piece == "q" || promo_piece == "queen"
121
- @@piece_locations_buffer[p1]["type"] = "queen"
122
- break
123
- elsif promo_piece == "k" || promo_piece == "knight"
124
- @@piece_locations_buffer[p1]["type"] = "knight"
125
- break
126
- elsif promo_piece == "r" || promo_piece == "rook"
127
- @@piece_locations_buffer[p1]["type"] = "rook"
128
- break
129
- elsif promo_piece == "b" || promo_piece == "bishop"
130
- @@piece_locations_buffer[p1]["type"] = "bishop"
131
- break
132
- else
133
- puts "Please enter one of: [Q]ueen, [K]night, [R]ook, [B]ishop"
134
- end
135
- end
136
- end
137
-
138
- private :promote
139
-
140
- # Return whether the player of a specified color has their king currently in check
141
- # by checking the attack vectors of all the opponents players, versus the king location
142
- # Also, check whether king currently in check, has all of their valid moves within
143
- # their opponents attack vectors, and therefore are in checkmate (@@checkmate)
144
- def check?(color, proposed_manifest = @@piece_locations)
145
- path, king_loc = [], []
146
- enemy_color = (["black", "red"] - ["#{color}"]).first
147
-
148
- proposed_manifest.each do |piece, details|
149
- if details["color"] == enemy_color
150
- path << possible_moves(piece, proposed_manifest)
151
- end
152
- if details["color"] == color && details["type"] == "king"
153
- king_loc = piece
154
- end
155
- end
156
-
157
- danger_vector = path.flatten.uniq
158
- king_positions = possible_moves(king_loc, proposed_manifest)
159
-
160
- # If the King is in the attackable locations for the opposing player
161
- if danger_vector.include? king_loc
162
- # If all the positions the can move to is also attackable by the opposing player
163
- if (king_positions - danger_vector).length != 0
164
- # This is flawed. It verified whether the king could move out check
165
- # There are two other cases: whether a piece can remove the enemy
166
- # And whether the enemy's attack vector can be blocked
167
- #@@checkmate = true
168
- end
169
- return true
170
- # Piece not in check
171
- else
172
- return false
173
- end
174
- end
175
-
176
-
177
- # Board spaces that are attackable by opposing pieces
178
- # TODO: check? method should use this function
179
- def attack_vectors(color = @@player_turn, proposed_manifest = @@piece_locations)
180
- enemy_color = (["black", "red"] - ["#{color}"]).first
181
- kill_zone = []
182
-
183
- proposed_manifest.each do |piece, details|
184
- if details["color"] == enemy_color
185
- kill_zone << possible_moves(piece, proposed_manifest)
186
- end
187
- end
188
-
189
- kill_zone.flatten.uniq
190
- end
191
-
192
-
193
- # Reprint the board. Called after every valid piece move
194
- def board_refresh
195
- print_board(@@piece_locations)
196
- end
197
-
198
-
199
- # Convert index [A-H][1-8] => (1 - 64)
200
- def get_index_from_rowcol(row_col)
201
- offset = @@row_mappings[row_col[0]].to_i
202
- multiplier = row_col[1].to_i - 1
203
- return multiplier * 8 + offset
204
- end
205
-
206
-
207
- # Convert index (1 - 64) => [A-H][1-8]
208
- def get_rowcol_from_index(index)
209
- letter = get_col_from_index(index)
210
- number = get_row_from_index(index)
211
- "#{letter}#{number}"
212
- end
213
-
214
-
215
- # Intial setup of board. Put pieces into the expected locations
216
- def setup_board
217
- (1..64).each do |location|
218
- @@piece_locations[location] = {"type" => " ", "number" => nil, "color" => nil}
219
- end
220
-
221
- # Black Pieces
222
- @@piece_locations[1] = {"type" => "rook", "number" => 1, "color" => "black", "moved" => false}
223
- @@piece_locations[2] = {"type" => "knight", "number" => 1, "color" => "black", "moved" => false}
224
- @@piece_locations[3] = {"type" => "bishop", "number" => 1, "color" => "black", "moved" => false}
225
- @@piece_locations[4] = {"type" => "queen", "number" => 1, "color" => "black", "moved" => false}
226
- @@piece_locations[5] = {"type" => "king", "number" => 1, "color" => "black", "moved" => false}
227
- @@piece_locations[6] = {"type" => "bishop", "number" => 2, "color" => "black", "moved" => false}
228
- @@piece_locations[7] = {"type" => "knight", "number" => 2, "color" => "black", "moved" => false}
229
- @@piece_locations[8] = {"type" => "rook", "number" => 2, "color" => "black", "moved" => false}
230
- (1..8).each do |col|
231
- @@piece_locations[col + 8] = {"type" => "pawn", "number" => col, "color" => "black", "moved" => false}
232
- end
233
-
234
- # White Pieces
235
- @@piece_locations[57] = {"type" => "rook", "number" => 1, "color" => "red", "moved" => false}
236
- @@piece_locations[58] = {"type" => "knight", "number" => 1, "color" => "red", "moved" => false}
237
- @@piece_locations[59] = {"type" => "bishop", "number" => 1, "color" => "red", "moved" => false}
238
- @@piece_locations[60] = {"type" => "queen", "number" => 1, "color" => "red", "moved" => false}
239
- @@piece_locations[61] = {"type" => "king", "number" => 1, "color" => "red", "moved" => false}
240
- @@piece_locations[62] = {"type" => "bishop", "number" => 2, "color" => "red", "moved" => false}
241
- @@piece_locations[63] = {"type" => "knight", "number" => 2, "color" => "red", "moved" => false}
242
- @@piece_locations[64] = {"type" => "rook", "number" => 2, "color" => "red", "moved" => false}
243
- (1..8).each do |col|
244
- @@piece_locations[col + 48] = {"type" => "pawn", "number" => col, "color" => "red", "moved" => false}
245
- end
246
- end
247
-
248
-
249
- def piece_manifest
250
- return @@piece_locations
251
- end
252
-
253
- # Not currently used
254
- def taken_pieces
255
- return @@taken_pieces
256
- end
257
-
258
- def checkmate?
259
- return @@checkmate
260
- end
261
-
262
- def player_turn
263
- return @@player_turn
264
- end
265
-
266
- end