Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

attempted to write capture logic #13

Merged
merged 13 commits into from
Aug 5, 2017
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion app/controllers/games_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
class GamesController < ApplicationController
before_action :authenticate_user!, only: %i[new create show]
before_action :authenticate_user!, only: %i[new create show update]

def index
@available_games = Game.available
Expand All @@ -17,6 +17,16 @@ def show
@game = Game.find(params[:id])
end

def update
@game = Game.find(params[:id])
if @game.user_black.nil?
@game.update(user_black_id: current_user.id)
else
@game.update(user_white_id: current_user.id)
end
redirect_to root_path
end

def game_params
params.require(:game).permit(:user_white_id, :user_black_id)
end
Expand Down
2 changes: 0 additions & 2 deletions app/models/game.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ class Game < ApplicationRecord
has_many :pieces
scope :available, -> { where('user_white_id IS NULL OR user_black_id IS NULL') }

scope :available, -> { where('user_white_id IS NULL OR user_black_id IS NULL') }

def populate_board!
# this should create all 32 Pieces with their initial X/Y coordinates.

Expand Down
3 changes: 2 additions & 1 deletion app/models/knight.rb
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
class Knight < Piece; end
class Knight < Piece
end
32 changes: 32 additions & 0 deletions app/models/piece.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,38 @@
class Piece < ApplicationRecord
belongs_to :game

def move_to!(new_x, new_y)
unless square_occupied?(new_x, new_y)
update_attributes(x_position: new_x, y_position: new_y)
return
end
occupying_piece = get_piece_at_coor(new_x, new_y)
unless (occupying_piece.is_white && is_white?) || (!occupying_piece.is_white && !is_white?)
capture_piece(occupying_piece)
update_attributes(x_position: new_x, y_position: new_y)
return
end
raise ArgumentError, 'That is an invalid move. Cannot capture your own piece.'
end

def square_occupied?(new_x, new_y)
piece = game.pieces.find_by(x_position: new_x, y_position: new_y)
return false if piece.nil?
true
end

def get_piece_at_coor(x, y)
Piece.all.find_each do |piece|
return piece if piece.x_position == x && piece.y_position == y
end
nil
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clever! 😄

This code is iterating through every piece and checking the coordinates. Totally works.

To make this more efficient, can use ActiveRecord/SQL:

game.pieces.find_by(x_position: x, y_position: y)

Notice game.pieces. This ensures we pull pieces from the current game (it knows the current game because game is an association on Piece and we are currently inside of a Piece).

find_by will find the record or return nil.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you update this to use find_by (see previous note)


def capture_piece(piece_captured)
piece_captured.update(x_position: nil, y_position: nil)
end
end

PAWN = 'Pawn'.freeze
ROOK = 'Rook'.freeze
KNIGHT = 'Knight'.freeze
Expand Down
4 changes: 3 additions & 1 deletion app/views/games/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<div class="col-12">
<% if game.user_white == nil %>
No one is playing White.
<%= link_to "Join game as white", game_path(game.id), method: :put, class: "btn btn-success"%>
<% else %>
<%= game.user_white.name %> is playing white.
<% end %>
Expand All @@ -18,8 +19,9 @@
<div class="col-12">
<% if game.user_black == nil %>
No one is playing Black.
<%= link_to "Join game as black", game_path(game.id), method: :put, class: "btn btn-success"%>
<% else %>
<%= game.user_black.name %> is playing white.
<%= game.user_black.name %> is playing black.
<% end %>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
devise_for :users
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'games#index'
resources :games, only: %i[new create show]
resources :games, only: %i[new create show update]
end
2 changes: 1 addition & 1 deletion spec/controllers/pieces_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe PiecesController, type: :controller do
describe 'Test action' do
it 'should successfully return true' do
expect(true).to eq true
expect(true).to eq(true)
end
end
end
71 changes: 71 additions & 0 deletions spec/models/piece_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,75 @@
require 'rails_helper'

RSpec.describe Piece, type: :model do
describe 'square_occupied? method' do
it 'returns true if the square your piece is moving to is occupied by another piece' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: PAWN, x_position: 1, y_position: 2)
occupied = piece1.square_occupied?(piece1.x_position, piece1.y_position)
expect(occupied).to eq(true)
end
it 'returns false if the square your piece is moving to is not occupied' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: QUEEN, x_position: 1, y_position: 2)
occupied = piece1.square_occupied?(2, piece1.y_position)
expect(occupied).to eq(false)
end
end

describe 'get_piece_at_coor method' do
it 'returns the piece object at given square' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: PAWN, x_position: 1, y_position: 2)
piece_found = piece1.get_piece_at_coor(1, 2)
expect(piece_found).to eq(piece1)
end
it 'returns nil if there is no piece at specified square' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: KNIGHT, x_position: 7, y_position: 1)
piece_found = piece1.get_piece_at_coor(1, 1)
expect(piece_found).to eq(nil)
end
end

describe 'capture_piece method' do
it 'sets piece x and y coor to nil if piece can be captured' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: KNIGHT, x_position: 7, y_position: 1)
piece1.capture_piece(piece1)
expect(piece1.x_position).to eq(nil)
expect(piece1.y_position).to eq(nil)
end
end

describe 'move_to! method' do
it 'Changes x and y coor of moving piece to x and y of destination square if that square is empty' do
game1 = FactoryGirl.create(:game)
piece1 = Piece.create(game_id: game1.id, is_white: false, type: KING, x_position: 2, y_position: 4)
piece1.move_to!(3, 4)
expect(piece1.x_position).to eq(3)
expect(piece1.y_position).to eq(4)
end
it 'updates x and y of moving piece to new square and captures enemy piece at that square' do
game1 = FactoryGirl.create(:game)
black_king = Piece.create(game_id: game1.id, is_white: false, type: KING, x_position: 2, y_position: 4)
white_queen = Piece.create(game_id: game1.id, is_white: true, type: QUEEN, x_position: 1, y_position: 4)
black_king.move_to!(1, 4)
expect(black_king.x_position).to eq(1)
expect(black_king.y_position).to eq(4)
white_queen.reload
expect(white_queen.x_position).to eq(nil)
expect(white_queen.y_position).to eq(nil)
end
it 'raises argument error if player tries to capture or move into a friendly piece' do
game1 = FactoryGirl.create(:game)
black_pawn = game1.pieces.create(game_id: game1.id, is_white: false, type: PAWN, x_position: 2, y_position: 5)
black_knight = game1.pieces.create(game_id: game1.id, is_white: false, type: KNIGHT, x_position: 3, y_position: 6)
expect { black_pawn.move_to!(3, 6) }.to raise_error(ArgumentError)
black_knight.reload
expect(black_pawn.x_position).to eq(2)
expect(black_pawn.y_position).to eq(5)
expect(black_knight.x_position).to eq(3)
expect(black_knight.y_position).to eq(6)
end
end
end