sapphire-chess 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +27 -1
- data/Gemfile.lock +1 -1
- data/README.md +2 -1
- data/lib/sapphire-chess/ai.rb +54 -24
- data/lib/sapphire-chess/board/board_general.rb +20 -23
- data/lib/sapphire-chess/display.rb +1 -1
- data/lib/sapphire-chess/human_input_validation.rb +14 -6
- data/lib/sapphire-chess/movement_rules/{pawn_movement_and_promotion.rb → pawn_movement_helpers_and_promotion.rb} +1 -14
- data/lib/sapphire-chess/openings_and_defenses.rb +15 -0
- data/lib/sapphire-chess/pieces/bishop.rb +6 -6
- data/lib/sapphire-chess/pieces/empty_square.rb +4 -0
- data/lib/sapphire-chess/pieces/knight.rb +4 -4
- data/lib/sapphire-chess/pieces/pawn.rb +19 -6
- data/lib/sapphire-chess/pieces/rook.rb +8 -8
- data/lib/sapphire-chess/player.rb +4 -0
- data/lib/sapphire-chess/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d026a9d0869d78ce30cc4ae4e761fe2f299f37d40f17f379ec19093f52b7993
|
4
|
+
data.tar.gz: 92def346caccfeaa7b7fa20b12c4d68625bc07f6e985167395a56351217e6075
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 90c2103e67d8f4e541d9ad20a2016a4e00b3f316eea71d1454fd0a39d3cd1460263d996a39244d2e64722a4c7a6f405b52f35999af145e95dcad165d4161e300
|
7
|
+
data.tar.gz: d217a64d520044a5fc8a09a8fed7bad5638ed3796d1947171749fde84c862170344f7d3a75d4e24bbb003c194c2dd426c32e6ff89d6cdb1f542d7b1d6f17a767
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
# 1.1.0 (January 25, 2023)
|
2
|
+
|
3
|
+
## Bug fixes:
|
4
|
+
|
5
|
+
- Fix `#get_move` invocation (correct: `#select_move`) in `human_input_validation.rb`.
|
6
|
+
- Pawns were not promoted correctly due to an error in `Pawn#available_moves`.
|
7
|
+
|
8
|
+
## Enhancement:
|
9
|
+
|
10
|
+
- Fine tune various pieces' location values for not hard difficulties
|
11
|
+
- The game now only allows legal movements. For example, when a player is in check,
|
12
|
+
the only valid movements are movements that move the player out of check.
|
13
|
+
- The white computer player now randomly chooses a classic opening, and the black computer player can answer with an appropriate defense.
|
14
|
+
|
15
|
+
## Documentation:
|
16
|
+
|
17
|
+
- Fix various typos in documentation.
|
18
|
+
|
19
|
+
## Style:
|
20
|
+
|
21
|
+
- I've abstracted logic in some methods to make them more readable, and changed a few variable names for clarity.
|
22
|
+
|
23
|
+
## Current worries:
|
24
|
+
|
25
|
+
- The hardest difficulty is still too slow, I'm studying how to improve the performance of the method, which builds recursively a huge n-tree.
|
26
|
+
|
1
27
|
# 1.0.1 (January 16, 2023)
|
2
28
|
|
3
29
|
## Enhancement:
|
@@ -13,6 +39,6 @@
|
|
13
39
|
|
14
40
|
# 1.0.0 (January 15, 2023)
|
15
41
|
|
16
|
-
Initial
|
42
|
+
Initial release.
|
17
43
|
|
18
44
|
Please, visit https://medium.com/@lucas.sorribes/nostromo-my-ruby-chess-journey-part-i-7ef544b547a5 for a very detailed account of how I wrote this game.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
# Sapphire Chess
|
1
|
+
# Sapphire Chess
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/sapphire-chess.svg?)](https://badge.fury.io/rb/sapphire-chess)
|
2
3
|
|
3
4
|
Sapphire Chess is a command line-based chess game with an algebraic notation input system,
|
4
5
|
complete chess rules, a beautiful interface and a functional AI. It provides three game modes:
|
data/lib/sapphire-chess/ai.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
require_relative 'openings_and_defenses'
|
2
|
+
|
1
3
|
module AI
|
4
|
+
include OpeningsAndDefenses
|
5
|
+
|
2
6
|
private
|
3
7
|
|
4
8
|
# Chooses move by best possible outcome:
|
5
9
|
def computer_chooses_move
|
10
|
+
return first_move(color) if first_turn?
|
11
|
+
|
6
12
|
possible_moves = board.generate_moves(color)
|
7
13
|
possible_moves << %i[castle king] if castle_rights?(:king)
|
8
14
|
possible_moves << %i[castle queen] if castle_rights?(:queen)
|
@@ -10,13 +16,37 @@ module AI
|
|
10
16
|
best_move(possible_moves)
|
11
17
|
end
|
12
18
|
|
19
|
+
def first_move(color)
|
20
|
+
if color == :white then opening
|
21
|
+
else
|
22
|
+
defense
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def opening
|
27
|
+
opening =
|
28
|
+
case rand(1..100)
|
29
|
+
when OPENINGS[:nf3][:probabilty] then :nf3
|
30
|
+
when OPENINGS[:e4][:probabilty] then :e4
|
31
|
+
when OPENINGS[:d4][:probabilty] then :d4
|
32
|
+
when OPENINGS[:c4][:probabilty] then :c4
|
33
|
+
end
|
34
|
+
|
35
|
+
OPENINGS[opening][:move]
|
36
|
+
end
|
37
|
+
|
38
|
+
def defense
|
39
|
+
DEFENSES[board.white_player.history.last] ||
|
40
|
+
best_move(board.generate_moves(:black))
|
41
|
+
end
|
42
|
+
|
13
43
|
def best_move(possible_moves)
|
14
44
|
evaluations = {}
|
15
45
|
anti_loop_filter(possible_moves)
|
16
46
|
|
17
47
|
possible_moves.each do |move|
|
18
|
-
evaluations[move] =
|
19
|
-
|
48
|
+
evaluations[move] =
|
49
|
+
minimax(move, depth, -Float::INFINITY, Float::INFINITY, maximizing_player?)
|
20
50
|
end
|
21
51
|
|
22
52
|
move_randomizer(evaluations)
|
@@ -27,29 +57,29 @@ module AI
|
|
27
57
|
return board.evaluate if depth.zero?
|
28
58
|
|
29
59
|
board.provisional(move, color) do
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
best_minimizing_evaluation
|
41
|
-
else
|
42
|
-
best_maximizing_evaluation = -Float::INFINITY
|
43
|
-
|
44
|
-
board.generate_moves(:white).each do |possible_move|
|
45
|
-
evaluation = minimax(possible_move, depth - 1, alpha, beta, true)
|
46
|
-
best_maximizing_evaluation = [best_maximizing_evaluation, evaluation].max
|
47
|
-
alpha = [alpha, evaluation].max
|
48
|
-
break if beta <= alpha
|
49
|
-
end
|
50
|
-
|
51
|
-
best_maximizing_evaluation
|
60
|
+
if maximizing_player
|
61
|
+
best_minimizing_evaluation = Float::INFINITY
|
62
|
+
|
63
|
+
board.generate_moves(:black).each do |possible_move|
|
64
|
+
evaluation = minimax(possible_move, depth - 1, alpha, beta, false)
|
65
|
+
best_minimizing_evaluation = [best_minimizing_evaluation, evaluation].min
|
66
|
+
beta = [beta, evaluation].min
|
67
|
+
break if beta <= alpha
|
52
68
|
end
|
69
|
+
|
70
|
+
best_minimizing_evaluation
|
71
|
+
else
|
72
|
+
best_maximizing_evaluation = -Float::INFINITY
|
73
|
+
|
74
|
+
board.generate_moves(:white).each do |possible_move|
|
75
|
+
evaluation = minimax(possible_move, depth - 1, alpha, beta, true)
|
76
|
+
best_maximizing_evaluation = [best_maximizing_evaluation, evaluation].max
|
77
|
+
alpha = [alpha, evaluation].max
|
78
|
+
break if beta <= alpha
|
79
|
+
end
|
80
|
+
|
81
|
+
best_maximizing_evaluation
|
82
|
+
end
|
53
83
|
end
|
54
84
|
end
|
55
85
|
|
@@ -1,9 +1,8 @@
|
|
1
1
|
require_relative '../pieces'
|
2
|
+
require_relative '../board'
|
2
3
|
require_relative '../movement_rules/castling_board_control'
|
3
4
|
require_relative '../movement_rules/en_passant_board_control'
|
4
|
-
require_relative '../
|
5
|
-
require_relative '../board/board_evaluation'
|
6
|
-
require_relative '../board/board_provisional_moves'
|
5
|
+
require_relative '../algebraic_conversion'
|
7
6
|
|
8
7
|
class Board
|
9
8
|
SQUARE_ORDER = 8
|
@@ -11,6 +10,7 @@ class Board
|
|
11
10
|
W_PAWN_ROW = 6
|
12
11
|
FIRST_ROW = 0
|
13
12
|
LAST_ROW = 7
|
13
|
+
MIN_FOR_HARD_DIFFICULTY = 2
|
14
14
|
PIECES_SEQUENCE = [
|
15
15
|
Rook, Knight, Bishop, Queen, King, Bishop, Knight, Rook
|
16
16
|
].freeze
|
@@ -20,8 +20,9 @@ class Board
|
|
20
20
|
include ProvisionalMoves
|
21
21
|
include CastlingBoardControl
|
22
22
|
include EnPassantBoardControl
|
23
|
+
include AlgebraicConversion
|
23
24
|
|
24
|
-
attr_reader :matrix, :white_player, :black_player
|
25
|
+
attr_reader :matrix, :white_player, :black_player
|
25
26
|
|
26
27
|
def self.initialize_board
|
27
28
|
board = new(duplicated: false)
|
@@ -38,7 +39,7 @@ class Board
|
|
38
39
|
def set_pawns(board)
|
39
40
|
[B_PAWN_ROW, W_PAWN_ROW].each do |pawn_row|
|
40
41
|
color = pawn_row == B_PAWN_ROW ? :black : :white
|
41
|
-
|
42
|
+
|
42
43
|
SQUARE_ORDER.times do |column|
|
43
44
|
board[[pawn_row, column]] = Pawn.new(board, [pawn_row, column], color)
|
44
45
|
end
|
@@ -96,7 +97,7 @@ class Board
|
|
96
97
|
self[target_square].location = target_square
|
97
98
|
|
98
99
|
return unless permanent && was_en_passant?(piece, target_square)
|
99
|
-
|
100
|
+
|
100
101
|
capture_passed_pawn!(target_square)
|
101
102
|
end
|
102
103
|
|
@@ -110,16 +111,17 @@ class Board
|
|
110
111
|
end
|
111
112
|
|
112
113
|
def generate_moves(color)
|
113
|
-
possible_moves =
|
114
114
|
friendly_pieces(color).each_with_object([]) do |piece, possible_moves|
|
115
|
-
location = piece.location
|
116
115
|
|
117
|
-
piece.
|
118
|
-
|
116
|
+
current_piece_location = piece.location
|
117
|
+
|
118
|
+
piece.available_moves.each do |possible_target_square|
|
119
|
+
|
120
|
+
move = [current_piece_location, possible_target_square]
|
121
|
+
|
122
|
+
possible_moves << move if legal_move?(piece, possible_target_square)
|
119
123
|
end
|
120
124
|
end
|
121
|
-
# sort_moves!(possible_moves, color)
|
122
|
-
possible_moves
|
123
125
|
end
|
124
126
|
|
125
127
|
# This method is avoids checking for availability of en passant
|
@@ -132,24 +134,19 @@ class Board
|
|
132
134
|
self.hard_difficulty =
|
133
135
|
[white_player, black_player].find do |player|
|
134
136
|
player.is_a?(Computer)
|
135
|
-
end.depth
|
137
|
+
end.depth >= MIN_FOR_HARD_DIFFICULTY
|
136
138
|
end
|
137
139
|
|
138
140
|
def hard_difficulty?
|
139
|
-
hard_difficulty
|
141
|
+
@hard_difficulty
|
140
142
|
end
|
141
143
|
|
142
144
|
private
|
143
145
|
|
144
146
|
attr_writer :hard_difficulty
|
145
|
-
|
146
|
-
def
|
147
|
-
|
148
|
-
|
149
|
-
evaluate_move(a, color) <=> evaluate_move(b, color)
|
150
|
-
else
|
151
|
-
evaluate_move(b, color) <=> evaluate_move(a, color)
|
152
|
-
end
|
153
|
-
end
|
147
|
+
|
148
|
+
def legal_move?(piece, target_square)
|
149
|
+
color = piece.color
|
150
|
+
!in_check?(color) || (in_check?(color) && piece.safe_moves.include?(target_square))
|
154
151
|
end
|
155
152
|
end
|
@@ -68,7 +68,7 @@ module HumanInputValidation
|
|
68
68
|
target_square = nil
|
69
69
|
puts "Where do you want to move the #{board[piece].class}?"
|
70
70
|
loop do
|
71
|
-
target_square = current_player.
|
71
|
+
target_square = current_player.select_move
|
72
72
|
break if valid_target_square?(piece, target_square)
|
73
73
|
|
74
74
|
puts "The #{board[piece].class} selected can't move to that square."
|
@@ -96,13 +96,21 @@ module HumanInputValidation
|
|
96
96
|
player_move_input.first.is_a?(Integer)
|
97
97
|
end
|
98
98
|
|
99
|
-
def valid_piece_selection?(
|
100
|
-
board[
|
101
|
-
|
99
|
+
def valid_piece_selection?(piece_location)
|
100
|
+
piece = board[piece_location]
|
101
|
+
|
102
|
+
piece.is_a?(Piece) &&
|
103
|
+
piece.color == current_player.color &&
|
104
|
+
!piece.available_moves.empty? &&
|
105
|
+
(!board.in_check?(current_player.color) || board.in_check?(current_player.color) && !piece.safe_moves.empty?)
|
102
106
|
end
|
103
107
|
|
104
|
-
def valid_target_square?(
|
105
|
-
board[
|
108
|
+
def valid_target_square?(piece_location, target_square)
|
109
|
+
piece = board[piece_location]
|
110
|
+
valid_target = piece.available_moves.include?(target_square)
|
111
|
+
|
112
|
+
(valid_target && !board.in_check?(current_player.color)) ||
|
113
|
+
(valid_target && board.in_check?(current_player.color) && piece.safe_moves.include?(target_square))
|
106
114
|
end
|
107
115
|
|
108
116
|
def valid_castling?(side)
|
@@ -1,17 +1,4 @@
|
|
1
|
-
module
|
2
|
-
def available_moves
|
3
|
-
if promoted? then SlidePattern::available_moves
|
4
|
-
else
|
5
|
-
moves = []
|
6
|
-
add_one_square_movement!(moves)
|
7
|
-
add_two_square_movement!(moves)
|
8
|
-
add_diagonal_movement!(moves)
|
9
|
-
add_en_passant_movement!(moves)
|
10
|
-
|
11
|
-
moves.select { |move| board.within_limits?(move) }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
1
|
+
module PawnMovementHelpersAndPromotion
|
15
2
|
def promoted?
|
16
3
|
@promoted
|
17
4
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OpeningsAndDefenses
|
2
|
+
OPENINGS = {
|
3
|
+
nf3: { probabilty: (1..50), move: [[7, 6], [5, 5]] }, # Most flexible white opening favored by many
|
4
|
+
e4: { probabilty: (51..75), move: [[6, 4], [4, 4]] }, # The best and most famous white opening.
|
5
|
+
d4: { probabilty: (76..90), move: [[6, 3], [4, 3]] }, # This can lead to the Queen's Gambit
|
6
|
+
c4: { probabilty: (91..100), move: [[6, 2], [4, 2]] }
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
DEFENSES = {
|
10
|
+
[[7, 6], [5, 5]] => [[[1, 2], [3, 2]], [[0, 6], [2, 5]]].sample, # Answers to 1.nf3
|
11
|
+
[[6, 4], [4, 4]] => [[[1, 2], [3, 2]], [[1, 4], [3, 4]]].sample, # Answers to 1.e4
|
12
|
+
[[6, 3], [4, 3]] => [[[0, 6], [2, 5]], [[1, 2], [2, 2]]].sample, # Answers to 1.d4
|
13
|
+
[[6, 2], [4, 2]] => [[[1, 2], [3, 2]], [[1, 4], [3, 4]]].sample # Answers to 1.c4
|
14
|
+
}.freeze
|
15
|
+
end
|
@@ -34,9 +34,9 @@ class Bishop < Piece
|
|
34
34
|
[-20, -10, -10, -10, -10, -10, -10, -20],
|
35
35
|
[-10, 0, 0, 0, 0, 0, 0, -10],
|
36
36
|
[-10, 0, 5, 15, 15, 5, 0, -10],
|
37
|
-
[-10, 5, 5,
|
38
|
-
[-10, 0,
|
39
|
-
[-10, 10,
|
37
|
+
[-10, 5, 5, 50, 50, 5, 5, -10],
|
38
|
+
[-10, 0, 20, 50, 50, 20, 0, -10],
|
39
|
+
[-10, 10, 20, 50, 50, 20, 10, -10],
|
40
40
|
[-10, 5, 0, 0, 0, 0, 5, -10],
|
41
41
|
[-20, -10, -10, -10, -10, -10, -10, -20]
|
42
42
|
].freeze
|
@@ -44,9 +44,9 @@ class Bishop < Piece
|
|
44
44
|
BLACK_LOCATION_VALUE_EASY = [
|
45
45
|
[-20, -10, -10, -10, -10, -10, -10, -20],
|
46
46
|
[-10, 5, 0, 0, 0, 0, 5, -10],
|
47
|
-
[-10, 10,
|
48
|
-
[-10, 0,
|
49
|
-
[-10, 5, 5,
|
47
|
+
[-10, 10, 20, 50, 50, 20, 10, -10],
|
48
|
+
[-10, 0, 20, 50, 50, 20, 0, -10],
|
49
|
+
[-10, 5, 5, 50, 50, 5, 5, -10],
|
50
50
|
[-10, 0, 5, 15, 15, 5, 0, -10],
|
51
51
|
[-10, 0, 0, 0, 0, 0, 0, -10],
|
52
52
|
[-20, -10, -10, -10, -10, -10, -10, -20]
|
@@ -35,8 +35,8 @@ class Knight < Piece
|
|
35
35
|
[-50, -40, -30, -30, -30, -30, -40, -50],
|
36
36
|
[-40, -20, 0, 0, 0, 0, -20, -40],
|
37
37
|
[-30, 0, 20, 25, 25, 20, 0, -30],
|
38
|
-
[-30, 5, 25,
|
39
|
-
[-30, 0, 25,
|
38
|
+
[-30, 5, 25, 50, 50, 25, 5, -30],
|
39
|
+
[-30, 0, 25, 50, 50, 25, 0, -30],
|
40
40
|
[-30, 5, 20, 25, 25, 20, 5, -30],
|
41
41
|
[-40, -20, 0, 5, 5, 0, -20, -40],
|
42
42
|
[-50, -40, -30, -30, -30, -30, -40, -50]
|
@@ -46,8 +46,8 @@ class Knight < Piece
|
|
46
46
|
[-50, -40, -30, -30, -30, -30, -40, -50],
|
47
47
|
[-40, -20, 0, 5, 5, 0, -20, -40],
|
48
48
|
[-30, 0, 20, 25, 25, 20, 0, -30],
|
49
|
-
[-30, 5, 25,
|
50
|
-
[-30, 0, 25,
|
49
|
+
[-30, 5, 25, 50, 50, 25, 5, -30],
|
50
|
+
[-30, 0, 25, 50, 50, 25, 0, -30],
|
51
51
|
[-30, 5, 20, 25, 25, 20, 5, -30],
|
52
52
|
[-40, -20, 0, 0, 0, 0, -20, -40],
|
53
53
|
[-50, -40, -30, -30, -30, -30, -40, -50]
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require_relative '../movement_rules/en_passant_piece_control'
|
2
|
-
require_relative '../movement_rules/
|
2
|
+
require_relative '../movement_rules/pawn_movement_helpers_and_promotion'
|
3
3
|
|
4
4
|
class Pawn < Piece
|
5
5
|
BLACK = ['♟', '♛'].freeze
|
@@ -42,8 +42,8 @@ class Pawn < Piece
|
|
42
42
|
[60, 60, 60, 60, 60, 60, 60, 60],
|
43
43
|
[50, 50, 60, 60, 60, 60, 50, 50],
|
44
44
|
[50, 50, 60, 60, 60, 60, 50, 50],
|
45
|
-
[50, 50, 60,
|
46
|
-
[50, 40, 10,
|
45
|
+
[50, 50, 60, 60, 60, 60, 50, 50],
|
46
|
+
[50, 40, 10, 70, 70, 10, 40, 50],
|
47
47
|
[5, 10, 10, -20, -20, 10, 10, 5],
|
48
48
|
[0, 0, 0, 0, 0, 0, 0, 0]
|
49
49
|
].freeze
|
@@ -51,8 +51,8 @@ class Pawn < Piece
|
|
51
51
|
BLACK_LOCATION_VALUE_EASY = [
|
52
52
|
[0, 0, 0, 0, 0, 0, 0, 0],
|
53
53
|
[5, 10, 10, -20, -20, 10, 10, 5],
|
54
|
-
[50, 40, 10,
|
55
|
-
[50, 50, 60,
|
54
|
+
[50, 40, 10, 70, 70, 10, 40, 50],
|
55
|
+
[50, 50, 60, 60, 60, 60, 50, 50],
|
56
56
|
[50, 50, 60, 60, 60, 60, 50, 50],
|
57
57
|
[50, 50, 60, 60, 60, 60, 50, 50],
|
58
58
|
[60, 60, 60, 60, 60, 60, 60, 60],
|
@@ -61,7 +61,7 @@ class Pawn < Piece
|
|
61
61
|
|
62
62
|
include SlidePattern
|
63
63
|
include EnPassantPieceControl
|
64
|
-
include
|
64
|
+
include PawnMovementHelpersAndPromotion
|
65
65
|
|
66
66
|
def initialize(board, location, color)
|
67
67
|
super(board, location, color)
|
@@ -79,4 +79,17 @@ class Pawn < Piece
|
|
79
79
|
Paint[self.class::BLACK.first, :blue]
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
def available_moves
|
84
|
+
if promoted? then super
|
85
|
+
else
|
86
|
+
moves = []
|
87
|
+
add_one_square_movement!(moves)
|
88
|
+
add_two_square_movement!(moves)
|
89
|
+
add_diagonal_movement!(moves)
|
90
|
+
add_en_passant_movement!(moves)
|
91
|
+
|
92
|
+
moves.select { |move| board.within_limits?(move) }
|
93
|
+
end
|
94
|
+
end
|
82
95
|
end
|
@@ -33,10 +33,10 @@ class Rook < Piece
|
|
33
33
|
WHITE_LOCATION_VALUE_EASY = [
|
34
34
|
[0, 0, 0, 0, 0, 0, 0, 0],
|
35
35
|
[5, 10, 10, 10, 10, 10, 10, 5],
|
36
|
-
[-5,
|
37
|
-
[-5,
|
38
|
-
[-5,
|
39
|
-
[-5,
|
36
|
+
[-5, 5, 10, 10, 10, 5, 0, -5],
|
37
|
+
[-5, 5, 10, 10, 10, 5, 0, -5],
|
38
|
+
[-5, 5, 10, 10, 10, 5, 0, -5],
|
39
|
+
[-5, 5, 10, 10, 10, 5, 0, -5],
|
40
40
|
[-5, 0, 0, 0, 0, 0, 0, -5],
|
41
41
|
[0, 0, 0, 5, 5, 0, 0, 0]
|
42
42
|
].freeze
|
@@ -44,10 +44,10 @@ class Rook < Piece
|
|
44
44
|
BLACK_LOCATION_VALUE_EASY = [
|
45
45
|
[0, 0, 0, 5, 5, 0, 0, 0],
|
46
46
|
[-5, 0, 0, 0, 0, 0, 0, -5],
|
47
|
-
[-5, 0,
|
48
|
-
[-5, 0,
|
49
|
-
[-5, 0,
|
50
|
-
[-5, 0,
|
47
|
+
[-5, 0, 5, 10, 10, 5, 0, -5],
|
48
|
+
[-5, 0, 5, 10, 10, 5, 0, -5],
|
49
|
+
[-5, 0, 5, 10, 10, 5, 0, -5],
|
50
|
+
[-5, 0, 5, 10, 10, 5, 0, -5],
|
51
51
|
[5, 10, 10, 10, 10, 10, 10, 5],
|
52
52
|
[0, 0, 0, 0, 0, 0, 0, 0]
|
53
53
|
].freeze
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sapphire-chess
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lucas Sorribes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-01-
|
11
|
+
date: 2023-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: paint
|
@@ -104,7 +104,8 @@ files:
|
|
104
104
|
- lib/sapphire-chess/movement_rules/en_passant_piece_control.rb
|
105
105
|
- lib/sapphire-chess/movement_rules/move_slide_pattern.rb
|
106
106
|
- lib/sapphire-chess/movement_rules/move_step_pattern.rb
|
107
|
-
- lib/sapphire-chess/movement_rules/
|
107
|
+
- lib/sapphire-chess/movement_rules/pawn_movement_helpers_and_promotion.rb
|
108
|
+
- lib/sapphire-chess/openings_and_defenses.rb
|
108
109
|
- lib/sapphire-chess/pieces.rb
|
109
110
|
- lib/sapphire-chess/pieces/bishop.rb
|
110
111
|
- lib/sapphire-chess/pieces/empty_square.rb
|
@@ -136,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
136
137
|
- !ruby/object:Gem::Version
|
137
138
|
version: '0'
|
138
139
|
requirements: []
|
139
|
-
rubygems_version: 3.
|
140
|
+
rubygems_version: 3.4.4
|
140
141
|
signing_key:
|
141
142
|
specification_version: 4
|
142
143
|
summary: Command line-based chess game
|