Class: RubyKnight::BoardEvaluator

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyknight/evaluator.rb

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (BoardEvaluator) initialize(board)

Returns a new instance of BoardEvaluator



4
5
6
7
# File 'lib/rubyknight/evaluator.rb', line 4

def initialize board
	@b = board
	@bestmoves, @bestscore, @donethinking = nil, 0, false
end

Instance Attribute Details

- (Object) bestmoves (readonly)

Returns the value of attribute bestmoves



3
4
5
# File 'lib/rubyknight/evaluator.rb', line 3

def bestmoves
  @bestmoves
end

- (Object) donethinking (readonly)

Returns the value of attribute donethinking



3
4
5
# File 'lib/rubyknight/evaluator.rb', line 3

def donethinking
  @donethinking
end

Instance Method Details

- (Object) bestmove

Pick a random move from equal options



10
11
12
13
14
15
# File 'lib/rubyknight/evaluator.rb', line 10

def bestmove
	if @bestmoves
		return @bestmoves[Kernel.rand(@bestmoves.size)]
	end
	nil
end

- (Object) eval_material(board)



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/rubyknight/evaluator.rb', line 102

def eval_material board
	q, r, b, n, p = 9, 5, 3, 3, 1
	white = p * board.num_pieces(RubyKnight::Board::WPAWN) +
       		q * board.num_pieces(RubyKnight::Board::WQUEEN) +
       		r * board.num_pieces(RubyKnight::Board::WROOK) +
       		b * board.num_pieces(RubyKnight::Board::WBISHOP) +
       		n * board.num_pieces(RubyKnight::Board::WKNIGHT)
	black = p * board.num_pieces(RubyKnight::Board::BPAWN) +
       		q * board.num_pieces(RubyKnight::Board::BQUEEN) +
       		r * board.num_pieces(RubyKnight::Board::BROOK) +
       		b * board.num_pieces(RubyKnight::Board::BBISHOP) +
       		n * board.num_pieces(RubyKnight::Board::BKNIGHT)

	white - black		
end

- (Object) eval_pawn_struct(board)



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rubyknight/evaluator.rb', line 43

def eval_pawn_struct board
	advant = board.num_pieces(RubyKnight::Board::WPAWN) - 
	         board.num_pieces(RubyKnight::Board::BPAWN)

	wpawns, bpawns = get_pawn_array board
	passed, isolated, doubled, chained = 0,0,0,0
	(1..8).each do |rank|
		w,wl,wr = wpawns[rank],wpawns[rank-1],wpawns[rank+1]
		b,bl,br = bpawns[rank],bpawns[rank+1],bpawns[rank-1]

		w.each {|c|passed+=1 if (b.size==0||c<b.min)&&(bl.size==0||c<=bl.min)&&(br.size==0||c<=br.min)}
		b.each {|c|passed-=1 if (w.size==0||c>w.max)&&(wl.size==0||c>=wl.max)&&(wr.size==0||c>=wr.max)}

		wchain = false
		w.each { |c|
			wl.each {|i| wchain = true if (c-i).abs <=1 }
			wr.each {|i| wchain = true if (c-i).abs <=1 } unless wchain
		}
		bchain = false
		b.each { |c|
			bl.each {|i| bchain = true if (c-i).abs <= 1 }
			br.each {|i| bchain = true if (c-i).abs <= 1 } unless bchain
		}
		#puts "rank=#{rank} wchain=#{wchain} bchain=#{bchain}"

		isolated +=1 unless w.size>0 && wchain
		isolated -=1 unless b.size>0 && bchain

		chained +=1 if w.size>0 && wchain
		chained -=1 if b.size>0 && bchain
	
		doubled -= 1 if w.size > 1
		doubled += 1 if b.size > 1
	end
	
	chained = if chained==0 then 0
	          elsif chained > 0 then 1
	          else -1 end
	doubled = if doubled==0 then 0
	          elsif doubled > 0 then 1
	          else -1 end
	#puts "#{advant} + #{passed} + #{doubled} + #{chained} - #{isolated}"
	return advant + passed + doubled + chained - isolated
end

- (Object) eval_position(board = @b)

Return an int being the pawn advantage of white



37
38
39
40
41
# File 'lib/rubyknight/evaluator.rb', line 37

def eval_position board=@b
	material = time_it("eval_material") { eval_material(board)}
	pawn_struct = time_it("eval_pawn_struct") { eval_pawn_struct(board)}
	material + pawn_struct
end

- (Object) get_pawn_array(board)

make array of pawns[rank]



89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rubyknight/evaluator.rb', line 89

def get_pawn_array board
	wpawns = Array.new(10)
	bpawns = Array.new(10)
	(0..9).each { |i| wpawns[i] = Array.new 0, 0}
	(0..9).each { |i| bpawns[i] = Array.new 0, 0}
	board.piece_positions(RubyKnight::Board::WPAWN).each \
		{ |p| wpawns[(p%8)+1] << (p/8) }
	board.piece_positions(RubyKnight::Board::BPAWN).each \
		{ |p| bpawns[(p%8)+1] << (p/8) }
	return wpawns, bpawns
end

- (Object) think(for_white)



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/rubyknight/evaluator.rb', line 17

def think for_white
	@bestmoves, @bestscore, @donethinking = nil, 0, false
	clone = Marshal.load(Marshal.dump( @b))
	clone.gen_legal_moves.each do |move|
		newb = Marshal.load(Marshal.dump( clone))
		newb.move move[0], move[1], move[2]
		result = eval_position newb
		if (for_white and result > @bestscore) or
			   result < @bestscore or @bestmoves == nil
			  @bestscore = result 
			  @bestmoves = [move]
		elsif result == @bestscore
			@bestmoves << move	
		end
	end
	@donethinking = true
end

- (Object) time_it(label)



118
119
120
121
122
123
# File 'lib/rubyknight/evaluator.rb', line 118

def time_it label
	start = Time.now
	res = yield
	#puts "TIMING( '#{label}=>#{res}'): #{Time.now - start} seconds"
	res
end