Initial commit
[trapthecap.git] / src / libttc-pplayer.rb
1 # == Synopsis
2 #
3 # Library to support a Trap the Cap player that uses potentials to select the
4 # best move
5 #
6 # == Author
7 # Neil Smith
8 #
9 # == Change history
10 # Version 1.1:: 23 April 2008
11
12 require 'libttc'
13
14 # Play Trap the Cap by using potential fields. For each possible move,
15 # calculate the field strength and pick the move with the lowest potential
16 class Potential_player
17
18 attr_reader :friend_pull, :enemy_pull, :base_pull,
19 :safe_bonus, :capture_bonus
20
21 def initialize(args, verbose = false)
22 @friend_pull = args[:friend_pull] || 1
23 @enemy_pull = args[:enemy_pull] || 0.5
24 @base_pull = args[:base_pull] || 2
25 @safe_bonus = args[:safe_bonus] || 8
26 @capture_bonus = args[:capture_bonus] || 10
27
28 @verbose = verbose
29 end
30
31 # Find the best move of the possible ones
32 def best_move(game, die_result)
33 me = game.current_player
34 possible_moves = game.possible_moves(die_result, me)
35 scored_moves = possible_moves.collect do |m|
36 begin
37 game.apply_move! m
38 score = score_position(game, me)
39 # game.undo_move!
40 rescue GameWonNotice
41 score = 10000
42 ensure
43 game.undo_move!
44 end
45 puts "#{m} scores #{score}" if @verbose
46 [m, score]
47 end
48 best_move = (scored_moves.max {|a, b| a[1] <=> b[1]})[0]
49 end
50
51 # Calculate the potential score of a position for a given player
52 def score_position(game, player)
53 score = 0
54 game.pieces.each_value do |piece|
55 here = piece.position
56 if piece.colour == player
57 game.pieces.each_value do |other_piece|
58 if other_piece.colour == player
59 score += game.board.distance_between[here.place][other_piece.position.place] * @friend_pull
60 else
61 score += game.board.distance_between[here.place][other_piece.position.place] * @enemy_pull
62 end
63 end
64 score += piece.contains.length * @capture_bonus
65 score += game.board.distance_between[here.place][game.board.positions[player].place] *
66 piece.contains.length * @base_pull
67 elsif here == game.board.positions[player]
68 score += @safe_bonus
69 end
70 end
71 score
72 end
73
74 end