Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

core_ext removed. Introduce Stone and GameGUI. Board specs. Reorganiz…

…e specs
  • Loading branch information...
commit 3fd332ce9bae72f1f1eb96141db30450c537b17d 1 parent e8afd8a
@jcangas authored
View
3  .autotest
@@ -1,2 +1,3 @@
-require "test_notifier/autotest"
+require "test_notifier/runner/autotest"
+TestNotifier.default_notifier = :notify_send #:growl
View
2  .rspec
@@ -1,3 +1,3 @@
---format p
+--format doc
--color
View
15 bin/pressman
@@ -3,16 +3,7 @@
$LOAD_PATH.unshift File.expand_path('../lib', File.dirname(__FILE__))
require 'pressman'
-module Display
- def say(*args)
- puts(*args)
- end
-end
-
-STDOUT.extend(Display)
-game = Pressman::Game.new(STDOUT)
-game.start
-while input = gets.chomp
- break if game.input(input)
-end
+game = Pressman::Game.new
+gui = Pressman::GameUI.new(game)
+gui.run
View
4 lib/pressman.rb
@@ -1,4 +1,6 @@
-require 'pressman/core_ext'
+require 'pressman/vector'
+require 'pressman/stone'
require 'pressman/board'
require 'pressman/game'
+require 'pressman/game_gui'
View
187 lib/pressman/board.rb
@@ -1,163 +1,130 @@
-module Pressman
- module Color
- Empty = 0
- White = 2
- Black = 4
-
- def self.to_ord(value)
- value / 2
- end
+ # Board captures the state of the game play and know some basics facts in order to help
+ # the Game class. Note this a Pressman:: Board not a "generic"" Board, so it knows some basics
+ # facts about a Pressman's board ...
+ # It's all about 'static' facts of the game: Board don't know game's dynamics nor game rules
+
+ # We use 2 ways for denote a board square:
+ # 1) As an array of board indexes in range 0..7, like [2,5].
+ # We say this is "a square"
+ #
+ # 2) As a algebraic coordinate analog to chess, like "c5".
+ # Rows are a..h and columns are 1..8. We say this is "a coordinate"
- def self.to_s(value)
- ['', 'White', 'Black'][to_ord(value)]
- end
- end
+module Pressman
class Board
- HomeColors = [ Color::White, Color::White, Color::Empty, Color::Empty,
- Color::Empty, Color::Empty, Color::Black, Color::Black]
- attr :player, true
- attr :stone_count
- attr :flash, true
- def initialize(display)
- @display = display
- @board = Array.new(8){ [Color::Empty]*8 }
- @stone_count = [64, 0, 0]
- end
+ attr_accessor :player # current player
+ attr_reader :stones # stone count for each player
+ attr_reader :max_row
+ attr_reader :max_column
- def [](square)
- sqr = square.to_square
- @board[sqr[0]][sqr[1]]
+ def initialize(rows, columns)
+ @max_row = rows - 1
+ @max_column = columns - 1
+ @board = Array.new(rows){ [nil]*columns }
+ @stones = {:black => 0, :white => 0}
end
- def []=(square, value)
- sqr = square.to_square
- stone_count[Color.to_ord(stone(sqr))] -= 1
- @board[sqr[0]][sqr[1]] = value
- stone_count[Color.to_ord(stone(sqr))] += 1
+ # Square <-> Coordinate conversions
+
+ def to_square(coord)
+ return coord if coord.is_a? Array
+ [coord[0].ord - "a".ord, coord[1].ord - '1'.ord]
end
- def home_color(square)
- HomeColors[square[0]]
+ def to_coord(square)
+ return square if square.is_a? String
+ [ square[0] + "a".ord, square[1] + '1'.ord ].map {|c| c.chr}.join
end
+ # current oponent
def oponent
- player == Color::White ? Color::Black : Color::White
+ player == :white ? :black : :white
end
- def top(color)
- (color == Color::Black) ? 0 : 7
- end
+ # Some facts about the board
- def bottom(color)
- (color == Color::Black) ? 7 : 0
+ # Board has 2 zones of equal size. The top side is assigned to White
+ def zone(square)
+ (0 .. (@max_row / 2)).include?(square[0]) ? :white : :black
end
- def clear!(square)
- self[square] = Color::Empty
- end
+ # Each player has top & bottom rows.
- # Board has 2 sides of equal size. The top side is assigned to White
- def side(square)
- (0..3).include?(square[0]) ? Color::White : Color::Black
+ # Bottom is the first row in player's initial game setup.
+ def bottom(player)
+ (player == :black) ? @max_row : 0
end
- # color of the stone at square.
- def stone(square)
- (self[square] / 2 ) * 2 # to ignore stone deactivation
+ # Top is the oponent's bottom
+ def top(player)
+ (player == :black) ? 0 : @max_row
end
- def occupied_by?(square, color)
- stone(square) == color
- end
+ # Helper methods to query board about some basics facts
def is_empty?(square)
- occupied_by?(square, Color::Empty)
+ self[square].nil?
end
def is_occupied?(square)
- !is_empty?(square)
- end
-
- # Stone behaivior. This methods operates "onthe stone" at square
-
- def stone_top(square)
- top(stone(square))
+ self[square]
end
- def stone_bottom(square)
- bottom(stone(square))
+ def occupied_by?(square, player)
+ is_occupied?(square) && self[square].color == player
end
- def put_stone(square)
- self[square] = player
+ # check if square contains a stone of current player
+ def friend?(square)
+ occupied_by?(square, player)
end
- def kill_stone(square)
- clear!(square)
+ # check if the stone in square is in their home zone
+ def at_home?(square)
+ zone(square) == self[square].color
end
- def deactivate_stone(square)
- return if is_empty?(square) || !stone_activated?(square)
- self[square] += 1
+ # check square is in player "Top" row
+ def at_top?(square, player)
+ square[0] == top(player)
end
- def activate_stone(square)
- return if is_empty?(square) || stone_activated?(square)
- self[square] -= 1
+ # Positon of the stones
+ def [](square)
+ sqr = to_square(square)
+ @board[sqr[0]][sqr[1]]
end
- def stone_activated?(square)
- is_occupied?(square) && (self[square] % 2 == 0)
- end
+ # Board state change
- # check if stone is smae color as current player
- def friend_stone?(square)
- occupied_by?(square, player)
+ def []=(square, player)
+ sqr = to_square(square)
+ adjust_stones(self[sqr], -1)
+ @board[sqr[0]][sqr[1]] = player
+ adjust_stones(self[sqr], +1)
end
- def stone_at_side?(square)
- side(square) == stone(square)
+ # Put a new stone. Clear it if player == nil
+ def put_stone(square, player)
+ self[square] = player ? Stone.new(player) : nil
end
- def stone_at_top?(square)
- square[0] == stone_top(square)
+ def clear!(square)
+ put_stone(square, nil)
end
- def draw
- @display.say ' 1 2 3 4 5 6 7 8'
- row_labels = "abcdefgh"
- row_sep = ' ' + "-"*(4*8)
- @board.each_index do |idx|
- @display.say row_sep
- row = @board[idx].map {|square| [' ', ' ', 'o', 'O', 'x', 'X'][square]}.join(' | ')
- @display.say "#{row_labels[idx]}| #{row} |"
- end
- @display.say row_sep
- stones_txt = [Color::Black, Color::White].map{ |c| Color.to_s(c) + " = #{stone_count[Color.to_ord(c)]}"}.join(' ')
- @display.say "Stones: #{stones_txt}"
- @display.say "#{flash}" if flash
- flash = nil
- @display.say "#{Color::to_s(player)} move?"
+ # Raw move
+ def move!(origin, destination)
+ self[destination] = self[origin]
+ clear!(origin)
end
private
- def empty_setup
- (0..7).each do |row|
- (0..7).each do |col|
- clear!([row, col])
- end
- end
- end
-
- def game_setup
- for row in 0..7 do
- for col in 0..7 do
- self[[row, col]] = home_color([row, col])
- end
- end
+ def adjust_stones(stone, delta)
+ @stones[stone.color] += delta if stone
end
end
end
View
34 lib/pressman/core_ext.rb
@@ -1,34 +0,0 @@
-class Array
- def to_coord
- sum(["a".ord, '1'.ord ]).map {|c| c.chr}.join
- end
-
- def to_square
- self
- end
-
- # operate squares like vectors
- def sum(other)
- self.zip(other).map do |pair|
- pair[0].to_i + pair[1].to_i
- end
- end
-
- def subs(other)
- self.zip(other).map do |pair|
- pair[0].to_i - pair[1].to_i
- end
- end
-
-end
-
-class String
- def to_square
- [self[0].ord, self[1].ord].subs ["a".ord, '1'.ord ]
- end
-
- def to_coord
- self
- end
-end
-
View
223 lib/pressman/game.rb
@@ -1,32 +1,30 @@
-# We use 2 ways for denote a board square:
-# As an array of board indexes, like [2,5]. Indexes are in range 0..7.
-# We say this is "a square"
-# As a algebraic coordinate, like "c5", analog to chess. Rows are a..h and columns are 1..8.
-# We say this is "a coordinate"
module Pressman
class Error < RuntimeError
end
+ # Game act as controller, it query and change board's state enforicing game rules.
+
class Game
+ include Pressman::Vector
+
+ attr_accessor :gui
attr :board
+ attr :winner
- def initialize(display)
- @display = display
- @board = Board.new(display)
- @display.say 'Welcome to Pressman Game!'
+ def initialize
+ @board = Board.new(8,8)
end
def error(msg)
Pressman::Error.new(msg)
end
- def start(board_setup = :game)
- board.send("#{board_setup}_setup")
- board.player = Color::Black
+ def start(template = :game)
+ board_setup(template)
+ board.player = :black
@winner = nil
- board.draw
end
def player
@@ -37,126 +35,157 @@ def oponent
@board.oponent
end
- def stone_count
- @board.stone_count
- end
-
- def input(command)
- begin
- case command
- when /[a-h]\d\s*=\s*(e|b|w)/
- user_setup command unless @winner
- when /[a-h]\d-[a-h]\d/
- move command unless @winner
- when 'r'
- resing unless @winner
- when 'e'
- start(:empty)
- when 'g'
- start(:game)
- when 'q'
- @display.say "Goodbye ..."
- return true
- end
- rescue Pressman::Error => e
- board.flash = command + " error!: #{e.message}"
- rescue Exception => e
- board.flash = command + " error!: #{e.message}" + "\n" + e.backtrace.join("\n")
- end
- board.draw
+ def stones
+ @board.stones
end
- def user_setup(command)
- coord, stone = command.split('=')
- coord = coord.strip
- stone = stone.strip
- board.clear!(coord) if stone == 'e'
- board[coord] = Color::White if stone == 'w'
- board[coord] = Color::Black if stone == 'b'
+ def resing
+ @winner = oponent
end
- def resing
- @winner = opponent
- @display.say("You resigns")
- @display.say("#{Color.to_s(@winner)} player wins!!")
+ def next_player
+ board.player = board.oponent
end
+ def put_stone(square, player)
+ board.put_stone(square, player)
+ end
+
+
+ # Here we can apply Observer Pattern to extract the logic for the rule games
+ # class GameRules
+ # def before_move
+ # validate_move!
+ # ...
+ # end
+ #
+ # def after_move
+ # if can_regenerate?(squares[1])
+ # ...
+ # end
+ #
+ # end
+ #
+ # So, at game creation: board.add_observer(GameRules.new)
+ #
+ # But not sure if this worth for Pressman :)
def move(move)
squares = move.is_a?(String) ? parse_move(move) : move
- validate_move(squares)
+ validate_move!(squares)
- board.kill_stone squares[1]
- board[squares[1]] = board[squares[0]]
- board.clear!(squares[0])
+ board.move!(squares[0], squares[1])
- check_regeneration(squares[1])
- check_reactivation(squares[1])
+ if can_regenerate?(squares[1])
- check_winner
- next_player
- end
+ regenerate_at = input_regenerate_at
- private
+ board[squares[1]].deactivate
+ board.put_stone(regenerate_at, player) if regenerate_at
- def parse_move(text)
- text.split('-').map{|coord| coord.to_square}
- end
-
- def next_player
- board.player = board.oponent
+ else
+ check_reactivation(squares[1])
+ end
+ check_for_winner
+ next_player
end
- def validate_move(squares)
- raise error("You don't have a stone in #{squares[0].to_coord}") unless board.friend_stone?(squares[0])
+ def validate_move!(squares)
+ raise error("You don't have a stone in #{board.to_coord(squares[0])}") unless board.friend?(squares[0])
- delta = squares[1].subs squares[0]
+ delta = vector_subs(squares[1], squares[0])
# can move along rows or columns. In this case or row not change or column not change
is_straight = (delta[1]*delta[0] == 0)
- # can move along diagonals. In this case the change rate rows / columns == 1
+ # can move along diagonals. In this case rows / columns == 1
is_diagonal = (delta[0] != 0) && ((delta[1] / delta[0]).abs == 1)
raise error("Invalid move") unless (is_straight || is_diagonal)
- occupied = first_between(squares, :is_occupied?)
- occupied = squares[1] if board.friend_stone?(squares[1])
- raise error("Square #{occupied.to_coord} is occupied") if occupied
+ occupied = first_occupied(squares[0], squares[1])
+ occupied = squares[1] if board.friend?(squares[1])
+ raise error("Square #{board.to_coord( occupied)} is occupied") if occupied
+ end
+
+ def can_regenerate?(square)
+ # check stone is at their top and active
+ if board.at_top?(square, player) && board[square].active?
+ free_square = first_free_at_bottom
+ end
+ end
+
+ def check_reactivation(square)
+ board[square].activate if board.at_home?(square)
+ end
+
+ def check_for_winner
+ @winner = player if stones[oponent] == 0
+ end
+
+ def first_occupied(first_sqr, last_sqr)
+ first_between(first_sqr, last_sqr, :is_occupied?)
end
- def first_between(squares, condition, inclusive = nil)
- step = squares[1].subs(squares[0]).map {|c| c <=> 0 } # map to signum
- checked = squares[0]
- checked = checked.sum(step) if !inclusive
- while checked != squares[1]
+ # Returns free square at player's bottom
+ def first_free_at_bottom
+ bottom_first = [board.bottom(player), 0]
+ bottom_last = [board.bottom(player), board.max_column]
+ first_between(bottom_first, bottom_last, :is_empty?, :inclusive)
+ end
+
+ private # some helpers
+
+ def parse_move(text)
+ text.split('-').map{|coord| board.to_square(coord)}
+ end
+
+ def input_regenerate_at
+ gui.say "column for regenration?"
+ col = gui.get_column
+ [board.bottom(player), col]
+ end
+
+ # find first square that satisfy condition, along the path first_sqr ... last_sqr
+ def first_between(first_sqr, last_sqr, condition, inclusive = nil)
+ step = vector_subs(last_sqr, first_sqr).map {|c| c <=> 0 } # map to signum
+ checked = first_sqr
+ checked = vector_sum(checked, step) if !inclusive
+ while checked != last_sqr
return checked if board.send(condition, checked)
- checked = checked.sum(step)
+ checked = vector_sum(checked, step)
end
return checked if inclusive && board.send(condition, checked)
nil
end
- def check_regeneration(square)
- return unless board.stone_activated?(square)
- return unless board.stone_at_top?(square)
-
- board.deactivate_stone(square)
-
- bottom = [board.stone_bottom(square), 0]
- bottom_row = [bottom, bottom.sum([0, 7])]
+ # A simple strategy for allow multiple board setups.
+ # This could be extended to reload a game play ...
- free_square = first_between(bottom_row, :is_empty?, :inclusive)
- return unless free_square
- board.put_stone(free_square)
+ def board_setup(template)
+ send("#{template}_setup")
end
- def check_reactivation(square)
- board.activate_stone(square) if board.stone_at_side?(square)
+ def empty_setup
+ for row in 0..board.max_row do
+ for col in 0..board.max_column do
+ board.clear!([row, col])
+ end
+ end
end
- def check_winner
- return if stone_count[Color.to_ord(oponent)] > 0
- @winner = player
- @display.say("#{Color.to_s(@winner)} player wins!!")
+ def game_setup
+ for row in 0..board.max_row do
+ case row
+ when (0..1)
+ color = :white
+ when (6..board.max_row)
+ color = :black
+ else
+ color = nil
+ end
+ for col in 0..board.max_column do
+ board.put_stone([row, col], color)
+ end
+ end
end
end
end
View
116 lib/pressman/game_gui.rb
@@ -0,0 +1,116 @@
+module Pressman
+
+ # A simple GUI for Pressman game.
+ # Currently only 8x8 board are supported
+
+ class GameUI
+ COLUMN_LABELS = ' 1 2 3 4 5 6 7 8'
+ ROW_LABELS = "abcdefgh"
+ ROW_SEP = ' ' + "-" * (4*8)
+
+ attr_reader :game
+
+ def get_square_icon(row, col)
+ stone = game.board[[row, col]]
+ if stone
+ icon = {:white => 'o', :black => 'x'}[stone.color]
+ icon = icon.upcase if stone.inactive?
+ else
+ icon = ' '
+ end
+ icon
+ end
+
+ def initialize(game)
+ @game = game
+ game.gui = self
+ end
+
+ def draw_board
+ say "#{Time.now}"
+ say COLUMN_LABELS
+ for row in 0..7 do
+ row_draw = []
+ for col in 0..7 do
+ row_draw << get_square_icon(row, col)
+ end
+ say ROW_SEP
+ say "#{ROW_LABELS[row]}| #{row_draw.join(' | ')} |"
+ end
+ say ROW_SEP
+ say "Stones: " + game.stones.map { |k, v| "#{k.capitalize} = #{v}"}.join(' ')
+ say "#{@flash}" if @flash
+ @flash = nil
+ say "#{game.player.capitalize} move?"
+ end
+
+ def say(*args)
+ puts(*args)
+ end
+
+ def get_column
+ result = nil
+ while !result
+ txt = gets.chomp
+ case txt
+ when /[1-9]/
+ result = txt.to_i
+ end
+ end
+ result - 1
+ end
+
+ def terminate
+ if game.winner
+ say("#{game.winner.capitalize} player wins!!")
+ @terminate = true
+ end
+ @terminate
+ end
+
+ def run
+ say 'Welcome to Pressman Game!'
+ game.start
+ while not terminate
+ draw_board
+ input(gets.chomp)
+ end
+ end
+
+ def input(command)
+ begin
+ case command
+ when /[a-h]\d\s*=\s*(e|b|w)/
+ coord, stone = command.split('=').map {|s| s.strip}
+ color = {'e' => nil, 'w' => :white, 'b' => :black}[stone]
+ game.put_stone(coord, color)
+
+ when /([a-h]\d)-([a-h]\d)/
+ game.move command
+ @flash = "Moved #{$1} to #{$2}"
+
+ when 'r'
+ say("You resigns")
+ game.resing
+
+ when 'e'
+ game.start(:empty)
+
+ when 'g'
+ game.start(:game)
+
+ when 'q'
+ say "Goodbye ..."
+ @terminate = true
+ end
+
+ rescue Pressman::Error => e
+ @flash = command + " error!: #{e.message}"
+
+ rescue Exception => e
+ @flash = command + " error!: #{e.message}" + "\n" + e.backtrace.join("\n")
+ end
+ end
+ end
+end
+
View
32 lib/pressman/stone.rb
@@ -0,0 +1,32 @@
+module Pressman
+ class Stone
+ attr :color
+
+ def initialize(color)
+ @color = color
+ activate
+ end
+
+ def active?
+ @active
+ end
+
+ def inactive?
+ !@active
+ end
+
+ def activate
+ @active = true
+ end
+
+ def deactivate
+ @active = false
+ end
+
+ def toggle
+ @active = !active
+ end
+
+ end
+end
+
View
20 lib/pressman/vector.rb
@@ -0,0 +1,20 @@
+
+# some shared helpers
+
+module Pressman
+ module Vector
+ # operate squares like vectors
+ def vector_sum(ary1, ary2)
+ ary1.zip(ary2).map do |pair|
+ pair[0].to_i + pair[1].to_i
+ end
+ end
+
+ def vector_subs(ary1, ary2)
+ ary1.zip(ary2).map do |pair|
+ pair[0].to_i - pair[1].to_i
+ end
+ end
+ end
+end
+
View
59 spec/pressman/board_spec.rb
@@ -0,0 +1,59 @@
+require 'spec_helper'
+module Pressman
+ describe Board do
+ let(:board) { Board.new(8,8) }
+
+ it "is created ok" do
+ board.max_row.should == 7
+ board.max_column.should == 7
+ board.stones.should == {:white => 0, :black => 0}
+ end
+
+ context "adding a stone" do
+ before(:each) { board.put_stone("c3", :black) }
+
+ it "change the sqaure state" do
+ board["c3"].color.should == :black
+ end
+
+ it "stone counts are adjusted" do
+ board.stones.should == {:white => 0, :black => 1}
+ end
+ end
+
+ context "clearing a square" do
+ before(:each) { board.put_stone("c3", :black) }
+
+ it "at occupied square" do
+ board.clear!("c3")
+ board["c3"].should == nil
+ end
+
+ it "stone counts are adjusted" do
+ board.clear!("c3")
+ board.stones.should == {:white => 0, :black => 0}
+ end
+ end
+
+ context "moving a stone" do
+ before(:each) {
+ board.put_stone("c3", :black)
+ board.put_stone("d4", :white)
+ board.move!("c3","d4")
+ }
+
+ it "source square is cleared" do
+ board["c3"].should == nil
+ end
+
+ it "target square is occupied" do
+ board["d4"].color.should == :black
+ end
+
+ it "stone counts are adjusted" do
+ board.stones.should == {:white => 0, :black => 1}
+ end
+ end
+ end
+end
+
View
120 spec/pressman/game_spec.rb
@@ -1,93 +1,149 @@
+# I know is good practice spec folder mimics lib folder structure
+#
+#
+#
+
require 'spec_helper'
module Pressman
describe Game do
- let(:display) {double('display').as_null_object }
- let(:game) {game = Game.new(display); game.board.stub(:draw); game}
-
- describe "at start" do
- it "sends a welcome message" do
- display.should_receive(:say).with('Welcome to Pressman Game!')
- game.start
- end
+ let(:game) do
+ game = Game.new
+ game.stub!(:input_regenerate_at).and_return {game.first_free_at_bottom}
+ game
+ end
+ describe "start" do
it "White begin as oponent" do
game.start
- game.oponent.should == Color::White
+ game.oponent.should == :white
end
it "Black starts the game" do
game.start
- game.player.should == Color::Black
+ game.player.should == :black
end
it "Stones count is ok" do
game.start
- game.stone_count.should == [32, 16, 16]
+ game.stones.should == {:white => 16, :black => 16}
end
end
describe "Game Over" do
it "player loses if all their stones are captured" do
+ # board setup for test
game.start :empty
- game.board["h4"] = Color::Black
- game.board["a4"] = Color::White
-
- display.should_receive(:say).with('Black player wins!!')
+ game.put_stone("h4", :black)
+ game.put_stone("a4", :white)
game.move "h4-a4"
- game.stone_count.should == [62, 0, 2]
+ game.winner.should == :black
end
+
end
- describe "when player try" do
+ describe "playing" do
context "an invalid move" do
before(:each) {game.start}
it "is refused if origin empty" do
expect { game.move("c1-b5")}.to raise_error(RuntimeError, "You don't have a stone in c1")
end
- it "is refused if target occupied" do
+ it "is refused if target occupied by oponent" do
expect { game.move("g2-g3")}.to raise_error(RuntimeError, "Square g3 is occupied")
end
it "is refused if path occupied by a fiend stone" do
- game.board["d2"] = game.player
- expect { game.move("g5-c1")}.to raise_error(RuntimeError, "Square d2 is occupied")
+ game.put_stone("d2", game.player)
+ expect { game.move("g5-c1") }.to raise_error(RuntimeError, "Square d2 is occupied")
end
it "is refused if path occupied by an oponent stone" do
- game.board["d2"] = game.oponent
+ game.put_stone("d2", game.oponent)
expect { game.move("g2-c2")}.to raise_error(RuntimeError, "Square d2 is occupied")
end
end
- context "a valid move" do
+ context "after a valid move" do
+ it "player turn change" do
+ game.start
+ player = game.player
+ game.move("g5-c5")
+ game.oponent.should == player
+ end
+
it "their stone is moved" do
game.start
- old_stones = game.stone_count.dup
player = game.player
- game.board.occupied_by?('g5', player).should be_true
- game.board.is_empty?('c5').should be_true
game.move("g5-c5")
game.board.is_empty?('g5').should be_true
game.board.occupied_by?('c5', player).should be_true
- game.stone_count.should == old_stones
+ end
+
+ it "stone count not change if no caputre" do
+ game.start
+ old_stones = game.stones.dup
+ game.move("g5-c5")
+ game.stones.should == old_stones
end
it "kill a stone if target square is not free" do
game.start
- old_stones = game.stone_count.dup
+ old_stones = game.stones.dup
player = game.player
- game.board.occupied_by?('g5', player).should be_true
- game.board.occupied_by?('b5', game.oponent).should be_true
+ oponent = game.oponent
game.move("g5-b5")
- game.board.is_empty?('g5').should be_true
- game.board.occupied_by?('b5', player).should be_true
- game.stone_count.subs(old_stones).should == [1, -1, 0]
+ game.stones[player].should == old_stones[player]
+ game.stones[oponent].should == old_stones[oponent] - 1
end
end
+ end
+
+ context "regeneration" do
+ before(:each) do
+ game.start :empty
+ game.put_stone "h4", game.player
+ end
+
+ it "generate a stone when player move to top" do
+ old_stones = game.stones.dup
+ player = game.player
+ oponent = game.oponent
+ game.move("h4-a4")
+ # the generated stone goes at first free square in bottom row
+ game.board.is_occupied?("h1").should be_true
+ game.stones[oponent].should == old_stones[oponent]
+ game.stones[player].should == old_stones[player] + 1
+ end
+
+ it "Stone is deactivated when move to top" do
+ game.move("h4-a4")
+ game.board["a4"].active?.should be_false
+ end
+
+ it "Stone deactivation is mantained if not cross side" do
+ game.stub(:next_player)
+ # force deactivation
+ game.move("h4-a4")
+
+ game.move("a4-c4")
+ game.board["c4"].active?.should be_false
+
+ end
+
+ it "Stone is reactivated when move to their side" do
+ game.stub(:next_player)
+
+ # force deactivation
+ game.move("h4-a4")
+
+
+ # check reactivation is mantained if cross side
+ game.move("a4-e4")
+ game.board["e4"].active?.should be_true
+ end
end
end
end
View
45 spec/pressman/regeneration_spec.rb
@@ -1,45 +0,0 @@
-
-require 'spec_helper'
-module Pressman
- describe Game do
- let(:display) {double('display').as_null_object }
- let(:game) {game = Game.new(display); game.board.stub(:draw); game}
-
- context "regeneration" do
- before(:each) do
- game.start :empty
- game.board.put_stone "h4"
- end
-
- it "generate a stone when player move to top" do
- old_stones = game.stone_count.dup
- game.move("h4-a4")
- # the generated stone goes at first free square in bottom row
- game.board.is_occupied?("h1").should be_true
- game.stone_count.subs(old_stones).should == [-1, 0, 1]
- end
-
- it "Stone is deactivated when move to top" do
- old_count = game.stone_count.dup
- game.move("h4-a4")
- game.board.stone_activated?("a4").should be_false
- end
-
- it "Stone is reactivated when move to their side" do
- game.stub(:next_player)
-
- # force deactivation
- game.move("h4-a4")
-
- # check deactivation is mantained if not cross side
- game.move("a4-c4")
- game.board.stone_activated?("c4").should be_false
-
- # check reactivation is mantained if cross side
- game.move("c4-e4")
- game.board.stone_activated?("e4").should be_true
- end
- end
- end
-end
-
View
1  spec/spec_helper.rb
@@ -1,2 +1,3 @@
require 'pressman'
+include Pressman::Vector
Please sign in to comment.
Something went wrong with that request. Please try again.