Skip to content
Newer
Older
100644 380 lines (321 sloc) 12.6 KB
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
1 """
2 An AI agent to play (and win) Spite and Malice
3 """
4
5 from model import *
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
6 from player import Player
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
7 import sys
8 import random
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 22, 2010
9 from copy import copy, deepcopy
6201595 AI almost complete
Pontiffx authored Feb 23, 2010
10 from cardmodels import Card
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
11 from time import sleep
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
12 import logging
13
14 log = logging.getLogger("snm.agent")
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
15
16
17 class StateNode(object):
18 " A node in the search that represents a current state of the board "
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
19 SELF = "self"
20 OTHER = "other"
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
21
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
22 def __init__(self, state, action=None, parent_node=None):
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
23 self.state = state
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
24 self.action = action
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
25 self.parent_node = parent_node
26 self.child_nodes = []
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
27 self.util_value = 0
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
28 self.player = self.SELF
29
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
30 def __eq__(self, other):
31 " Override equality so that we can remove duplicate states. "
32 if other == None or type(other) != StateNode:
33 return False
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
34 if self.state == other.state and self.action == other.action:
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
35 return True
36 return False
37
38 def __ne__(self, other):
39 return not self.__eq__(other)
40
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
41 def __str__(self):
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
42 return "Node[%d](p:%s|%s,%s,childs:%d)" % (
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
43 self.util_value, self.player, self.action, self.state, len(self.child_nodes))
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
44
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
45
46 class ComputerPlayer(Player):
47 """
48 An AI player for Spite and Malice. This uses a modified version of minimax that
49 checks each state to see which player is player, and evaluates accordingly.
50 """
51
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
52 MIN_VALUE = -sys.maxint
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
53 MAX_VALUE = sys.maxint
54
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
55 def __init__(self):
56 " setup the ai "
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
57 # list of moves stored up
58 self.play_queue = []
59
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
60 def play_card(self, game_state):
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
61 """
62 my_cards: cards in their hand, the top card on their payoff stack, and their discard piles.
63 opponents_cards: the top card of the opponents payoff stack, and their discard piles.
64 center_stacks: the enter center stacks
65 """
66 # play queued moves if we have some
67 if len(self.play_queue) > 0:
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
68 sleep(0.3)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
69 return self.play_queue.pop(0)
70
71 # find the best possible move
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
72 self.terminal_nodes = []
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
73 node = StateNode(game_state)
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
74 self._evaluate(node)
75
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
76 self._build_play_queue()
77 return self.play_queue.pop(0)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
78
79
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
80 def _evaluate(self, node):
81 " Evaluate a node, and recurse if necessary "
82 # no reason to get util for starting state
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
83 if node.parent_node:
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
84 node.util_value = self._utility(node)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
85
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
86 if self._terminal_test(node):
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
87 log.info("Adding terminal %s" % node)
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
88 self.terminal_nodes.append(node)
89 return
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
90
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
91 # evaluate all child nodes
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
92 log.info("Evaluating %d succcessor" % len(node.child_nodes))
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
93 for child_node in node.child_nodes:
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
94 self._evaluate(child_node)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
95
96
97
98 def _terminal_test(self, node):
99 """
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
100 Check if this node is the last node in its path that can be evaluated. If
101 it is not calls sucessors to populate the child nodes of the node.
102 Returns True if this is a terminal node, False otherwise.
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
103 """
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
104 # if nothing was done, can't be a terminal node
105 if not node.action:
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
106 node.child_nodes = self._successors(node)
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
107 return False
108
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
109 # if move is a pay_off for either player, it's a terminal node
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
110 if node.action.from_pile == PAY_OFF:
111 return True
112
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
113 # node is a play for SELF
114 if node.player == StateNode.SELF:
115 # we emptied hand without a discard
116 if not len(node.state.get_player()[HAND]) and node.action.to_pile != DISCARD:
117 return True
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
118
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
119 # discard is only move
120 if node.action.to_pile == DISCARD and node.parent_node and not node.parent_node.action:
121 return True
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
122
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
123 # otherwise generate successors
124 node.child_nodes = self._successors(node)
125
126 # we've played center cards, so we want to see what the opponent can do
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
127 if node.action.to_pile == DISCARD and node.player == StateNode.SELF:
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
128 return False
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
129
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
130 # we can't determine any more moves for either player
131 if not node.child_nodes:
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
132 return True
133
134 return False
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
135
136
137 def _successors(self, node):
138 """
139 Return a list of successor nodes for the current node. Each node is a valid move.
140 """
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
141 log.debug("Generating successors for %s" % node)
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
142 node_list = []
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
143 # moves for the computer player as long as we didn't discard
144 if node.player == StateNode.SELF and (not(node.action) or node.action.from_pile != DISCARD):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
145
146 # moves to center
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
147 for pile_name, pile_len in [(HAND,1), (PAY_OFF,1), (DISCARD,4)]:
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
148 # TODO: skip extra piles of same length as one we've already evaled
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
149 for pile_id in range(pile_len):
150 for action in self._get_center_move_from(node.state, pile_name, pile_id):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
151 new_state = ComputerPlayer._new_state_from_action(node.state, action)
152 new_node = StateNode(new_state, action, node)
153 if new_node not in node_list:
154 node_list.append(new_node)
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
155 else:
156 log.warn('skip duplicate state %s' % new_node)
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
157
158 # moves to discard
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
159 for card in node.state.get_player()[HAND]:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
160 # can't discard kings
161 if Card.to_numeric_value(card) == 13:
162 continue
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
163 # TODO: only consider one empty pile
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
164 for pile_id in range(len(node.state.get_player()[DISCARD])):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
165 action = PlayerMove(card, from_pile=HAND, to_pile=DISCARD, to_id=pile_id)
166 new_state = ComputerPlayer._new_state_from_action(node.state, action)
167 new_node = StateNode(new_state, action, node)
168 if new_node not in node_list:
169 node_list.append(new_node)
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
170 else:
171 log.warn('skip duplicate state %s' % new_node)
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
172 return node_list
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
173
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
174 # opponent plays card on center
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
175 for pile_name, pile_len in [(PAY_OFF,1), (DISCARD,4)]:
176 for pile_id in range(pile_len):
177 for action in self._get_center_move_from(node.state, pile_name, pile_id, True):
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
178 new_state = ComputerPlayer._new_state_from_action(node.state, action, True)
179 new_node = StateNode(new_state, action, node)
180 if new_node not in node_list:
181 node_list.append(new_node)
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
182 else:
183 log.warn('skip duplicate state %s' % new_node)
184 return node_list
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
185
186 @staticmethod
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
187 def _get_center_move_from(state, pile_name, pile_index, other_player=False):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
188 " Get all the valid center stack placements from a pile "
189 moves = []
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
190
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
191 # set pile to HAND or PAY_OFF stacks
192 pile = state.get_player(other_player)[pile_name]
193 # otherwise, set it to top of DISCARD
194 if pile_name == DISCARD:
195 if len(state.get_player(other_player)[pile_name][pile_index]) < 1:
196 return moves
197 pile = [state.get_player(other_player)[pile_name][pile_index][-1]]
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
198
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
199 for i in range(len(pile)):
200 card = pile[i]
201 for center_id in range(len(state.center_stacks)):
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
202 if state.can_place_card_in_center(state.center_stacks[center_id], card):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
203 moves.append(PlayerMove(card, from_pile=pile_name, from_id=pile_index,
204 to_pile=CENTER, to_id=center_id))
205 return moves
206
207
208 @staticmethod
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
209 def _new_state_from_action(state, action, swap_player=False):
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
210 " Return a new state created from the previous state and the action "
211 new_state = deepcopy(state)
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
212 if swap_player:
213 new_state.swap_players()
4393627 Some progress on AI. GameState now extends the game mode, so we can r…
Pontiffx authored Feb 23, 2010
214 new_state.place_card(action)
215 return new_state
216
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
217 class PointTracker(dict):
218 """
219 dictionary wrapper class to keep track of which points are being used
220 for the final utility value.
221 """
222 def __init__(self, d):
223 dict.__init__(self, d)
224 self.used = []
225 def __getitem__(self, key):
226 if key not in ['discard_common', 'op_dist_op', 'discard_least', 'card_in_discard']:
227 self.used.append(key)
228 return dict.__getitem__(self, key)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
229
230 def _utility(self, node):
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
231 """
232 Calculate the utility value for this state node.
233 """
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
234
235 # TODO: discard values should be less then playing op_dist_po cards
236 # TODO: points for playing on empty discard stack
237 # TODO: organize values into sections (DISCARD, OTHER, PAYOFF), base points for each
238 points = self.PointTracker({
239 'pay_off': 400, # Play pay_off card
240 'empty_hand': 120, # Empty hand without a discard
241 'discard_same': 32, # Discard on same value card
242 'discard_common': 10, # Each time the discard card occures in the hard
243 'op_dist_po': 4, # Each point away the closest center is from opponents pay off (max +48)
244 'bury_least': 2, # Discard buries the least essential card
245 'discard_least': 1, # Discard least essential card
246 'card_in_discard': -1, # each card in discard
247 'hand_cards': -3, # Each card in hand
248 'op_pay_off': -80, # Opponent plays pay_off card
249 })
250
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
251 # shortcut vars
252 center_values = []
253 for pile in node.state.center_stacks:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
254 center_values.append(len(pile))
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
255 if node.player == StateNode.SELF:
256 myself = node.state.get_player()
257 other = node.state.get_player(True)
258 else:
259 myself = node.state.get_player(True)
260 other = node.state.get_player()
261
262 value = 0
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
263 if node.player == StateNode.SELF:
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
264 # pay off played
265 if node.action.from_pile == PAY_OFF:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
266 value += points['pay_off']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
267 # empty hand without a discard
268 if len(myself[HAND]) == 0 and node.action.to_pile != DISCARD:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
269 value += points['empty_hand']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
270 # each time the discard cards value ocurs in the hand
271 if node.action.to_pile == DISCARD:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
272 value += points['discard_common'] * map(lambda c: Card.to_numeric_value(c), myself[HAND]).count(
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
273 Card.to_numeric_value(node.action.card))
274 # discard on same value card
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
275 if node.action.to_pile == DISCARD and len(myself[DISCARD][node.action.to_id]) > 1 \
276 and Card.to_numeric_value(myself[DISCARD][node.action.to_id][-1]) == \
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
277 Card.to_numeric_value(myself[DISCARD][node.action.to_id][-2]):
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
278 value += points['discard_same']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
279 # discad buries least essential card
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
280 if node.action.to_pile == DISCARD and len(myself[DISCARD][node.action.to_id]) >= 1:
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
281 discard_piles = []
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
282 for pile_id in range(len(myself[DISCARD])):
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
283 pile = myself[DISCARD][pile_id]
284 if len(pile) > 1 and node.action.to_id:
285 discard_piles.append(pile[-2])
286 elif len(pile) > 1:
287 discard_piles.append(pile[-1])
288 else:
289 discard_piles.append(None)
290 if node.action.to_id == self._find_least_essential_card(center_values,
291 discard_piles, myself[PAY_OFF][-1]):
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
292 # TODO: broken ? always discards on 0
293 value += points['bury_least']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
294 # discard least essential card
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
295 if node.action.to_pile == DISCARD and 0 == self._find_least_essential_card(
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
296 center_values, [node.action.card] + myself[HAND], myself[PAY_OFF][-1]):
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
297 value += points['discard_least']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
298 # each point away the closest center is from opponents pay off
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
299 value += points['op_dist_po'] * self._distance_between_values(self._find_closest_center_stack_value(
300 center_values, other[PAY_OFF][-1]), Card.to_numeric_value(other[PAY_OFF][-1]))
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
301 # each card in hand
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
302 value += points['hand_cards'] * len(myself[HAND])
303 # each card in discard
304 value += points['card_in_discard'] * sum(map(lambda p: len(p), myself[DISCARD]))
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
305
306 else:
307 # opponent plays pay_off
308 if node.action.from_pile == PAY_OFF:
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
309 value -= points['op_pay_off']
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
310
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
311 # cumulative utils
312 log.debug("Util %d from: (%s)" % (value, points.used))
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
313 return value + node.parent_node.util_value
314
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
315
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
316 @staticmethod
317 def _find_least_essential_card(center_values, pile, pay_off_card):
318 """
319 Return the id in pile that is considered least essential relative to the
320 pay off card.
321 """
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
322 # TODO: broken, returns cards below value, should return highest outside range from center -> payoff,
323 # for at least the case of discards, maybe this is used correctly elsewhere ?
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
324 center_value = ComputerPlayer._find_closest_center_stack_value(center_values, pay_off_card)
325 list_values = map(lambda c: ComputerPlayer._distance_between_values(
326 center_value, Card.to_numeric_value(c)), pile)
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
327
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
328 card = pile[list_values.index(max(list_values))]
de20a47 More bug fixes to AI
Pontiffx authored Feb 27, 2010
329 log.debug("Least essential card for center_values[%s] and pay_off[%s]: %s" % (
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
330 "".join(map(str, center_values)), pay_off_card, card))
331 return card
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
332
333
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
334 @staticmethod
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
335 def _find_closest_center_stack_value(center_values, pay_off_card):
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
336 """
337 return the value from the center stack that is closest available
338 for playing the pay_off_card.
339 """
340 po_value = Card.to_numeric_value(pay_off_card)
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
341 return min(map(lambda v: ComputerPlayer._distance_between_values(v, po_value), center_values))
6201595 AI almost complete
Pontiffx authored Feb 24, 2010
342
343
344 @staticmethod
345 def _distance_between_values(pile_card, play_card):
346 " find the distance between the pile card, and the play card values"
347 if pile_card == None:
348 return play_card
349 if play_card > pile_card:
350 return play_card - pile_card
351 if play_card == pile_card:
352 return 12
353 return 12 - pile_card + play_card
354
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
355 def _build_play_queue(self):
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
356 """
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
357 Find the best path, and build the play queue for this path.
358 In the case of a tie, pick a random path
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
359 """
94cd02d More progress on the AI
Pontiffx authored Feb 26, 2010
360 log.info("Choosing from %d possible paths" % len(self.terminal_nodes))
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
361 node = max(self.terminal_nodes, key=lambda s: s.util_value)
362
363 chain = []
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
364 # loop while there are still nodes in the chain
365 while node:
5931471 Adding logger for AI, AI running, still some bugs with util of discards
Pontiffx authored Feb 25, 2010
366 # skip any opponent nodes we have in the chain
367 if node.player == StateNode.OTHER:
368 node = node.parent_node
369 continue
370 chain.append(node.action)
371 node = node.parent_node
372
373 # remove the starting state, and reverse the list, so we can traverse the path
374 chain.pop()
375 chain.reverse()
376 log.info("Chosing path: %s" % (" ".join(map(str, chain))))
377 self.play_queue = chain
4306df9 Refactored the game so the view is actually in the view, and players…
Pontiffx authored Feb 21, 2010
378
379
Something went wrong with that request. Please try again.