diff --git a/app/controllers/pieces_controller.rb b/app/controllers/pieces_controller.rb index efb328e..c2b061a 100644 --- a/app/controllers/pieces_controller.rb +++ b/app/controllers/pieces_controller.rb @@ -1,29 +1,46 @@ +require 'pry' class PiecesController < ApplicationController - before_action :select_pc, :only => [:show, :update] - before_action :only => :update do - validate_move(:x_position, :y_position) - end + before_action :select_pc, :only => [:show, :update] + before_action :only => :update do + validate_move(:x_position, :y_position) + end - def show - @pieces = select_pc.game.pieces - end + def show + @pieces = select_pc.game.pieces + end - def update - row = params[:y_position].to_i - col = params[:x_position].to_i - @select_pc.move_to!(col, row) - redirect_to game_path(select_pc.game.id) + def update + row = params[:y_position].to_i + col = params[:x_position].to_i + select_pc.move_to!(col, row) + redirect_to game_path(select_pc.game.id) end private - def validate_move(x_position, y_position) - row = params[:y_position].to_i - col = params[:x_position].to_i - if !select_pc.valid_move?(col, row) + + def validate_move(x_position, y_position) + row = params[:y_position].to_i + col = params[:x_position].to_i + #binding.pry + color = select_pc.color + if invalid_move?(col, row) flash[:alert] = "That move is not allowed! Please choose your piece and try again." - redirect_to game_path(select_pc.game.id) + elsif put_self_in_check?(color, col, row) + flash[:alert] = "You cannot put yourself in check" + else + return true end + redirect_to game_path(select_pc.game.id) + return false + end + + def invalid_move?(col, row) + !select_pc.valid_move?(col, row) || select_pc.nil_move?(col, row) + end + + def put_self_in_check?(color, col, row) + select_pc.game.checking_piece?(color, select_pc.id, col, row) end def select_pc diff --git a/app/helpers/games_helper.rb b/app/helpers/games_helper.rb index 5e0fc4d..2ee2146 100644 --- a/app/helpers/games_helper.rb +++ b/app/helpers/games_helper.rb @@ -1,8 +1,8 @@ module GamesHelper def piece_color(piece) case - when piece.color == 0 && piece.active == 1 then "Black\n" + piece.type - when piece.color == 1 && piece.active == 1 then "White\n" + piece.type + when piece.color == 0 then "Black\n" + piece.type + when piece.color == 1 then "White\n" + piece.type end end diff --git a/app/models/game.rb b/app/models/game.rb index 78bf279..df2f3f9 100644 --- a/app/models/game.rb +++ b/app/models/game.rb @@ -1,9 +1,14 @@ +require 'pry' class Game < ActiveRecord::Base belongs_to :user has_many :pieces + #before_action only: :show do + # :in_check(:color) + #end after_create :populate_board! + def populate_board! # These are initialized to the white pieces' y coordinates. y2 is for the # pawns' y coordinate. @@ -69,5 +74,25 @@ def populate_board! y2 = 7 color = 0 end + + end + + def in_check?(color) + checking_piece?(color) + end + + def checking_piece?(color, piece_id, col, row) + opponents_pieces = pieces.where.not(color: color, active: 0) + check_king(color, piece_id, col, row) + opponents_pieces.each do |piece| + piece.valid_move?(*@king_position) ? (return true) : false + end + return false + end + + def check_king(color, piece_id, col, row) + @king = pieces.find_by(type: 'King', color: color) + piece_moving = pieces.find_by(id: piece_id) + piece_moving == @king ? (@king_position = col, row) : (@king_position = @king.x_position, @king.y_position) end end diff --git a/app/models/pawn.rb b/app/models/pawn.rb index c528478..3396836 100644 --- a/app/models/pawn.rb +++ b/app/models/pawn.rb @@ -1,9 +1,10 @@ +require 'pry' class Pawn < Piece def valid_move?(new_x, new_y) - [move_number_allowed?(new_y), - no_vertical_obstacle?(new_x, new_y), - not_a_backwards_move?(new_y), + [move_number_allowed?(new_y), + no_vertical_obstacle?(new_x, new_y), + not_a_backwards_move?(new_y), diagonal_move_allowed?(new_x, new_y)].all? end @@ -16,13 +17,13 @@ def move_number(new_y) end def first_move?(new_y) - (color == 1 && y_position == 2) || (color == 0 && y_position == 7) + (color == 1 && y_position == 2) || (color == 0 && y_position == 7) end def no_vertical_obstacle?(new_x, new_y) return true if x_position != new_x - if move_number(new_y) == 2 - !is_obstructed?(x_position, new_y) && no_vertical_adjacent_obstacle?(x_position, new_y) + if move_number(new_y) == 2 + !is_obstructed?(x_position, new_y) && no_vertical_adjacent_obstacle?(x_position, new_y) else (no_vertical_adjacent_obstacle?(x_position, new_y)) end @@ -33,13 +34,13 @@ def no_vertical_adjacent_obstacle?(x_position, new_y) end def not_a_backwards_move?(new_y) - color == 1 ? (new_y - y_position) > 0 : (new_y - y_position) < 0 + color == 1 ? (new_y - y_position) > 0 : (new_y - y_position) < 0 end def diagonal_move_allowed?(new_x, new_y) return true if new_x == x_position - if (new_x - x_position).abs == 1 && (new_y - y_position).abs == 1 - capture_diagonally?(new_x, new_y) + if (new_x - x_position).abs == 1 && (new_y - y_position).abs == 1 + capture_diagonally?(new_x, new_y) else false end @@ -52,5 +53,5 @@ def capture_diagonally?(new_x, new_y) def enemy_piece?(new_x, new_y) obstacle_piece = Piece.find_by(:x_position => new_x, :y_position => new_y) obstacle_piece.color != color - end -end \ No newline at end of file + end +end diff --git a/app/models/piece.rb b/app/models/piece.rb index 2091224..a5c7c1e 100644 --- a/app/models/piece.rb +++ b/app/models/piece.rb @@ -1,7 +1,7 @@ -require 'pry' class Piece < ActiveRecord::Base belongs_to :user belongs_to :game + has_many :types def self.types %w(Pawn Rook Knight Bishop Queen King) @@ -95,8 +95,8 @@ def move_to!(new_x, new_y) self.update(:x_position => new_x, :y_position => new_y) # Else if a friendly piece exists there, do nothing - elsif friend_or_foe.color == friendly_color - return + #elsif friend_or_foe.color == friendly_color + #return else # It's an enemy. Capture it friend_or_foe.update(:active => 0) @@ -105,4 +105,26 @@ def move_to!(new_x, new_y) self.update(:x_position => new_x, :y_position => new_y) end end + + def friendly_piece?(new_x, new_y) + obstacle_piece = game.pieces.find_by( + :x_position => new_x, :y_position => new_y, :active => 1) + if obstacle_piece.nil? + return false + else + obstacle_piece.color == color + end + end + + def off_the_board?(new_x, new_y) + [new_x > 8, new_x < 1, new_y > 8, new_y < 1].any? + end + + def going_nowhere?(new_x, new_y) + new_x == x_position && new_y == y_position + end + + def nil_move?(new_x, new_y) + [off_the_board?(new_x, new_y), friendly_piece?(new_x, new_y), going_nowhere?(new_x, new_y)].any? + end end # end class diff --git a/test/controllers/pieces_controller_test.rb b/test/controllers/pieces_controller_test.rb index c30f646..e10099b 100644 --- a/test/controllers/pieces_controller_test.rb +++ b/test/controllers/pieces_controller_test.rb @@ -1,5 +1,4 @@ require 'test_helper' -require 'pry' class PiecesControllerTest < ActionController::TestCase def setup diff --git a/test/models/in_check_test.rb b/test/models/in_check_test.rb new file mode 100644 index 0000000..5e97c55 --- /dev/null +++ b/test/models/in_check_test.rb @@ -0,0 +1,20 @@ +require 'test_helper' + +class GameInCheckTest < ActiveSupport::TestCase + test "game in check state" do + g = Game.create + expected = true + + black_p = g.pieces.find_by(:x_position => 4, :y_position => 7, :type => 'Pawn', color: 0) + deactivate_white_pawn = g.pieces.find_by(:x_position => 4, :y_position => 2).update_attributes(:active => 0) + black_p.update_attributes(:y_position => 2) + + white_k = g.pieces.find_by(:x_position => 5, :y_position => 1, :color => 1, :type => 'King') + check_color = white_k.color + position_in_check = black_p.x_position, black_p.y_position + actual = g.checking_piece?(black_p.id, check_color, *position_in_check) + + assert_equal expected, actual + end + +end diff --git a/test/models/pawn_test.rb b/test/models/pawn_test.rb index 2a0889e..ef81268 100644 --- a/test/models/pawn_test.rb +++ b/test/models/pawn_test.rb @@ -1,5 +1,4 @@ require 'test_helper' -require 'pry' class PawnTest < ActiveSupport::TestCase diff --git a/test/models/piece_test.rb b/test/models/piece_test.rb index bdc8ed6..4c9096f 100644 --- a/test/models/piece_test.rb +++ b/test/models/piece_test.rb @@ -299,24 +299,6 @@ class PieceTest < ActiveSupport::TestCase assert_equal expected, actual end - test "move to a new destination that's occupied by a friendly" do - # Assume that is_obstructed? and is_valid? give the green light - - game = Game.create - - # Find the white king - white_king = game.pieces.find_by(:color => 1, :type => 'King') - - # Test when a new destination is occupied by a friendly - white_king.move_to!(5, 2) - - expected = [5, 1] - - actual = [white_king.x_position, white_king.y_position] - - assert_equal expected, actual - end - test "move to a new destination that's occupied by an enemy" do game = Game.create @@ -347,6 +329,64 @@ class PieceTest < ActiveSupport::TestCase actual = black_king.active # Assert the black piece's new :active status as captured (or 0) + assert_equal expected, actual + end +#--------------------Test nil_move? logic----------------------------------- + test "invalid move to a new destination that's occupied by a friendly" do + # Corrected this test so that this move cannot take place + game = Game.create + + # Find the white king + white_king = game.pieces.find_by(:color => 1, :type => 'King', :x_position => 5, :y_position => 1) + obstacle = game.pieces.find_by(:color => 1, :type => "Pawn") + obstacle.update_attributes(:x_position => 5, :y_position => 2) + + # Test a destination that is occupied by a friendly + actual = white_king.nil_move?(5, 2) + + expected = true + + assert_equal expected, actual + end + + test "invalid move off of the board" do + game = Game.create + + # Remove all pieces except Queen + pieces_to_deactivate = game.pieces.where.not(:type => "Queen") + pieces_to_deactivate.update_all(:active => 0) + + white_queen = game.pieces.find_by(:color => 1, :type => 'Queen') + + expected = true + # Test position far north + actual = white_queen.nil_move?(4, 9) + + assert_equal expected, actual + + # Test position far east + actual = white_queen.nil_move?(9, 1) + + assert_equal expected, actual + + # Test position far west + actual = white_queen.nil_move?(0, 1) + + assert_equal expected, actual + + # Test position south + actual = white_queen.nil_move?(4, 0) + assert_equal expected, actual + end + + test "invalid attempt - choosing current location" do + game = Game.create + white_pawn = game.pieces.find_by( + :type => "Pawn", :color => 1, :x_position => 1, :y_position => 2) + + actual = white_pawn.nil_move?(1,2) + expected = true + assert_equal expected, actual end end