From b1e2c8e1fda7cd75f482ba8edfef12112d631021 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Fri, 29 Jul 2016 21:54:32 +0000 Subject: [PATCH 01/32] Add move_number to games table --- db/migrate/20160729214941_add_move_number_to_games.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20160729214941_add_move_number_to_games.rb diff --git a/db/migrate/20160729214941_add_move_number_to_games.rb b/db/migrate/20160729214941_add_move_number_to_games.rb new file mode 100644 index 0000000..8b0a63e --- /dev/null +++ b/db/migrate/20160729214941_add_move_number_to_games.rb @@ -0,0 +1,5 @@ +class AddMoveNumberToGames < ActiveRecord::Migration[5.0] + def change + add_column :games, :move_number, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 66d69bc..f89347e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160726151316) do +ActiveRecord::Schema.define(version: 20160729214941) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -24,6 +24,7 @@ t.integer "player_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "move_number" end create_table "pieces", force: :cascade do |t| From 541874418edb05f56289a8634a71ab4a723a0913 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Fri, 29 Jul 2016 22:18:35 +0000 Subject: [PATCH 02/32] En Passant first attempt --- app/models/pawn.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 2a5bc46..400c5a8 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -49,4 +49,20 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end + + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + def en_passant?(x, y) + return false unless clear_two_forward_move(x, y) + end + + def en_passant_pawn?(x, y) + side_piece = find_piece(x, y) + return false if side_piece.nil? + return true if side_piece.type == 'Pawn' && side_piece.color != color + false + end end From 00755cc3f5706ff5d2bf5844f9ce29d0d7593fae Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:01:42 +0000 Subject: [PATCH 03/32] Add first_turn logic to game model --- app/models/game.rb | 6 +++++- app/models/pawn.rb | 8 ++++++-- db/migrate/20160730005057_add_en_passant_to_games.rb | 5 +++++ .../20160730144006_change_turn_type_to_string.rb | 5 +++++ db/schema.rb | 9 +++++---- spec/models/game_spec.rb | 12 ++++++++++++ 6 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20160730005057_add_en_passant_to_games.rb create mode 100644 db/migrate/20160730144006_change_turn_type_to_string.rb diff --git a/app/models/game.rb b/app/models/game.rb index 966195f..aa03406 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -4,7 +4,7 @@ class Game < ActiveRecord::Base has_many :players after_create :populate_bishops!, :populate_rooks!, :populate_pawns!,\ - :populate_knights!, :populate_queens_kings! + :populate_knights!, :populate_queens_kings!, :first_turn! def populate_bishops! pieces.create(type: 'Bishop', x_position: 2, y_position: 7, color: 'white') @@ -42,4 +42,8 @@ def populate_queens_kings! pieces.create(type: 'Queen', x_position: 3, y_position: 0, color: 'black') pieces.create(type: 'King', x_position: 4, y_position: 0, color: 'black') end + + def first_turn! + update(turn: 'white', move_number: 1) + end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 400c5a8..c70525c 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -56,13 +56,17 @@ def forward_capture?(x, y) # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis def en_passant?(x, y) - return false unless clear_two_forward_move(x, y) + return false unless en_passant_pawn?(x, y) end - def en_passant_pawn?(x, y) + def en_passant_pawn?(x, y, horizontal) side_piece = find_piece(x, y) return false if side_piece.nil? return true if side_piece.type == 'Pawn' && side_piece.color != color false end + + def last_moved_piece + game.pieces.find_by(game.move_number - 1) + end end diff --git a/db/migrate/20160730005057_add_en_passant_to_games.rb b/db/migrate/20160730005057_add_en_passant_to_games.rb new file mode 100644 index 0000000..2c712d5 --- /dev/null +++ b/db/migrate/20160730005057_add_en_passant_to_games.rb @@ -0,0 +1,5 @@ +class AddEnPassantToGames < ActiveRecord::Migration[5.0] + def change + add_column :games, :en_passant, :boolean, default: false + end +end diff --git a/db/migrate/20160730144006_change_turn_type_to_string.rb b/db/migrate/20160730144006_change_turn_type_to_string.rb new file mode 100644 index 0000000..5f1ed28 --- /dev/null +++ b/db/migrate/20160730144006_change_turn_type_to_string.rb @@ -0,0 +1,5 @@ +class ChangeTurnTypeToString < ActiveRecord::Migration[5.0] + def change + change_column :games, :turn, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index f89347e..a74a049 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160729214941) do +ActiveRecord::Schema.define(version: 20160730144006) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,12 +19,13 @@ t.string "winning_player" t.string "game_status" t.integer "counter" - t.integer "turn" + t.string "turn" t.integer "user_id" t.integer "player_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "move_number" + t.boolean "en_passant", default: false end create_table "pieces", force: :cascade do |t| diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 6f14e84..88b89a2 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -7,17 +7,29 @@ it 'should give us 32 pieces upon board population' do expect(game.pieces.count).to eq 32 end + it 'should give me the last x position of population' do expect(game.pieces.last.x_position).to eq 4 end + it 'should give me the last y position of population' do expect(game.pieces.last.y_position).to eq 0 end + it 'should give me the last piece of the population as the King' do expect(game.pieces.last.type).to eq 'King' end + it 'should give me the last pieces color' do expect(game.pieces.last.color).to eq 'black' end + + it 'should show first turn of game belong to white player' do + expect(game.turn).to eq 'white' + end + + it 'should show move number as 1' do + expect(game.move_number).to eq 1 + end end end From ff0f3b76cc51e59e57c39346e3a74147149bc7c1 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:41:00 +0000 Subject: [PATCH 04/32] integrate end_turn! into move! & pass all tests --- app/models/game.rb | 5 +++++ app/models/piece.rb | 1 + spec/models/piece_spec.rb | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/app/models/game.rb b/app/models/game.rb index aa03406..788e832 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -46,4 +46,9 @@ def populate_queens_kings! def first_turn! update(turn: 'white', move_number: 1) end + + def end_turn! + increment!(:move_number) + move_number % 2 == 0 ? update(turn: 'black') : update(turn: 'white') + end end diff --git a/app/models/piece.rb b/app/models/piece.rb index 6ad61cf..7d07106 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -26,6 +26,7 @@ def move!(x, y) capture!(victim) end update(x_position: x, y_position: y, moved: true) + game.end_turn! true end diff --git a/spec/models/piece_spec.rb b/spec/models/piece_spec.rb index ea5f728..781f50c 100644 --- a/spec/models/piece_spec.rb +++ b/spec/models/piece_spec.rb @@ -31,6 +31,8 @@ expect(victim.x_position).to eq nil expect(victim.y_position).to eq nil expect(victim.captured).to eq true + expect(game.move_number).to eq 2 + expect(game.turn).to eq 'black' end it 'should return false on a move against a friendly piece' do @@ -43,6 +45,8 @@ expect(victim.x_position).to eq 3 expect(victim.y_position).to eq 6 expect(victim.captured).to eq nil + expect(game.move_number).to eq 1 + expect(game.turn).to eq 'white' end end end From d8db2edbba7dcf5eef104eccaa8a5df6727bcfd5 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:42:12 +0000 Subject: [PATCH 05/32] add end_turn! tests in game_spec.rb and pass all tests --- spec/models/game_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 88b89a2..37318fe 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -32,4 +32,21 @@ expect(game.move_number).to eq 1 end end + + describe "end_turn!" do + game = FactoryGirl.create(:game) + + it 'should increment move_number by 1 once the turn ended' do + game.end_turn! + + expect(game.move_number).to eq 2 + end + + it 'should switch turn between black and white player' do + game.reload + game.end_turn! + + expect(game.turn).to eq 'black' + end + end end From 3fc6f0064298d694ee45e2252bfc012b8f43b858 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 17:21:36 +0000 Subject: [PATCH 06/32] En Passsant Logic 2nd attempt --- app/models/pawn.rb | 18 +++++++++------- spec/models/pawn_spec.rb | 45 ++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index c70525c..18663e7 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -7,7 +7,14 @@ class Pawn < Piece # and thus ignored. Diagonal attack not implemented. def valid_move?(x, y) (moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && - !forward_capture?(x, y) + !forward_capture?(x, y) + end + + def en_passant?(x, y) + return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' + return false unless valid_en_passant_pawn?(x, y, horizontal_difference) + update(en_passant: true) + true end # Updates the piece's type from Pawn to the new type @@ -55,18 +62,15 @@ def forward_capture?(x, y) # 2)only capture within the next turn # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis - def en_passant?(x, y) - return false unless en_passant_pawn?(x, y) - end - def en_passant_pawn?(x, y, horizontal) - side_piece = find_piece(x, y) + def valid_passant_pawn?(x, y, horizontal_difference) + side_piece = occupant_piece(x, y + (horizontal_difference ? -1 : 1)) return false if side_piece.nil? return true if side_piece.type == 'Pawn' && side_piece.color != color false end def last_moved_piece - game.pieces.find_by(game.move_number - 1) + game.pieces.find_by(game.move_number - 1 || game.move_number == 0) end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index ed2539a..b3281aa 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -4,31 +4,32 @@ let(:game) { FactoryGirl.create(:game) } let(:pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 5, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 5, + y_position: 6 ) end let(:moved_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 3, - y_position: 4, - moved: true + type: 'Pawn', + color: 'white', + x_position: 3, + y_position: 4, + moved: true ) end describe 'creation' do it 'should create a white pawn' do pawn = FactoryGirl.create(:pawn, color: 'white') + expect(pawn.type).to eq('Pawn') end it 'should fail to create a red pawn' do expect { FactoryGirl.create(:pawn, color: 'red') }.to\ - raise_error(ActiveRecord::RecordInvalid) + raise_error(ActiveRecord::RecordInvalid) end end @@ -90,11 +91,12 @@ describe 'obstructed move' do it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) + expect(pawn.move!(5, 4)).to eq false expect(pawn.x_position).to eq 5 expect(pawn.y_position).to eq 6 @@ -103,15 +105,22 @@ it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) + expect(pawn.move!(5, 5)).to eq false expect(pawn.x_position).to eq 5 expect(pawn.y_position).to eq 6 expect(pawn.moved).to eq false end end + + describe "en_passant?" do + it 'should return false if no piece is found adjacent to the piece' do + expect(pawn.en_passant?(3, 4)).to eq false + end + end end From 4bad9e03adc8afe7e56b7b9b5975047a80487e65 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 19:48:34 +0000 Subject: [PATCH 07/32] refactor en passant logics --- app/models/pawn.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 18663e7..ad7155e 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,4 +1,5 @@ # Pawn behavior. +require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or else a regular forward move, @@ -71,6 +72,7 @@ def valid_passant_pawn?(x, y, horizontal_difference) end def last_moved_piece - game.pieces.find_by(game.move_number - 1 || game.move_number == 0) + binding.pry + game.pieces.find_by(game.move_number - 1) end end From 11ad23cac1b72fcc42b9845b89b0364d89c29db4 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 02:36:37 +0000 Subject: [PATCH 08/32] add en_passant left and right pawn logic --- app/models/pawn.rb | 51 ++++++++++++------- app/models/piece.rb | 16 +++--- ...59_add_last_moved_piece_to_pieces_table.rb | 5 ++ db/schema.rb | 5 +- spec/models/pawn_spec.rb | 22 +++++++- 5 files changed, 69 insertions(+), 30 deletions(-) create mode 100644 db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb diff --git a/app/models/pawn.rb b/app/models/pawn.rb index ad7155e..00f43b0 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -12,12 +12,43 @@ def valid_move?(x, y) end def en_passant?(x, y) + return false if last_moved_piece.nil? return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' - return false unless valid_en_passant_pawn?(x, y, horizontal_difference) + return false unless valid_en_passant_pawn?(x, y) update(en_passant: true) true end + def valid_en_passant_pawn?(x, y) + return false unless valid_passant_pawn_left?(x, y) + return false unless valid_passant_pawn_right?(x. y) + false + end + + def valid_passant_pawn_left?(x, y) + left_piece = find_piece(x - 1, y) + return false if left_piece.nil? + return true if left_piece.type == 'Pawn' && side_piece.color != color + false + end + + def valid_passant_pawn_right?(x, y) + right_piece = find_piece(x + 1, y) + return false if right_piece.nil? + return true if right_piece.type == 'Pawn' && side_piece.color != color + false + end + + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + + def last_moved_piece + game.pieces.where(last_moved_piece: game.move_number - 1).take + end + # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -57,22 +88,4 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end - - # En Passant Logic: - # 1)target pawn just moved 2 space forward - # 2)only capture within the next turn - # 3)can only capture by opponent's pawn - # 4)opponent pawn must be on the left or right of target piece's y axis - - def valid_passant_pawn?(x, y, horizontal_difference) - side_piece = occupant_piece(x, y + (horizontal_difference ? -1 : 1)) - return false if side_piece.nil? - return true if side_piece.type == 'Pawn' && side_piece.color != color - false - end - - def last_moved_piece - binding.pry - game.pieces.find_by(game.move_number - 1) - end end diff --git a/app/models/piece.rb b/app/models/piece.rb index 7d07106..c1a5413 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -25,11 +25,18 @@ def move!(x, y) return false unless enemy?(victim) capture!(victim) end - update(x_position: x, y_position: y, moved: true) + update(x_position: x, y_position: y, moved: true, last_moved_piece: game.move_number) game.end_turn! true end + # Compares a piece's y_position with the + # coordinate provided and returns the + # distance between the two. + def y_distance(new_y_coordinate) + (y_position - new_y_coordinate).abs + end + # All validation assumes white player is on the # 6-7 rows of the array, and black player is on # 0-1 rows of the array. @@ -58,13 +65,6 @@ def x_distance(new_x_coordinate) (x_position - new_x_coordinate).abs end - # Compares a piece's y_position with the - # coordinate provided and returns the - # distance between the two. - def y_distance(new_y_coordinate) - (y_position - new_y_coordinate).abs - end - # Returns true if the coordinates provided # are different from the piece's starting # position. diff --git a/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb b/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb new file mode 100644 index 0000000..8d83960 --- /dev/null +++ b/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb @@ -0,0 +1,5 @@ +class AddLastMovedPieceToPiecesTable < ActiveRecord::Migration[5.0] + def change + add_column :pieces, :last_moved_piece, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index a74a049..73515e6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160730144006) do +ActiveRecord::Schema.define(version: 20160730194959) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -39,7 +39,8 @@ t.boolean "checkmate" t.datetime "created_at" t.datetime "updated_at" - t.boolean "moved", default: false + t.boolean "moved", default: false + t.integer "last_moved_piece" end create_table "players", force: :cascade do |t| diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index b3281aa..0ded4fe 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -1,5 +1,5 @@ require 'rails_helper' - +require 'pry' RSpec.describe Pawn, type: :model do let(:game) { FactoryGirl.create(:game) } let(:pawn) do @@ -122,5 +122,25 @@ it 'should return false if no piece is found adjacent to the piece' do expect(pawn.en_passant?(3, 4)).to eq false end + + it 'should return true if opponent pawn did not move 2 space in last turn' do + white_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 6 + ) + + black_pawn = game.pieces.create( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 4 + ) + + white_pawn.move!(7,4) + binding.pry + expect(black_pawn.en_passant?(7,4)).to eq true + end end end From 2dab1d039c2231fc0b3515cbeedc0fb44382d9cd Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:11:45 +0000 Subject: [PATCH 09/32] refactor En Passant Logic & Working in console --- app/models/pawn.rb | 41 +++++++++++++--------------------------- spec/factories/games.rb | 34 ++++++++++++++++----------------- spec/models/pawn_spec.rb | 25 +++++++++++++----------- stoicchess-teamstoic | 1 + 4 files changed, 45 insertions(+), 56 deletions(-) create mode 160000 stoicchess-teamstoic diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 00f43b0..fd1bf8d 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -11,42 +11,27 @@ def valid_move?(x, y) !forward_capture?(x, y) end + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + def en_passant?(x, y) return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' - return false unless valid_en_passant_pawn?(x, y) - update(en_passant: true) - true + return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' + [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) end - def valid_en_passant_pawn?(x, y) - return false unless valid_passant_pawn_left?(x, y) - return false unless valid_passant_pawn_right?(x. y) + def valid_en_passant_pawn?(x, y, adjacent) + adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) + return false if adjacent_piece.nil? + return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color false end - def valid_passant_pawn_left?(x, y) - left_piece = find_piece(x - 1, y) - return false if left_piece.nil? - return true if left_piece.type == 'Pawn' && side_piece.color != color - false - end - - def valid_passant_pawn_right?(x, y) - right_piece = find_piece(x + 1, y) - return false if right_piece.nil? - return true if right_piece.type == 'Pawn' && side_piece.color != color - false - end - - # En Passant Logic: - # 1)target pawn just moved 2 space forward - # 2)only capture within the next turn - # 3)can only capture by opponent's pawn - # 4)opponent pawn must be on the left or right of target piece's y axis - def last_moved_piece - game.pieces.where(last_moved_piece: game.move_number - 1).take + game.pieces.find_by(last_moved_piece: game.move_number - 1) end # Updates the piece's type from Pawn to the new type diff --git a/spec/factories/games.rb b/spec/factories/games.rb index 59ca4f0..5993839 100644 --- a/spec/factories/games.rb +++ b/spec/factories/games.rb @@ -2,21 +2,21 @@ factory :game do end - # factory :empty_chess_board, class: Game do - # # after rails 5 you need to set up call_back first - # after(:build) do |game| - # game.class.set_callback(:create, :after, - # :populate_bishops!, :populate_rooks!, - # :populate_knights!, :populate_pawns!, - # :populate_queens_kings!) - # end - # - # # After game is created, skip populate game pieces - # after(:build) do |game| - # game.class.skip_callback(:create, :after, - # :populate_bishops!, :populate_rooks!, - # :populate_knights!, :populate_pawns!, - # :populate_queens_kings!) - # end - # end + factory :empty_chess_board, class: Game do + # after rails 5 you need to set up call_back first + after(:build) do |game| + game.class.set_callback(:create, :after, + :populate_bishops!, :populate_rooks!, + :populate_knights!, :populate_pawns!, + :populate_queens_kings!) + end + + # After game is created, skip populate game pieces + after(:build) do |game| + game.class.skip_callback(:create, :after, + :populate_bishops!, :populate_rooks!, + :populate_knights!, :populate_pawns!, + :populate_queens_kings!) + end + end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 0ded4fe..ba029da 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -123,23 +123,26 @@ expect(pawn.en_passant?(3, 4)).to eq false end - it 'should return true if opponent pawn did not move 2 space in last turn' do + it 'should return false if last moved piece is nil' do + expect(pawn.en_passant?(3, 4)).to eq false + end + + it 'should return true if opponent pawn move 2 space in last turn' do white_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 6 ) black_pawn = game.pieces.create( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 4 + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 4 ) - - white_pawn.move!(7,4) binding.pry + white_pawn.move!(7,4) expect(black_pawn.en_passant?(7,4)).to eq true end end diff --git a/stoicchess-teamstoic b/stoicchess-teamstoic new file mode 160000 index 0000000..53ab483 --- /dev/null +++ b/stoicchess-teamstoic @@ -0,0 +1 @@ +Subproject commit 53ab483e3abe7bed9fb4610f8becea886ea57cb0 From 728cb71ddc6a6be9757a168081f7605eb0394ae7 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:39:17 +0000 Subject: [PATCH 10/32] unit tests for En_Passant? logic --- app/models/pawn.rb | 35 +++++++++++++++---------- spec/models/pawn_spec.rb | 56 +++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index fd1bf8d..7a8644b 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -7,8 +7,8 @@ class Pawn < Piece # Check, and checkmate logic are not implemented yet # and thus ignored. Diagonal attack not implemented. def valid_move?(x, y) - (moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && - !forward_capture?(x, y) + ((moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && + !forward_capture?(x, y)) end # En Passant Logic: @@ -16,23 +16,17 @@ def valid_move?(x, y) # 2)only capture within the next turn # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis - + + # return false if last move piece is nil (Start of game) + # return false last moved piece is not pawn or its y axis difference is !2 + # check both both adjacent side of pawn + # if any have valid En Passant pawn piece, return true def en_passant?(x, y) return false if last_moved_piece.nil? return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) end - def valid_en_passant_pawn?(x, y, adjacent) - adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) - return false if adjacent_piece.nil? - return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color - false - end - - def last_moved_piece - game.pieces.find_by(last_moved_piece: game.move_number - 1) - end # Updates the piece's type from Pawn to the new type # provided. @@ -73,4 +67,19 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end + + # check for any adjacent piece + # return false if none if found + # return true if opponent's pawn is found + def valid_en_passant_pawn?(x, y, adjacent) + adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) + return false if adjacent_piece.nil? + return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color + false + end + + # find the last moved piece by subtracting current move number - 1 + def last_moved_piece + game.pieces.find_by(last_moved_piece: game.move_number - 1) + end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index ba029da..7098893 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -128,22 +128,66 @@ end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn = game.pieces.find_by( + white_pawn = game.pieces.create( type: 'Pawn', color: 'white', x_position: 7, - y_position: 6 + y_position: 4 + ) + + black_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + + white_pawn.move!(7,3) + black_pawn.move!(6,3) + + expect(black_pawn.en_passant?(6,3)).to eq true + end + + it 'should return false if opponent piece is not pawn' do + white_Rook = game.pieces.create( + type: 'Rook', + color: 'white', + x_position: 7, + y_position: 4 ) - black_pawn = game.pieces.create( + black_pawn = game.pieces.find_by( type: 'Pawn', color: 'black', x_position: 6, + y_position: 1 + ) + + white_Rook.move!(7,3) + black_pawn.move!(6,3) + + expect(black_pawn.en_passant?(6,3)).to eq false + end + + it 'should return false if opponent pawn only move 1 space in last turn' do + white_pawn = game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 7, y_position: 4 ) - binding.pry - white_pawn.move!(7,4) - expect(black_pawn.en_passant?(7,4)).to eq true + + black_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + + white_pawn.move!(7,3) + black_pawn.move!(6,2) + + expect(black_pawn.en_passant?(6,2)).to eq false end end end From 3d78eb0074391e751e30b81464806c9ddd10171e Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:47:00 +0000 Subject: [PATCH 11/32] refactor en passant RSpec tests --- spec/models/pawn_spec.rb | 55 +++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 7098893..88612d0 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -10,6 +10,7 @@ y_position: 6 ) end + let(:moved_pawn) do game.pieces.create( type: 'Pawn', @@ -20,6 +21,24 @@ ) end + let(:white_pawn) do + game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 4 + ) + end + + let(:black_pawn) do + game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + end + describe 'creation' do it 'should create a white pawn' do pawn = FactoryGirl.create(:pawn, color: 'white') @@ -123,25 +142,12 @@ expect(pawn.en_passant?(3, 4)).to eq false end + # Check edge case at the start of game it 'should return false if last moved piece is nil' do expect(pawn.en_passant?(3, 4)).to eq false end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn = game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 - ) - - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_pawn.move!(7,3) black_pawn.move!(6,3) @@ -156,13 +162,6 @@ y_position: 4 ) - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_Rook.move!(7,3) black_pawn.move!(6,3) @@ -170,20 +169,6 @@ end it 'should return false if opponent pawn only move 1 space in last turn' do - white_pawn = game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 - ) - - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_pawn.move!(7,3) black_pawn.move!(6,2) From 30efba2de56c6c5f6e76cc0835d4c5fe999322f2 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 21:08:52 +0000 Subject: [PATCH 12/32] remove duplicate files --- app/models/game.rb | 4 +- app/models/pawn.rb | 11 ++- app/models/piece.rb | 3 +- config/application.rb | 1 + config/environments/production.rb | 4 +- config/environments/test.rb | 4 +- config/initializers/backtrace_silencers.rb | 6 +- config/initializers/devise.rb | 4 +- config/initializers/secret_token.rb | 5 +- config/initializers/session_store.rb | 3 +- config/initializers/wrap_parameters.rb | 3 +- .../20160629091417_devise_create_users.rb | 1 + db/migrate/20160712160707_create_games.rb | 3 +- .../20160719140518_add_moved_to_pieces.rb | 1 + spec/factories/games.rb | 34 +++---- spec/models/game_spec.rb | 2 +- spec/models/pawn_spec.rb | 96 +++++++++++-------- stoicchess-teamstoic | 1 - 18 files changed, 108 insertions(+), 78 deletions(-) delete mode 160000 stoicchess-teamstoic diff --git a/app/models/game.rb b/app/models/game.rb index 788e832..0a5ce69 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -4,7 +4,7 @@ class Game < ActiveRecord::Base has_many :players after_create :populate_bishops!, :populate_rooks!, :populate_pawns!,\ - :populate_knights!, :populate_queens_kings!, :first_turn! + :populate_knights!, :populate_queens_kings!, :first_turn! def populate_bishops! pieces.create(type: 'Bishop', x_position: 2, y_position: 7, color: 'white') @@ -49,6 +49,6 @@ def first_turn! def end_turn! increment!(:move_number) - move_number % 2 == 0 ? update(turn: 'black') : update(turn: 'white') + move_number.even? ? update(turn: 'black') : update(turn: 'white') end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 7a8644b..5c0d46b 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,5 +1,4 @@ # Pawn behavior. -require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or else a regular forward move, @@ -23,11 +22,12 @@ def valid_move?(x, y) # if any have valid En Passant pawn piece, return true def en_passant?(x, y) return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' - [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) + return false unless last_moved_piece.y_distance(y - 2) == 2 && + type == 'Pawn' + [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)] + .include?(true) end - # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -74,7 +74,8 @@ def forward_capture?(x, y) def valid_en_passant_pawn?(x, y, adjacent) adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) return false if adjacent_piece.nil? - return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color + return true if adjacent_piece.type == + 'Pawn' && adjacent_piece.color != color false end diff --git a/app/models/piece.rb b/app/models/piece.rb index c1a5413..bcd2192 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -25,7 +25,8 @@ def move!(x, y) return false unless enemy?(victim) capture!(victim) end - update(x_position: x, y_position: y, moved: true, last_moved_piece: game.move_number) + update(x_position: x, y_position: y, moved: true, + last_moved_piece: game.move_number) game.end_turn! true end diff --git a/config/application.rb b/config/application.rb index e8d762f..dc992ee 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,4 @@ +#Application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' diff --git a/config/environments/production.rb b/config/environments/production.rb index 6297e09..04ee300 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,5 +1,7 @@ +# Production.rb StoicChess::Application.configure do - config.action_mailer.default_url_options = { host: 'stoicchess-teamstoic.herokuapp.com' } + config.action_mailer.default_url_options = + { host: 'stoicchess-teamstoic.herokuapp.com' } # Settings specified here will take precedence over those in # config/application.rb. diff --git a/config/environments/test.rb b/config/environments/test.rb index cc312e1..7fa3a2c 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,4 @@ +#test.rb StoicChess::Application.configure do # Settings specified here will take precedence over those in # config/application.rb. @@ -19,7 +20,8 @@ # Configure static asset server for tests with Cache-Control for performance. config.public_file_server.enabled = true - config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } + config.public_file_server.headers = + { 'Cache-Control' => 'public, max-age=3600' } # Show full error reports and disable caching. config.consider_all_requests_local = true diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cd..573be5b 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,7 +1,9 @@ # Be sure to restart your server when you modify this file. -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# You can add backtrace silencers for libraries that you're using +# but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# You can also remove all the silencers if you're trying to debug a problem +# that might stem from framework code. # Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index a10c673..5ac41f2 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -33,7 +33,9 @@ # :subdomain], so for authenticating a user, both parameters # are required. # - # Remember that those parameters are used only when authenticating and not when retrieving from session. If you need permissions, you should implement that in a before filter. + # Remember that those parameters are used only when authenticating + # and not when retrieving from session. If you need permissions, + # you should implement that in a before filter. # # You can also supply a hash where the value is a boolean # determining whether diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index f1d9d1c..4ec6070 100644 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -9,4 +9,7 @@ # Make sure your secret_key_base is kept private # if you're sharing your code publicly. -StoicChess::Application.config.secret_key_base = 'b02af4ed78836e0a007c890e7f38df540669ad77d076cffe3899647bfbfd000e5e5080fc5841fff22763a5ce871d3f4f077b4c2693f964cdd67c0da25d6fad29' +StoicChess::Application.config.secret_key_base = +'b02af4ed78836e0a007c890e7f38df540669ad77d076cff +e3899647bfbfd000e5e5080fc5841fff22763a5ce871d3f4 +f077b4c2693f964cdd67c0da25d6fad29' diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index e6bb783..f1bbec8 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,4 @@ # Be sure to restart your server when you modify this file. -StoicChess::Application.config.session_store :cookie_store, key: '_StoicChess_session' +StoicChess::Application.config.session_store :cookie_store, key: + '_StoicChess_session' diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 33725e9..8aa4151 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -3,7 +3,8 @@ # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +# Enable parameter wrapping for JSON. You can disable this by setting +# :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] if respond_to?(:wrap_parameters) end diff --git a/db/migrate/20160629091417_devise_create_users.rb b/db/migrate/20160629091417_devise_create_users.rb index 8873c8c..ff45f41 100644 --- a/db/migrate/20160629091417_devise_create_users.rb +++ b/db/migrate/20160629091417_devise_create_users.rb @@ -1,3 +1,4 @@ +#devise auto migration class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| diff --git a/db/migrate/20160712160707_create_games.rb b/db/migrate/20160712160707_create_games.rb index b83e64f..05860a3 100644 --- a/db/migrate/20160712160707_create_games.rb +++ b/db/migrate/20160712160707_create_games.rb @@ -1,9 +1,10 @@ +# game model class CreateGames < ActiveRecord::Migration def change create_table :games do |t| t.string :winning_player t.string :game_status - + t.integer :counter t.integer :turn t.integer :user_id diff --git a/db/migrate/20160719140518_add_moved_to_pieces.rb b/db/migrate/20160719140518_add_moved_to_pieces.rb index b9520ae..e9f1b07 100644 --- a/db/migrate/20160719140518_add_moved_to_pieces.rb +++ b/db/migrate/20160719140518_add_moved_to_pieces.rb @@ -1,3 +1,4 @@ +# add moved to pieces table class AddMovedToPieces < ActiveRecord::Migration[5.0] def change add_column :pieces, :moved, :boolean, default: false diff --git a/spec/factories/games.rb b/spec/factories/games.rb index 5993839..b047fcd 100644 --- a/spec/factories/games.rb +++ b/spec/factories/games.rb @@ -2,21 +2,21 @@ factory :game do end - factory :empty_chess_board, class: Game do - # after rails 5 you need to set up call_back first - after(:build) do |game| - game.class.set_callback(:create, :after, - :populate_bishops!, :populate_rooks!, - :populate_knights!, :populate_pawns!, - :populate_queens_kings!) - end - - # After game is created, skip populate game pieces - after(:build) do |game| - game.class.skip_callback(:create, :after, - :populate_bishops!, :populate_rooks!, - :populate_knights!, :populate_pawns!, - :populate_queens_kings!) - end - end + # factory :empty_chess_board, class: Game do + # # after rails 5 you need to set up call_back first + # after(:build) do |game| + # game.class.set_callback(:create, :after, + # :populate_bishops!, :populate_rooks!, + # :populate_knights!, :populate_pawns!, + # :populate_queens_kings!) + # end + # + # # After game is created, skip populate game pieces + # after(:build) do |game| + # game.class.skip_callback(:create, :after, + # :populate_bishops!, :populate_rooks!, + # :populate_knights!, :populate_pawns!, + # :populate_queens_kings!) + # end + # end end diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 37318fe..c6258c6 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -33,7 +33,7 @@ end end - describe "end_turn!" do + describe 'end_turn!' do game = FactoryGirl.create(:game) it 'should increment move_number by 1 once the turn ended' do diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 88612d0..e7c3a0b 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -1,41 +1,40 @@ require 'rails_helper' -require 'pry' RSpec.describe Pawn, type: :model do let(:game) { FactoryGirl.create(:game) } let(:pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 5, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 5, + y_position: 6 ) end let(:moved_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 3, - y_position: 4, - moved: true + type: 'Pawn', + color: 'white', + x_position: 3, + y_position: 4, + moved: true ) end let(:white_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 4 ) end let(:black_pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 ) end @@ -48,7 +47,7 @@ it 'should fail to create a red pawn' do expect { FactoryGirl.create(:pawn, color: 'red') }.to\ - raise_error(ActiveRecord::RecordInvalid) + raise_error(ActiveRecord::RecordInvalid) end end @@ -110,10 +109,10 @@ describe 'obstructed move' do it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 4)).to eq false @@ -124,10 +123,10 @@ it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 5)).to eq false @@ -137,7 +136,7 @@ end end - describe "en_passant?" do + describe 'en_passant?' do it 'should return false if no piece is found adjacent to the piece' do expect(pawn.en_passant?(3, 4)).to eq false end @@ -148,31 +147,44 @@ end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn.move!(7,3) - black_pawn.move!(6,3) + white_pawn.move!(7, 3) + black_pawn.move!(6, 3) - expect(black_pawn.en_passant?(6,3)).to eq true + expect(black_pawn.en_passant?(6, 3)).to eq true end it 'should return false if opponent piece is not pawn' do - white_Rook = game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 7, - y_position: 4 + white_rook = game.pieces.create( + type: 'Rook', + color: 'white', + x_position: 7, + y_position: 4 ) - white_Rook.move!(7,3) - black_pawn.move!(6,3) + white_rook.move!(7, 3) + black_pawn.move!(6, 3) - expect(black_pawn.en_passant?(6,3)).to eq false + expect(black_pawn.en_passant?(6, 3)).to eq false end it 'should return false if opponent pawn only move 1 space in last turn' do - white_pawn.move!(7,3) - black_pawn.move!(6,2) + white_pawn.move!(7, 3) + black_pawn.move!(6, 2) + + expect(black_pawn.en_passant?(6, 2)).to eq false + end + + it 'should return false if adjacent pawn is the same color' do + another_white_pawn = game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 6, + y_position: 3 + ) + + white_pawn.move!(7, 3) - expect(black_pawn.en_passant?(6,2)).to eq false + expect(another_white_pawn.en_passant?(6, 3)).to eq false end end end diff --git a/stoicchess-teamstoic b/stoicchess-teamstoic deleted file mode 160000 index 53ab483..0000000 --- a/stoicchess-teamstoic +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 53ab483e3abe7bed9fb4610f8becea886ea57cb0 From cbdc2e8166531352925c3125d6d6be32b2b24dff Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Fri, 29 Jul 2016 21:54:32 +0000 Subject: [PATCH 13/32] Add move_number to games table --- db/migrate/20160729214941_add_move_number_to_games.rb | 5 +++++ db/schema.rb | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20160729214941_add_move_number_to_games.rb diff --git a/db/migrate/20160729214941_add_move_number_to_games.rb b/db/migrate/20160729214941_add_move_number_to_games.rb new file mode 100644 index 0000000..8b0a63e --- /dev/null +++ b/db/migrate/20160729214941_add_move_number_to_games.rb @@ -0,0 +1,5 @@ +class AddMoveNumberToGames < ActiveRecord::Migration[5.0] + def change + add_column :games, :move_number, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 9294ad6..1866b9d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160726151316) do +ActiveRecord::Schema.define(version: 20160729214941) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -24,6 +24,7 @@ t.integer "player_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "move_number" end create_table "pieces", force: :cascade do |t| From 681a00f77d035f80b8b804599073a4b77fff1f53 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Fri, 29 Jul 2016 22:18:35 +0000 Subject: [PATCH 14/32] En Passant first attempt --- app/models/pawn.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 2a5bc46..400c5a8 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -49,4 +49,20 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end + + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + def en_passant?(x, y) + return false unless clear_two_forward_move(x, y) + end + + def en_passant_pawn?(x, y) + side_piece = find_piece(x, y) + return false if side_piece.nil? + return true if side_piece.type == 'Pawn' && side_piece.color != color + false + end end From 00ee14cebe2aa3b39a1dd72914c2d7cd1447738d Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:01:42 +0000 Subject: [PATCH 15/32] Add first_turn logic to game model --- app/models/game.rb | 6 +++++- app/models/pawn.rb | 8 ++++++-- db/migrate/20160730005057_add_en_passant_to_games.rb | 5 +++++ .../20160730144006_change_turn_type_to_string.rb | 5 +++++ db/schema.rb | 9 +++++---- spec/models/game_spec.rb | 12 ++++++++++++ 6 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20160730005057_add_en_passant_to_games.rb create mode 100644 db/migrate/20160730144006_change_turn_type_to_string.rb diff --git a/app/models/game.rb b/app/models/game.rb index 966195f..aa03406 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -4,7 +4,7 @@ class Game < ActiveRecord::Base has_many :players after_create :populate_bishops!, :populate_rooks!, :populate_pawns!,\ - :populate_knights!, :populate_queens_kings! + :populate_knights!, :populate_queens_kings!, :first_turn! def populate_bishops! pieces.create(type: 'Bishop', x_position: 2, y_position: 7, color: 'white') @@ -42,4 +42,8 @@ def populate_queens_kings! pieces.create(type: 'Queen', x_position: 3, y_position: 0, color: 'black') pieces.create(type: 'King', x_position: 4, y_position: 0, color: 'black') end + + def first_turn! + update(turn: 'white', move_number: 1) + end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 400c5a8..c70525c 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -56,13 +56,17 @@ def forward_capture?(x, y) # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis def en_passant?(x, y) - return false unless clear_two_forward_move(x, y) + return false unless en_passant_pawn?(x, y) end - def en_passant_pawn?(x, y) + def en_passant_pawn?(x, y, horizontal) side_piece = find_piece(x, y) return false if side_piece.nil? return true if side_piece.type == 'Pawn' && side_piece.color != color false end + + def last_moved_piece + game.pieces.find_by(game.move_number - 1) + end end diff --git a/db/migrate/20160730005057_add_en_passant_to_games.rb b/db/migrate/20160730005057_add_en_passant_to_games.rb new file mode 100644 index 0000000..2c712d5 --- /dev/null +++ b/db/migrate/20160730005057_add_en_passant_to_games.rb @@ -0,0 +1,5 @@ +class AddEnPassantToGames < ActiveRecord::Migration[5.0] + def change + add_column :games, :en_passant, :boolean, default: false + end +end diff --git a/db/migrate/20160730144006_change_turn_type_to_string.rb b/db/migrate/20160730144006_change_turn_type_to_string.rb new file mode 100644 index 0000000..5f1ed28 --- /dev/null +++ b/db/migrate/20160730144006_change_turn_type_to_string.rb @@ -0,0 +1,5 @@ +class ChangeTurnTypeToString < ActiveRecord::Migration[5.0] + def change + change_column :games, :turn, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 1866b9d..815b951 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160729214941) do +ActiveRecord::Schema.define(version: 20160730144006) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,12 +19,13 @@ t.string "winning_player" t.string "game_status" t.integer "counter" - t.integer "turn" + t.string "turn" t.integer "user_id" t.integer "player_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "move_number" + t.boolean "en_passant", default: false end create_table "pieces", force: :cascade do |t| diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 6f14e84..88b89a2 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -7,17 +7,29 @@ it 'should give us 32 pieces upon board population' do expect(game.pieces.count).to eq 32 end + it 'should give me the last x position of population' do expect(game.pieces.last.x_position).to eq 4 end + it 'should give me the last y position of population' do expect(game.pieces.last.y_position).to eq 0 end + it 'should give me the last piece of the population as the King' do expect(game.pieces.last.type).to eq 'King' end + it 'should give me the last pieces color' do expect(game.pieces.last.color).to eq 'black' end + + it 'should show first turn of game belong to white player' do + expect(game.turn).to eq 'white' + end + + it 'should show move number as 1' do + expect(game.move_number).to eq 1 + end end end From b7d4f74da38f3cee6023c6e00aa49c2b6632987a Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:41:00 +0000 Subject: [PATCH 16/32] integrate end_turn! into move! & pass all tests --- app/models/game.rb | 5 +++++ app/models/piece.rb | 1 + spec/models/piece_spec.rb | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/app/models/game.rb b/app/models/game.rb index aa03406..788e832 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -46,4 +46,9 @@ def populate_queens_kings! def first_turn! update(turn: 'white', move_number: 1) end + + def end_turn! + increment!(:move_number) + move_number % 2 == 0 ? update(turn: 'black') : update(turn: 'white') + end end diff --git a/app/models/piece.rb b/app/models/piece.rb index 6ad61cf..7d07106 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -26,6 +26,7 @@ def move!(x, y) capture!(victim) end update(x_position: x, y_position: y, moved: true) + game.end_turn! true end diff --git a/spec/models/piece_spec.rb b/spec/models/piece_spec.rb index ea5f728..781f50c 100644 --- a/spec/models/piece_spec.rb +++ b/spec/models/piece_spec.rb @@ -31,6 +31,8 @@ expect(victim.x_position).to eq nil expect(victim.y_position).to eq nil expect(victim.captured).to eq true + expect(game.move_number).to eq 2 + expect(game.turn).to eq 'black' end it 'should return false on a move against a friendly piece' do @@ -43,6 +45,8 @@ expect(victim.x_position).to eq 3 expect(victim.y_position).to eq 6 expect(victim.captured).to eq nil + expect(game.move_number).to eq 1 + expect(game.turn).to eq 'white' end end end From b9d81752689215cdaf8b39e08003b02194851e07 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 15:42:12 +0000 Subject: [PATCH 17/32] add end_turn! tests in game_spec.rb and pass all tests --- spec/models/game_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 88b89a2..37318fe 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -32,4 +32,21 @@ expect(game.move_number).to eq 1 end end + + describe "end_turn!" do + game = FactoryGirl.create(:game) + + it 'should increment move_number by 1 once the turn ended' do + game.end_turn! + + expect(game.move_number).to eq 2 + end + + it 'should switch turn between black and white player' do + game.reload + game.end_turn! + + expect(game.turn).to eq 'black' + end + end end From f64eeb4cb279110f82e99d88b5aba946434d08fa Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 17:21:36 +0000 Subject: [PATCH 18/32] En Passsant Logic 2nd attempt --- app/models/pawn.rb | 18 +++++++++------- spec/models/pawn_spec.rb | 45 ++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index c70525c..18663e7 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -7,7 +7,14 @@ class Pawn < Piece # and thus ignored. Diagonal attack not implemented. def valid_move?(x, y) (moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && - !forward_capture?(x, y) + !forward_capture?(x, y) + end + + def en_passant?(x, y) + return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' + return false unless valid_en_passant_pawn?(x, y, horizontal_difference) + update(en_passant: true) + true end # Updates the piece's type from Pawn to the new type @@ -55,18 +62,15 @@ def forward_capture?(x, y) # 2)only capture within the next turn # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis - def en_passant?(x, y) - return false unless en_passant_pawn?(x, y) - end - def en_passant_pawn?(x, y, horizontal) - side_piece = find_piece(x, y) + def valid_passant_pawn?(x, y, horizontal_difference) + side_piece = occupant_piece(x, y + (horizontal_difference ? -1 : 1)) return false if side_piece.nil? return true if side_piece.type == 'Pawn' && side_piece.color != color false end def last_moved_piece - game.pieces.find_by(game.move_number - 1) + game.pieces.find_by(game.move_number - 1 || game.move_number == 0) end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index ed2539a..b3281aa 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -4,31 +4,32 @@ let(:game) { FactoryGirl.create(:game) } let(:pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 5, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 5, + y_position: 6 ) end let(:moved_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 3, - y_position: 4, - moved: true + type: 'Pawn', + color: 'white', + x_position: 3, + y_position: 4, + moved: true ) end describe 'creation' do it 'should create a white pawn' do pawn = FactoryGirl.create(:pawn, color: 'white') + expect(pawn.type).to eq('Pawn') end it 'should fail to create a red pawn' do expect { FactoryGirl.create(:pawn, color: 'red') }.to\ - raise_error(ActiveRecord::RecordInvalid) + raise_error(ActiveRecord::RecordInvalid) end end @@ -90,11 +91,12 @@ describe 'obstructed move' do it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) + expect(pawn.move!(5, 4)).to eq false expect(pawn.x_position).to eq 5 expect(pawn.y_position).to eq 6 @@ -103,15 +105,22 @@ it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) + expect(pawn.move!(5, 5)).to eq false expect(pawn.x_position).to eq 5 expect(pawn.y_position).to eq 6 expect(pawn.moved).to eq false end end + + describe "en_passant?" do + it 'should return false if no piece is found adjacent to the piece' do + expect(pawn.en_passant?(3, 4)).to eq false + end + end end From 666acce36196556d2578b12bbca50a45311636d6 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 30 Jul 2016 19:48:34 +0000 Subject: [PATCH 19/32] refactor en passant logics --- app/models/pawn.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 18663e7..ad7155e 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,4 +1,5 @@ # Pawn behavior. +require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or else a regular forward move, @@ -71,6 +72,7 @@ def valid_passant_pawn?(x, y, horizontal_difference) end def last_moved_piece - game.pieces.find_by(game.move_number - 1 || game.move_number == 0) + binding.pry + game.pieces.find_by(game.move_number - 1) end end From 6b1ba61d497476aa777bf6415748544dce0672f1 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 02:36:37 +0000 Subject: [PATCH 20/32] add en_passant left and right pawn logic --- app/models/pawn.rb | 51 ++++++++++++------- app/models/piece.rb | 16 +++--- ...59_add_last_moved_piece_to_pieces_table.rb | 5 ++ db/schema.rb | 5 +- spec/models/pawn_spec.rb | 22 +++++++- 5 files changed, 69 insertions(+), 30 deletions(-) create mode 100644 db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb diff --git a/app/models/pawn.rb b/app/models/pawn.rb index ad7155e..00f43b0 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -12,12 +12,43 @@ def valid_move?(x, y) end def en_passant?(x, y) + return false if last_moved_piece.nil? return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' - return false unless valid_en_passant_pawn?(x, y, horizontal_difference) + return false unless valid_en_passant_pawn?(x, y) update(en_passant: true) true end + def valid_en_passant_pawn?(x, y) + return false unless valid_passant_pawn_left?(x, y) + return false unless valid_passant_pawn_right?(x. y) + false + end + + def valid_passant_pawn_left?(x, y) + left_piece = find_piece(x - 1, y) + return false if left_piece.nil? + return true if left_piece.type == 'Pawn' && side_piece.color != color + false + end + + def valid_passant_pawn_right?(x, y) + right_piece = find_piece(x + 1, y) + return false if right_piece.nil? + return true if right_piece.type == 'Pawn' && side_piece.color != color + false + end + + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + + def last_moved_piece + game.pieces.where(last_moved_piece: game.move_number - 1).take + end + # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -57,22 +88,4 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end - - # En Passant Logic: - # 1)target pawn just moved 2 space forward - # 2)only capture within the next turn - # 3)can only capture by opponent's pawn - # 4)opponent pawn must be on the left or right of target piece's y axis - - def valid_passant_pawn?(x, y, horizontal_difference) - side_piece = occupant_piece(x, y + (horizontal_difference ? -1 : 1)) - return false if side_piece.nil? - return true if side_piece.type == 'Pawn' && side_piece.color != color - false - end - - def last_moved_piece - binding.pry - game.pieces.find_by(game.move_number - 1) - end end diff --git a/app/models/piece.rb b/app/models/piece.rb index 7d07106..c1a5413 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -25,11 +25,18 @@ def move!(x, y) return false unless enemy?(victim) capture!(victim) end - update(x_position: x, y_position: y, moved: true) + update(x_position: x, y_position: y, moved: true, last_moved_piece: game.move_number) game.end_turn! true end + # Compares a piece's y_position with the + # coordinate provided and returns the + # distance between the two. + def y_distance(new_y_coordinate) + (y_position - new_y_coordinate).abs + end + # All validation assumes white player is on the # 6-7 rows of the array, and black player is on # 0-1 rows of the array. @@ -58,13 +65,6 @@ def x_distance(new_x_coordinate) (x_position - new_x_coordinate).abs end - # Compares a piece's y_position with the - # coordinate provided and returns the - # distance between the two. - def y_distance(new_y_coordinate) - (y_position - new_y_coordinate).abs - end - # Returns true if the coordinates provided # are different from the piece's starting # position. diff --git a/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb b/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb new file mode 100644 index 0000000..8d83960 --- /dev/null +++ b/db/migrate/20160730194959_add_last_moved_piece_to_pieces_table.rb @@ -0,0 +1,5 @@ +class AddLastMovedPieceToPiecesTable < ActiveRecord::Migration[5.0] + def change + add_column :pieces, :last_moved_piece, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 815b951..ec27757 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160730144006) do +ActiveRecord::Schema.define(version: 20160730194959) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -39,7 +39,8 @@ t.boolean "checkmate" t.datetime "created_at" t.datetime "updated_at" - t.boolean "moved", default: false + t.boolean "moved", default: false + t.integer "last_moved_piece" end create_table "players", force: :cascade do |t| diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index b3281aa..0ded4fe 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -1,5 +1,5 @@ require 'rails_helper' - +require 'pry' RSpec.describe Pawn, type: :model do let(:game) { FactoryGirl.create(:game) } let(:pawn) do @@ -122,5 +122,25 @@ it 'should return false if no piece is found adjacent to the piece' do expect(pawn.en_passant?(3, 4)).to eq false end + + it 'should return true if opponent pawn did not move 2 space in last turn' do + white_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 6 + ) + + black_pawn = game.pieces.create( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 4 + ) + + white_pawn.move!(7,4) + binding.pry + expect(black_pawn.en_passant?(7,4)).to eq true + end end end From 68ce4763e7a718e778cb3f05c661e106fddea2cb Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:11:45 +0000 Subject: [PATCH 21/32] refactor En Passant Logic & Working in console --- app/models/pawn.rb | 41 +++++++++++++--------------------------- spec/factories/games.rb | 34 ++++++++++++++++----------------- spec/models/pawn_spec.rb | 25 +++++++++++++----------- stoicchess-teamstoic | 1 + 4 files changed, 45 insertions(+), 56 deletions(-) create mode 160000 stoicchess-teamstoic diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 00f43b0..fd1bf8d 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -11,42 +11,27 @@ def valid_move?(x, y) !forward_capture?(x, y) end + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + def en_passant?(x, y) return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' - return false unless valid_en_passant_pawn?(x, y) - update(en_passant: true) - true + return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' + [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) end - def valid_en_passant_pawn?(x, y) - return false unless valid_passant_pawn_left?(x, y) - return false unless valid_passant_pawn_right?(x. y) + def valid_en_passant_pawn?(x, y, adjacent) + adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) + return false if adjacent_piece.nil? + return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color false end - def valid_passant_pawn_left?(x, y) - left_piece = find_piece(x - 1, y) - return false if left_piece.nil? - return true if left_piece.type == 'Pawn' && side_piece.color != color - false - end - - def valid_passant_pawn_right?(x, y) - right_piece = find_piece(x + 1, y) - return false if right_piece.nil? - return true if right_piece.type == 'Pawn' && side_piece.color != color - false - end - - # En Passant Logic: - # 1)target pawn just moved 2 space forward - # 2)only capture within the next turn - # 3)can only capture by opponent's pawn - # 4)opponent pawn must be on the left or right of target piece's y axis - def last_moved_piece - game.pieces.where(last_moved_piece: game.move_number - 1).take + game.pieces.find_by(last_moved_piece: game.move_number - 1) end # Updates the piece's type from Pawn to the new type diff --git a/spec/factories/games.rb b/spec/factories/games.rb index 59ca4f0..5993839 100644 --- a/spec/factories/games.rb +++ b/spec/factories/games.rb @@ -2,21 +2,21 @@ factory :game do end - # factory :empty_chess_board, class: Game do - # # after rails 5 you need to set up call_back first - # after(:build) do |game| - # game.class.set_callback(:create, :after, - # :populate_bishops!, :populate_rooks!, - # :populate_knights!, :populate_pawns!, - # :populate_queens_kings!) - # end - # - # # After game is created, skip populate game pieces - # after(:build) do |game| - # game.class.skip_callback(:create, :after, - # :populate_bishops!, :populate_rooks!, - # :populate_knights!, :populate_pawns!, - # :populate_queens_kings!) - # end - # end + factory :empty_chess_board, class: Game do + # after rails 5 you need to set up call_back first + after(:build) do |game| + game.class.set_callback(:create, :after, + :populate_bishops!, :populate_rooks!, + :populate_knights!, :populate_pawns!, + :populate_queens_kings!) + end + + # After game is created, skip populate game pieces + after(:build) do |game| + game.class.skip_callback(:create, :after, + :populate_bishops!, :populate_rooks!, + :populate_knights!, :populate_pawns!, + :populate_queens_kings!) + end + end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 0ded4fe..ba029da 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -123,23 +123,26 @@ expect(pawn.en_passant?(3, 4)).to eq false end - it 'should return true if opponent pawn did not move 2 space in last turn' do + it 'should return false if last moved piece is nil' do + expect(pawn.en_passant?(3, 4)).to eq false + end + + it 'should return true if opponent pawn move 2 space in last turn' do white_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 6 ) black_pawn = game.pieces.create( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 4 + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 4 ) - - white_pawn.move!(7,4) binding.pry + white_pawn.move!(7,4) expect(black_pawn.en_passant?(7,4)).to eq true end end diff --git a/stoicchess-teamstoic b/stoicchess-teamstoic new file mode 160000 index 0000000..53ab483 --- /dev/null +++ b/stoicchess-teamstoic @@ -0,0 +1 @@ +Subproject commit 53ab483e3abe7bed9fb4610f8becea886ea57cb0 From 08b4406d8549eea04b5d01ffaec54b6feb156e9d Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:39:17 +0000 Subject: [PATCH 22/32] unit tests for En_Passant? logic --- app/models/pawn.rb | 35 +++++++++++++++---------- spec/models/pawn_spec.rb | 56 +++++++++++++++++++++++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index fd1bf8d..7a8644b 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -7,8 +7,8 @@ class Pawn < Piece # Check, and checkmate logic are not implemented yet # and thus ignored. Diagonal attack not implemented. def valid_move?(x, y) - (moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && - !forward_capture?(x, y) + ((moved ? one_forward_move?(x, y) : first_forward_move?(x, y)) && + !forward_capture?(x, y)) end # En Passant Logic: @@ -16,23 +16,17 @@ def valid_move?(x, y) # 2)only capture within the next turn # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis - + + # return false if last move piece is nil (Start of game) + # return false last moved piece is not pawn or its y axis difference is !2 + # check both both adjacent side of pawn + # if any have valid En Passant pawn piece, return true def en_passant?(x, y) return false if last_moved_piece.nil? return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) end - def valid_en_passant_pawn?(x, y, adjacent) - adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) - return false if adjacent_piece.nil? - return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color - false - end - - def last_moved_piece - game.pieces.find_by(last_moved_piece: game.move_number - 1) - end # Updates the piece's type from Pawn to the new type # provided. @@ -73,4 +67,19 @@ def first_forward_move?(x, y) def forward_capture?(x, y) game.pieces.exists?(x_position: x, y_position: y) end + + # check for any adjacent piece + # return false if none if found + # return true if opponent's pawn is found + def valid_en_passant_pawn?(x, y, adjacent) + adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) + return false if adjacent_piece.nil? + return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color + false + end + + # find the last moved piece by subtracting current move number - 1 + def last_moved_piece + game.pieces.find_by(last_moved_piece: game.move_number - 1) + end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index ba029da..7098893 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -128,22 +128,66 @@ end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn = game.pieces.find_by( + white_pawn = game.pieces.create( type: 'Pawn', color: 'white', x_position: 7, - y_position: 6 + y_position: 4 + ) + + black_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + + white_pawn.move!(7,3) + black_pawn.move!(6,3) + + expect(black_pawn.en_passant?(6,3)).to eq true + end + + it 'should return false if opponent piece is not pawn' do + white_Rook = game.pieces.create( + type: 'Rook', + color: 'white', + x_position: 7, + y_position: 4 ) - black_pawn = game.pieces.create( + black_pawn = game.pieces.find_by( type: 'Pawn', color: 'black', x_position: 6, + y_position: 1 + ) + + white_Rook.move!(7,3) + black_pawn.move!(6,3) + + expect(black_pawn.en_passant?(6,3)).to eq false + end + + it 'should return false if opponent pawn only move 1 space in last turn' do + white_pawn = game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 7, y_position: 4 ) - binding.pry - white_pawn.move!(7,4) - expect(black_pawn.en_passant?(7,4)).to eq true + + black_pawn = game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + + white_pawn.move!(7,3) + black_pawn.move!(6,2) + + expect(black_pawn.en_passant?(6,2)).to eq false end end end From 2f3b1956db9e132ea2f7a6272557a233f75a84fa Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 17:47:00 +0000 Subject: [PATCH 23/32] refactor en passant RSpec tests --- spec/models/pawn_spec.rb | 55 +++++++++++++++------------------------- 1 file changed, 20 insertions(+), 35 deletions(-) diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 7098893..88612d0 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -10,6 +10,7 @@ y_position: 6 ) end + let(:moved_pawn) do game.pieces.create( type: 'Pawn', @@ -20,6 +21,24 @@ ) end + let(:white_pawn) do + game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 4 + ) + end + + let(:black_pawn) do + game.pieces.find_by( + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 + ) + end + describe 'creation' do it 'should create a white pawn' do pawn = FactoryGirl.create(:pawn, color: 'white') @@ -123,25 +142,12 @@ expect(pawn.en_passant?(3, 4)).to eq false end + # Check edge case at the start of game it 'should return false if last moved piece is nil' do expect(pawn.en_passant?(3, 4)).to eq false end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn = game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 - ) - - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_pawn.move!(7,3) black_pawn.move!(6,3) @@ -156,13 +162,6 @@ y_position: 4 ) - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_Rook.move!(7,3) black_pawn.move!(6,3) @@ -170,20 +169,6 @@ end it 'should return false if opponent pawn only move 1 space in last turn' do - white_pawn = game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 - ) - - black_pawn = game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 - ) - white_pawn.move!(7,3) black_pawn.move!(6,2) From a19fa0768a234b3b5415968fd67c0e5c13d66f28 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 31 Jul 2016 21:08:52 +0000 Subject: [PATCH 24/32] remove duplicate files --- app/models/game.rb | 4 +- app/models/pawn.rb | 11 ++- app/models/piece.rb | 3 +- config/application.rb | 1 + config/environments/production.rb | 4 +- config/environments/test.rb | 4 +- config/initializers/backtrace_silencers.rb | 6 +- config/initializers/devise.rb | 4 +- config/initializers/secret_token.rb | 5 +- config/initializers/session_store.rb | 3 +- config/initializers/wrap_parameters.rb | 3 +- .../20160629091417_devise_create_users.rb | 1 + db/migrate/20160712160707_create_games.rb | 3 +- .../20160719140518_add_moved_to_pieces.rb | 1 + spec/factories/games.rb | 34 +++---- spec/models/game_spec.rb | 2 +- spec/models/pawn_spec.rb | 96 +++++++++++-------- stoicchess-teamstoic | 1 - 18 files changed, 108 insertions(+), 78 deletions(-) delete mode 160000 stoicchess-teamstoic diff --git a/app/models/game.rb b/app/models/game.rb index 788e832..0a5ce69 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -4,7 +4,7 @@ class Game < ActiveRecord::Base has_many :players after_create :populate_bishops!, :populate_rooks!, :populate_pawns!,\ - :populate_knights!, :populate_queens_kings!, :first_turn! + :populate_knights!, :populate_queens_kings!, :first_turn! def populate_bishops! pieces.create(type: 'Bishop', x_position: 2, y_position: 7, color: 'white') @@ -49,6 +49,6 @@ def first_turn! def end_turn! increment!(:move_number) - move_number % 2 == 0 ? update(turn: 'black') : update(turn: 'white') + move_number.even? ? update(turn: 'black') : update(turn: 'white') end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 7a8644b..5c0d46b 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,5 +1,4 @@ # Pawn behavior. -require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or else a regular forward move, @@ -23,11 +22,12 @@ def valid_move?(x, y) # if any have valid En Passant pawn piece, return true def en_passant?(x, y) return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y-2) == 2 && type == 'Pawn' - [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)].include?(true) + return false unless last_moved_piece.y_distance(y - 2) == 2 && + type == 'Pawn' + [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)] + .include?(true) end - # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -74,7 +74,8 @@ def forward_capture?(x, y) def valid_en_passant_pawn?(x, y, adjacent) adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) return false if adjacent_piece.nil? - return true if adjacent_piece.type == 'Pawn' && adjacent_piece.color != color + return true if adjacent_piece.type == + 'Pawn' && adjacent_piece.color != color false end diff --git a/app/models/piece.rb b/app/models/piece.rb index c1a5413..bcd2192 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -25,7 +25,8 @@ def move!(x, y) return false unless enemy?(victim) capture!(victim) end - update(x_position: x, y_position: y, moved: true, last_moved_piece: game.move_number) + update(x_position: x, y_position: y, moved: true, + last_moved_piece: game.move_number) game.end_turn! true end diff --git a/config/application.rb b/config/application.rb index f7aa353..f549a2a 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,3 +1,4 @@ +#Application.rb require File.expand_path('../boot', __FILE__) require 'rails/all' diff --git a/config/environments/production.rb b/config/environments/production.rb index 6297e09..04ee300 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,5 +1,7 @@ +# Production.rb StoicChess::Application.configure do - config.action_mailer.default_url_options = { host: 'stoicchess-teamstoic.herokuapp.com' } + config.action_mailer.default_url_options = + { host: 'stoicchess-teamstoic.herokuapp.com' } # Settings specified here will take precedence over those in # config/application.rb. diff --git a/config/environments/test.rb b/config/environments/test.rb index cc312e1..7fa3a2c 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,4 @@ +#test.rb StoicChess::Application.configure do # Settings specified here will take precedence over those in # config/application.rb. @@ -19,7 +20,8 @@ # Configure static asset server for tests with Cache-Control for performance. config.public_file_server.enabled = true - config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } + config.public_file_server.headers = + { 'Cache-Control' => 'public, max-age=3600' } # Show full error reports and disable caching. config.consider_all_requests_local = true diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cd..573be5b 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,7 +1,9 @@ # Be sure to restart your server when you modify this file. -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# You can add backtrace silencers for libraries that you're using +# but don't wish to see in your backtraces. # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# You can also remove all the silencers if you're trying to debug a problem +# that might stem from framework code. # Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index a10c673..5ac41f2 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -33,7 +33,9 @@ # :subdomain], so for authenticating a user, both parameters # are required. # - # Remember that those parameters are used only when authenticating and not when retrieving from session. If you need permissions, you should implement that in a before filter. + # Remember that those parameters are used only when authenticating + # and not when retrieving from session. If you need permissions, + # you should implement that in a before filter. # # You can also supply a hash where the value is a boolean # determining whether diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index f1d9d1c..4ec6070 100644 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -9,4 +9,7 @@ # Make sure your secret_key_base is kept private # if you're sharing your code publicly. -StoicChess::Application.config.secret_key_base = 'b02af4ed78836e0a007c890e7f38df540669ad77d076cffe3899647bfbfd000e5e5080fc5841fff22763a5ce871d3f4f077b4c2693f964cdd67c0da25d6fad29' +StoicChess::Application.config.secret_key_base = +'b02af4ed78836e0a007c890e7f38df540669ad77d076cff +e3899647bfbfd000e5e5080fc5841fff22763a5ce871d3f4 +f077b4c2693f964cdd67c0da25d6fad29' diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index e6bb783..f1bbec8 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,4 @@ # Be sure to restart your server when you modify this file. -StoicChess::Application.config.session_store :cookie_store, key: '_StoicChess_session' +StoicChess::Application.config.session_store :cookie_store, key: + '_StoicChess_session' diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 33725e9..8aa4151 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -3,7 +3,8 @@ # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. -# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +# Enable parameter wrapping for JSON. You can disable this by setting +# :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] if respond_to?(:wrap_parameters) end diff --git a/db/migrate/20160629091417_devise_create_users.rb b/db/migrate/20160629091417_devise_create_users.rb index 8873c8c..ff45f41 100644 --- a/db/migrate/20160629091417_devise_create_users.rb +++ b/db/migrate/20160629091417_devise_create_users.rb @@ -1,3 +1,4 @@ +#devise auto migration class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t| diff --git a/db/migrate/20160712160707_create_games.rb b/db/migrate/20160712160707_create_games.rb index b83e64f..05860a3 100644 --- a/db/migrate/20160712160707_create_games.rb +++ b/db/migrate/20160712160707_create_games.rb @@ -1,9 +1,10 @@ +# game model class CreateGames < ActiveRecord::Migration def change create_table :games do |t| t.string :winning_player t.string :game_status - + t.integer :counter t.integer :turn t.integer :user_id diff --git a/db/migrate/20160719140518_add_moved_to_pieces.rb b/db/migrate/20160719140518_add_moved_to_pieces.rb index b9520ae..e9f1b07 100644 --- a/db/migrate/20160719140518_add_moved_to_pieces.rb +++ b/db/migrate/20160719140518_add_moved_to_pieces.rb @@ -1,3 +1,4 @@ +# add moved to pieces table class AddMovedToPieces < ActiveRecord::Migration[5.0] def change add_column :pieces, :moved, :boolean, default: false diff --git a/spec/factories/games.rb b/spec/factories/games.rb index 5993839..b047fcd 100644 --- a/spec/factories/games.rb +++ b/spec/factories/games.rb @@ -2,21 +2,21 @@ factory :game do end - factory :empty_chess_board, class: Game do - # after rails 5 you need to set up call_back first - after(:build) do |game| - game.class.set_callback(:create, :after, - :populate_bishops!, :populate_rooks!, - :populate_knights!, :populate_pawns!, - :populate_queens_kings!) - end - - # After game is created, skip populate game pieces - after(:build) do |game| - game.class.skip_callback(:create, :after, - :populate_bishops!, :populate_rooks!, - :populate_knights!, :populate_pawns!, - :populate_queens_kings!) - end - end + # factory :empty_chess_board, class: Game do + # # after rails 5 you need to set up call_back first + # after(:build) do |game| + # game.class.set_callback(:create, :after, + # :populate_bishops!, :populate_rooks!, + # :populate_knights!, :populate_pawns!, + # :populate_queens_kings!) + # end + # + # # After game is created, skip populate game pieces + # after(:build) do |game| + # game.class.skip_callback(:create, :after, + # :populate_bishops!, :populate_rooks!, + # :populate_knights!, :populate_pawns!, + # :populate_queens_kings!) + # end + # end end diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 37318fe..c6258c6 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -33,7 +33,7 @@ end end - describe "end_turn!" do + describe 'end_turn!' do game = FactoryGirl.create(:game) it 'should increment move_number by 1 once the turn ended' do diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 88612d0..e7c3a0b 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -1,41 +1,40 @@ require 'rails_helper' -require 'pry' RSpec.describe Pawn, type: :model do let(:game) { FactoryGirl.create(:game) } let(:pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 5, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 5, + y_position: 6 ) end let(:moved_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 3, - y_position: 4, - moved: true + type: 'Pawn', + color: 'white', + x_position: 3, + y_position: 4, + moved: true ) end let(:white_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 4 ) end let(:black_pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 ) end @@ -48,7 +47,7 @@ it 'should fail to create a red pawn' do expect { FactoryGirl.create(:pawn, color: 'red') }.to\ - raise_error(ActiveRecord::RecordInvalid) + raise_error(ActiveRecord::RecordInvalid) end end @@ -110,10 +109,10 @@ describe 'obstructed move' do it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 4)).to eq false @@ -124,10 +123,10 @@ it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 5)).to eq false @@ -137,7 +136,7 @@ end end - describe "en_passant?" do + describe 'en_passant?' do it 'should return false if no piece is found adjacent to the piece' do expect(pawn.en_passant?(3, 4)).to eq false end @@ -148,31 +147,44 @@ end it 'should return true if opponent pawn move 2 space in last turn' do - white_pawn.move!(7,3) - black_pawn.move!(6,3) + white_pawn.move!(7, 3) + black_pawn.move!(6, 3) - expect(black_pawn.en_passant?(6,3)).to eq true + expect(black_pawn.en_passant?(6, 3)).to eq true end it 'should return false if opponent piece is not pawn' do - white_Rook = game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 7, - y_position: 4 + white_rook = game.pieces.create( + type: 'Rook', + color: 'white', + x_position: 7, + y_position: 4 ) - white_Rook.move!(7,3) - black_pawn.move!(6,3) + white_rook.move!(7, 3) + black_pawn.move!(6, 3) - expect(black_pawn.en_passant?(6,3)).to eq false + expect(black_pawn.en_passant?(6, 3)).to eq false end it 'should return false if opponent pawn only move 1 space in last turn' do - white_pawn.move!(7,3) - black_pawn.move!(6,2) + white_pawn.move!(7, 3) + black_pawn.move!(6, 2) + + expect(black_pawn.en_passant?(6, 2)).to eq false + end + + it 'should return false if adjacent pawn is the same color' do + another_white_pawn = game.pieces.create( + type: 'Pawn', + color: 'white', + x_position: 6, + y_position: 3 + ) + + white_pawn.move!(7, 3) - expect(black_pawn.en_passant?(6,2)).to eq false + expect(another_white_pawn.en_passant?(6, 3)).to eq false end end end diff --git a/stoicchess-teamstoic b/stoicchess-teamstoic deleted file mode 160000 index 53ab483..0000000 --- a/stoicchess-teamstoic +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 53ab483e3abe7bed9fb4610f8becea886ea57cb0 From 1883571739422b334b398eac241fd03c7ec15187 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 6 Aug 2016 16:58:59 +0000 Subject: [PATCH 25/32] add Ethan's LinkedIn to README --- README.md | 3 ++- spec/models/game_spec.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ee6f48d..27de954 100644 --- a/README.md +++ b/README.md @@ -36,4 +36,5 @@ Contributors * [Aleks Gorbenko](mailto:aleksedgorbenko@gmail.com) | [GitHub](https://github.com/aleksgorbenko) | [LinkedIn](https://uk.linkedin.com/in/aleks-gorbenko-web-developer) | [Portfolio](https://aleksgorbenko.github.io/) | [Blog](https://aleksgorbenko.com) -* [Ethan He](mailto:ethanhe.dev@gmail.com) | [GitHub](https://github.com/Se7enB2st) +* [Ethan He](mailto:ethanhe.dev@gmail.com) | [GitHub](https://github.com/Se7enB2st) | +[LinkedIn](https://www.linkedin.com/in/ethan-he) diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index d6af0cf..ffe40fb 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -36,7 +36,7 @@ describe 'end_turn!' do it 'should increment move_number by 1 once the turn ended' do game.end_turn! - + expect(game.move_number).to eq 2 end From 63194d80a32a96b98d39c9cc9887589af909a0eb Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 6 Aug 2016 17:45:34 +0000 Subject: [PATCH 26/32] merge en_passant into capture --- app/models/pawn.rb | 1 + spec/models/pawn_spec.rb | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 083b0fc..0acf5cb 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -85,6 +85,7 @@ def fwd_attack?(x, y) # that is one space diagonally forward to the left or right # of the pawn's starting position. def fwd_diagonal_attack?(x, y) + return true if en_passant?(x, y) return false unless occupant_piece(x, y) return false unless x == x_position + 1 || x == x_position - 1 y == if color == 'black' diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 8c11f77..77a83cc 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -177,15 +177,14 @@ expect(moved_pawn.y_position).to eq 4 expect(moved_pawn.moved).to eq true end - end - describe 'en_passant?' do + it 'should return false if no piece is found adjacent to the piece' do - expect(pawn.en_passant?(3, 4)).to eq false + expect(pawn.move!(3, 4)).to eq false end # Check edge case at the start of game it 'should return false if last moved piece is nil' do - expect(pawn.en_passant?(3, 4)).to eq false + expect(pawn.move!(3, 4)).to eq false end it 'should return true if opponent pawn move 2 space in last turn' do From 2c09cd3670d91b039c86935534a94b5355945eeb Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 6 Aug 2016 23:15:46 +0000 Subject: [PATCH 27/32] add en passant capture logic --- app/models/pawn.rb | 18 +++++++++++++----- spec/models/pawn_spec.rb | 31 ++++++------------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 0acf5cb..09f694c 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,4 +1,5 @@ # Pawn behavior. +require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or a regular forward move, or @@ -7,7 +8,6 @@ class Pawn < Piece # are not implemented yet and thus ignored. def valid_move?(x, y) return true if fwd_diagonal_attack?(x, y) - return true if en_passant?(x, y) moved ? one_fwd_move?(x, y) : first_fwd_move?(x, y) && !fwd_attack?(x, y) end @@ -29,6 +29,17 @@ def en_passant?(x, y) .include?(true) end + def en_passant_capture?(x, y) + victim = last_moved_piece + return true if en_passant?(x, y) + return false if victim.color == color + return true if x == victim.x_position && (y == victim.y_position - 1 || y == victim.y_position + 1) + end + + def last_moved_piece + game.pieces.find_by(last_moved_piece: game.move_number - 1) + end + # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -85,7 +96,6 @@ def fwd_attack?(x, y) # that is one space diagonally forward to the left or right # of the pawn's starting position. def fwd_diagonal_attack?(x, y) - return true if en_passant?(x, y) return false unless occupant_piece(x, y) return false unless x == x_position + 1 || x == x_position - 1 y == if color == 'black' @@ -96,7 +106,5 @@ def fwd_diagonal_attack?(x, y) end # find the last moved piece by subtracting current move number - 1 - def last_moved_piece - game.pieces.find_by(last_moved_piece: game.move_number - 1) - end + end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 77a83cc..a782cc8 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -1,4 +1,5 @@ require 'rails_helper' +require 'pry' RSpec.describe Pawn, type: :model do let(:game) { FactoryGirl.create(:game, :populated) } let(:pawn) do @@ -191,28 +192,7 @@ white_pawn.move!(7, 3) black_pawn.move!(6, 3) - expect(black_pawn.en_passant?(6, 3)).to eq true - end - - it 'should return false if opponent piece is not pawn' do - white_rook = game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 7, - y_position: 4 - ) - - white_rook.move!(7, 3) - black_pawn.move!(6, 3) - - expect(black_pawn.en_passant?(6, 3)).to eq false - end - - it 'should return false if opponent pawn only move 1 space in last turn' do - white_pawn.move!(7, 3) - black_pawn.move!(6, 2) - - expect(black_pawn.en_passant?(6, 2)).to eq false + expect(white_pawn.en_passant_capture?(6, 2)).to eq true end it 'should return false if adjacent pawn is the same color' do @@ -220,12 +200,13 @@ type: 'Pawn', color: 'white', x_position: 6, - y_position: 3 + y_position: 5 ) white_pawn.move!(7, 3) - - expect(another_white_pawn.en_passant?(6, 3)).to eq false + another_white_pawn.move!(6, 3) + + expect(white_pawn.en_passant_capture?(6, 2)).to eq false end end end From 4a2b24ac924d48d5943f92c92f361634664b20e6 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sat, 6 Aug 2016 23:20:23 +0000 Subject: [PATCH 28/32] fix Rubocop errors --- app/models/pawn.rb | 58 +++++++++++++++--------------- spec/models/pawn_spec.rb | 78 ++++++++++++++++++++-------------------- 2 files changed, 67 insertions(+), 69 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 09f694c..fee287e 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,5 +1,4 @@ # Pawn behavior. -require 'pry' class Pawn < Piece # Returns true if the pawn made a valid upgraded forward # move on its first move, or a regular forward move, or @@ -11,33 +10,12 @@ def valid_move?(x, y) moved ? one_fwd_move?(x, y) : first_fwd_move?(x, y) && !fwd_attack?(x, y) end - # En Passant Logic: - # 1)target pawn just moved 2 space forward - # 2)only capture within the next turn - # 3)can only capture by opponent's pawn - # 4)opponent pawn must be on the left or right of target piece's y axis - - # return false if last move piece is nil (Start of game) - # return false last moved piece is not pawn or its y axis difference is !2 - # check both both adjacent side of pawn - # if any have valid En Passant pawn piece, return true - def en_passant?(x, y) - return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y - 2) == 2 && - type == 'Pawn' - [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)] - .include?(true) - end - def en_passant_capture?(x, y) victim = last_moved_piece return true if en_passant?(x, y) return false if victim.color == color - return true if x == victim.x_position && (y == victim.y_position - 1 || y == victim.y_position + 1) - end - - def last_moved_piece - game.pieces.find_by(last_moved_piece: game.move_number - 1) + return true if x == victim.x_position && + (y == victim.y_position - 1 || y == victim.y_position + 1) end # Updates the piece's type from Pawn to the new type @@ -50,6 +28,24 @@ def promote!(new_type) private + # En Passant Logic: + # 1)target pawn just moved 2 space forward + # 2)only capture within the next turn + # 3)can only capture by opponent's pawn + # 4)opponent pawn must be on the left or right of target piece's y axis + + # return false if last move piece is nil (Start of game) + # return false last moved piece is not pawn or its y axis difference is !2 + # check both both adjacent side of pawn + # if any have valid En Passant pawn piece, return true + def en_passant?(x, y) + return false if last_moved_piece.nil? + return false unless last_moved_piece.y_distance(y - 2) == 2 && + type == 'Pawn' + [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)] + .include?(true) + end + # check for any adjacent piece # return false if none if found # return true if opponent's pawn is found @@ -57,7 +53,7 @@ def valid_en_passant_pawn?(x, y, adjacent) adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) return false if adjacent_piece.nil? return true if adjacent_piece.type == - 'Pawn' && adjacent_piece.color != color + 'Pawn' && adjacent_piece.color != color false end @@ -99,12 +95,14 @@ def fwd_diagonal_attack?(x, y) return false unless occupant_piece(x, y) return false unless x == x_position + 1 || x == x_position - 1 y == if color == 'black' - y_position + 1 - else - y_position - 1 - end + y_position + 1 + else + y_position - 1 + end end # find the last moved piece by subtracting current move number - 1 - + def last_moved_piece + game.pieces.find_by(last_moved_piece: game.move_number - 1) + end end diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index a782cc8..710430b 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -4,38 +4,38 @@ let(:game) { FactoryGirl.create(:game, :populated) } let(:pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'white', - x_position: 5, - y_position: 6 + type: 'Pawn', + color: 'white', + x_position: 5, + y_position: 6 ) end let(:moved_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 3, - y_position: 4, - moved: true + type: 'Pawn', + color: 'white', + x_position: 3, + y_position: 4, + moved: true ) end let(:white_pawn) do game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 7, - y_position: 4 + type: 'Pawn', + color: 'white', + x_position: 7, + y_position: 4 ) end let(:black_pawn) do game.pieces.find_by( - type: 'Pawn', - color: 'black', - x_position: 6, - y_position: 1 + type: 'Pawn', + color: 'black', + x_position: 6, + y_position: 1 ) end @@ -48,7 +48,7 @@ it 'should fail to create a red pawn' do expect { FactoryGirl.create(:pawn, color: 'red') }.to\ - raise_error(ActiveRecord::RecordInvalid) + raise_error(ActiveRecord::RecordInvalid) end end @@ -110,10 +110,10 @@ describe 'obstructed move' do it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 4)).to eq false @@ -124,10 +124,10 @@ it 'should return false and not update position on obstructed move' do game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 5, - y_position: 5 + type: 'Rook', + color: 'white', + x_position: 5, + y_position: 5 ) expect(pawn.move!(5, 5)).to eq false @@ -140,10 +140,10 @@ describe 'diagonal capture' do it 'should return false and not update position on capturing friendly' do victim = game.pieces.create( - type: 'Rook', - color: 'white', - x_position: 2, - y_position: 3 + type: 'Rook', + color: 'white', + x_position: 2, + y_position: 3 ) expect(moved_pawn.move!(2, 3)).to eq false expect(moved_pawn.x_position).to eq 3 @@ -157,10 +157,10 @@ it 'should return true and update position on capturing enemy' do victim = game.pieces.create( - type: 'Rook', - color: 'black', - x_position: 2, - y_position: 3 + type: 'Rook', + color: 'black', + x_position: 2, + y_position: 3 ) expect(moved_pawn.move!(2, 3)).to eq true expect(moved_pawn.x_position).to eq 2 @@ -197,15 +197,15 @@ it 'should return false if adjacent pawn is the same color' do another_white_pawn = game.pieces.create( - type: 'Pawn', - color: 'white', - x_position: 6, - y_position: 5 + type: 'Pawn', + color: 'white', + x_position: 6, + y_position: 5 ) white_pawn.move!(7, 3) another_white_pawn.move!(6, 3) - + expect(white_pawn.en_passant_capture?(6, 2)).to eq false end end From db950b6ddffc03489a1b40f1c290d8474fc30210 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 7 Aug 2016 16:12:54 +0000 Subject: [PATCH 29/32] En Passant Capture logic now working with move! logic --- app/models/pawn.rb | 21 ++++++++++++--------- spec/models/pawn_spec.rb | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index fee287e..a5fbaad 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -10,14 +10,6 @@ def valid_move?(x, y) moved ? one_fwd_move?(x, y) : first_fwd_move?(x, y) && !fwd_attack?(x, y) end - def en_passant_capture?(x, y) - victim = last_moved_piece - return true if en_passant?(x, y) - return false if victim.color == color - return true if x == victim.x_position && - (y == victim.y_position - 1 || y == victim.y_position + 1) - end - # Updates the piece's type from Pawn to the new type # provided. def promote!(new_type) @@ -34,6 +26,17 @@ def promote!(new_type) # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis + # Find the last moved piece + # check if en passant is possible + # return true if victim piece y coordinates is +1 or -1 from target spot + def en_passant_capture?(x, y) + victim = last_moved_piece + return true if en_passant?(x, y) + return false if victim.nil? || victim.color == color + return true if x == victim.x_position && + (y == victim.y_position - 1 || y == victim.y_position + 1) + end + # return false if last move piece is nil (Start of game) # return false last moved piece is not pawn or its y axis difference is !2 # check both both adjacent side of pawn @@ -92,7 +95,7 @@ def fwd_attack?(x, y) # that is one space diagonally forward to the left or right # of the pawn's starting position. def fwd_diagonal_attack?(x, y) - return false unless occupant_piece(x, y) + return false unless occupant_piece(x, y) || en_passant_capture?(x, y) return false unless x == x_position + 1 || x == x_position - 1 y == if color == 'black' y_position + 1 diff --git a/spec/models/pawn_spec.rb b/spec/models/pawn_spec.rb index 710430b..017f558 100644 --- a/spec/models/pawn_spec.rb +++ b/spec/models/pawn_spec.rb @@ -192,7 +192,7 @@ white_pawn.move!(7, 3) black_pawn.move!(6, 3) - expect(white_pawn.en_passant_capture?(6, 2)).to eq true + expect(white_pawn.move!(6, 2)).to eq true end it 'should return false if adjacent pawn is the same color' do @@ -206,7 +206,7 @@ white_pawn.move!(7, 3) another_white_pawn.move!(6, 3) - expect(white_pawn.en_passant_capture?(6, 2)).to eq false + expect(white_pawn.move!(6, 2)).to eq false end end end From 775dd87a6254a08b8c51f6cdd1d9b8f2d35bfe09 Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Sun, 7 Aug 2016 17:32:10 +0000 Subject: [PATCH 30/32] Fix Rubocop errors --- app/models/pawn.rb | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index c5bf19b..a6a2cfc 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -26,22 +26,25 @@ def promote!(new_type) # 3)can only capture by opponent's pawn # 4)opponent pawn must be on the left or right of target piece's y axis - # Find the last moved piece - # check if en passant is possible - # return true if victim piece y coordinates is +1 or -1 from target spot + # En Passant Capture logic def en_passant_capture?(x, y) + return true if en_passant_possible?(x, y) || en_passant_y_diff?(x, y) + end + + # Return false if victim piece is nil or same color + # Return true if victim piece's y axis difference is equal to 1 + def en_passant_y_diff?(x, y) victim = last_moved_piece return false if victim.nil? || victim.color == color - return true if en_passant?(x, y) return true if x == victim.x_position && (y == victim.y_position - 1 || y == victim.y_position + 1) end - # return false if last move piece is nil (Start of game) - # return false last moved piece is not pawn or its y axis difference is !2 - # check both both adjacent side of pawn - # if any have valid En Passant pawn piece, return true - def en_passant?(x, y) + # Return false if last move piece is nil (Start of game) + # Return false last moved piece is not pawn or its y axis difference is !2 + # Check both both adjacent side of pawn + # If any have valid En Passant pawn piece, return true + def en_passant_possible?(x, y) return false if last_moved_piece.nil? return false unless last_moved_piece.y_distance(y - 2) == 2 && type == 'Pawn' @@ -49,9 +52,9 @@ def en_passant?(x, y) .include?(true) end - # check for any adjacent piece - # return false if none if found - # return true if opponent's pawn is found + # Check for any adjacent piece + # Return false if none if found + # Return true if opponent's pawn is found def valid_en_passant_pawn?(x, y, adjacent) adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) return false if adjacent_piece.nil? @@ -104,7 +107,7 @@ def fwd_diagonal_attack?(x, y) end end - # find the last moved piece by subtracting current move number - 1 + # Find the last moved piece by subtracting current move number - 1 def last_moved_piece game.pieces.find_by(last_moved_piece: game.move_number - 1) end From 8adf4ee3158c7629d06e0385362439752294608e Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Tue, 9 Aug 2016 15:21:25 +0000 Subject: [PATCH 31/32] clean up database --- app/models/game.rb | 5 ++-- app/models/pawn.rb | 2 +- app/models/piece.rb | 2 +- ...60809143920_remove_en_passant_from_game.rb | 5 ++++ .../20160809145214_change_turn_from_games.rb | 6 ++++ .../20160809150350_add_turn_to_games.rb | 5 ++++ ...435_change_last_moved_piece_from_pieces.rb | 5 ++++ db/schema.rb | 18 ++++++------ spec/models/game_spec.rb | 28 ++++++------------- spec/models/piece_spec.rb | 6 ++-- 10 files changed, 43 insertions(+), 39 deletions(-) create mode 100644 db/migrate/20160809143920_remove_en_passant_from_game.rb create mode 100644 db/migrate/20160809145214_change_turn_from_games.rb create mode 100644 db/migrate/20160809150350_add_turn_to_games.rb create mode 100644 db/migrate/20160809151435_change_last_moved_piece_from_pieces.rb diff --git a/app/models/game.rb b/app/models/game.rb index d71fe80..0645dc9 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -18,8 +18,7 @@ def populate! end def end_turn! - increment!(:move_number) - move_number.even? ? update(turn: 'black') : update(turn: 'white') + increment!(:turn) end def check?(color) @@ -104,6 +103,6 @@ def create_piece(type, color, x_pos, y_pos) end def first_turn! - update(turn: 'white', move_number: 1) + update(turn: 1) end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index a6a2cfc..12f1715 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -109,6 +109,6 @@ def fwd_diagonal_attack?(x, y) # Find the last moved piece by subtracting current move number - 1 def last_moved_piece - game.pieces.find_by(last_moved_piece: game.move_number - 1) + game.pieces.find_by(turn_last_moved: game.turn - 1) end end diff --git a/app/models/piece.rb b/app/models/piece.rb index e63f590..1de86f3 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -25,7 +25,7 @@ def move!(x, y) capture!(victim) end update(x_position: x, y_position: y, moved: true, - last_moved_piece: game.move_number) + turn_last_moved: game.turn) game.end_turn! # if checked_king(white_king) # elsif checked_king(black_king) diff --git a/db/migrate/20160809143920_remove_en_passant_from_game.rb b/db/migrate/20160809143920_remove_en_passant_from_game.rb new file mode 100644 index 0000000..6641e88 --- /dev/null +++ b/db/migrate/20160809143920_remove_en_passant_from_game.rb @@ -0,0 +1,5 @@ +class RemoveEnPassantFromGame < ActiveRecord::Migration[5.0] + def change + remove_column :games, :en_passant, :boolean + end +end diff --git a/db/migrate/20160809145214_change_turn_from_games.rb b/db/migrate/20160809145214_change_turn_from_games.rb new file mode 100644 index 0000000..3b2ae0b --- /dev/null +++ b/db/migrate/20160809145214_change_turn_from_games.rb @@ -0,0 +1,6 @@ +class ChangeTurnFromGames < ActiveRecord::Migration[5.0] + def change + remove_column :games, :turn, :integer + remove_column :games, :move_number, :integer + end +end diff --git a/db/migrate/20160809150350_add_turn_to_games.rb b/db/migrate/20160809150350_add_turn_to_games.rb new file mode 100644 index 0000000..e8e3f9d --- /dev/null +++ b/db/migrate/20160809150350_add_turn_to_games.rb @@ -0,0 +1,5 @@ +class AddTurnToGames < ActiveRecord::Migration[5.0] + def change + add_column :games, :turn, :integer + end +end diff --git a/db/migrate/20160809151435_change_last_moved_piece_from_pieces.rb b/db/migrate/20160809151435_change_last_moved_piece_from_pieces.rb new file mode 100644 index 0000000..2823704 --- /dev/null +++ b/db/migrate/20160809151435_change_last_moved_piece_from_pieces.rb @@ -0,0 +1,5 @@ +class ChangeLastMovedPieceFromPieces < ActiveRecord::Migration[5.0] + def change + rename_column :pieces, :last_moved_piece, :turn_last_moved + end +end diff --git a/db/schema.rb b/db/schema.rb index 7b4c8c0..d01aa5c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160806192848) do +ActiveRecord::Schema.define(version: 20160809151435) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -19,11 +19,9 @@ t.string "winning_player" t.string "game_status" t.integer "counter" - t.string "turn" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "move_number" - t.boolean "en_passant", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "turn" end create_table "pieces", force: :cascade do |t| @@ -33,12 +31,12 @@ t.integer "y_position" t.integer "game_id" t.integer "player_id" - t.boolean "captured", default: false - t.boolean "checkmate", default: false + t.boolean "captured", default: false + t.boolean "checkmate", default: false t.datetime "created_at" t.datetime "updated_at" - t.boolean "moved", default: false - t.integer "last_moved_piece" + t.boolean "moved", default: false + t.integer "turn_last_moved" end create_table "players", force: :cascade do |t| diff --git a/spec/models/game_spec.rb b/spec/models/game_spec.rb index 7eb55f4..6af6cf3 100644 --- a/spec/models/game_spec.rb +++ b/spec/models/game_spec.rb @@ -24,34 +24,22 @@ expect(game.pieces.last.color).to eq 'white' end - it 'should show first turn of game belong to white player' do - expect(game.turn).to eq 'white' - end - - it 'should show move number as 1' do - expect(game.move_number).to eq 1 + it 'should show turn as 1' do + expect(game.turn).to eq 1 end describe 'end_turn!' do - it 'should increment move_number by 1 once the turn ended' do + it 'should increment turn by 1 once the turn ended' do game.end_turn! - expect(game.move_number).to eq 2 + expect(game.turn).to eq 2 end - - it 'should switch turn between black and white player' do - game.end_turn! - - expect(game.turn).to eq 'black' - end - end - - it 'should show first turn of game belong to white player' do - expect(game.turn).to eq 'white' end - it 'should show move number as 1' do - expect(game.move_number).to eq 1 + describe 'first_turn' do + it 'should show turn as 1' do + expect(game.turn).to eq 1 + end end end diff --git a/spec/models/piece_spec.rb b/spec/models/piece_spec.rb index 41275df..7f5a615 100644 --- a/spec/models/piece_spec.rb +++ b/spec/models/piece_spec.rb @@ -31,8 +31,7 @@ expect(victim.x_position).to eq nil expect(victim.y_position).to eq nil expect(victim.captured).to eq true - expect(game.move_number).to eq 2 - expect(game.turn).to eq 'black' + expect(game.turn).to eq 2 end it 'should return false on a move against a friendly piece' do @@ -44,8 +43,7 @@ victim.reload expect(victim.x_position).to eq 3 expect(victim.y_position).to eq 6 - expect(game.move_number).to eq 1 - expect(game.turn).to eq 'white' + expect(game.turn).to eq 1 expect(victim.captured).to eq false end end From 463a9eeed009dbf9aa5b9a3d5847d20d64b6868b Mon Sep 17 00:00:00 2001 From: Se7enB2st Date: Tue, 9 Aug 2016 16:17:49 +0000 Subject: [PATCH 32/32] refactor En Passant logic --- app/models/pawn.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/pawn.rb b/app/models/pawn.rb index 12f1715..068586d 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -46,7 +46,7 @@ def en_passant_y_diff?(x, y) # If any have valid En Passant pawn piece, return true def en_passant_possible?(x, y) return false if last_moved_piece.nil? - return false unless last_moved_piece.y_distance(y - 2) == 2 && + return false unless last_moved_piece.y_distance(y) == 2 && type == 'Pawn' [valid_en_passant_pawn?(x, y, true), valid_en_passant_pawn?(x, y, false)] .include?(true) @@ -58,8 +58,8 @@ def en_passant_possible?(x, y) def valid_en_passant_pawn?(x, y, adjacent) adjacent_piece = occupant_piece(x + (adjacent ? 1 : -1), y) return false if adjacent_piece.nil? - return true if adjacent_piece.type == - 'Pawn' && adjacent_piece.color != color + return true if adjacent_piece.type == 'Pawn' && + adjacent_piece.color != color false end