Updated version to 0.0.7.
[troncode.git] / players / SelfishGitPlayer.py
blob4d00dcd4eff30829c2a34ec63eb8bac675023c7b
1 import math
3 from troncode_values import *
4 from BasicGameBoard import BasicGameBoard
6 STATE_START = 0 # Start
7 STATE_CUT1 = 1 # First part of cutoff step
8 STATE_TURN = 2 # Turning around
9 STATE_CUT2 = 3 # Second part of cutoff step
10 STATE_NORMAL_LEFT = 4 # Normal wallfollower behaviour
11 STATE_NORMAL_RIGHT = 5 # Reversed wallfollower behaviour
12 STATE_KILL_OUT = 6 # We've noticed an opponent - move out to capture
13 STATE_KILL_AROUND = 7 # Move along towards opponent to capture
14 STATE_KILL_DOWN = 8 # Cut off behind opponent
16 ORIENTATION_UNKNOWN = -1
17 ORIENTATION_VERTICAL = 0
18 ORIENTATION_HORIZONTAL = 1
20 BOARD_SIZE = 200
21 ACCEPTABLE_SPACE = 90
23 TURN_AROUND_SIZE = 2000
24 KILL_OUT_PIXELS = 5
26 class SelfishGitPlayer( object ):
27 """Makes a nice space for itself with as few others in it as possible,
28 then follows walls, turning around from time to time,
29 and killing anyone it finds following walls by drawing a little box around them.
30 by Andy Balaam"""
32 def __init__( self ):
33 self._state = STATE_START
34 self.orientation = ORIENTATION_UNKNOWN
35 self.final_dir = -1000
36 self.turn_around_time = TURN_AROUND_SIZE
37 self.kill_out_timer = KILL_OUT_PIXELS
38 self.around_dir = -1000
39 self.down_dir = -1000
40 self.previous_normal_state = STATE_NORMAL_LEFT
41 self.killing_player = -1000
43 def GetColour( self ):
44 return ( 185, 255, 185 )
46 def GetName():
47 return "Selfish Git"
48 GetName = staticmethod( GetName )
50 def GetShortLongDir( self, coord, pasthalf_dir, lessthanhalf_dir ):
51 if coord > ( 200 - coord ):
52 return pasthalf_dir
53 else:
54 return lessthanhalf_dir
56 def GetLongestVerticalDir( self, y_pos ):
57 return self.GetShortLongDir( y_pos, DIR_UP, DIR_DOWN )
59 def GetShortestHorizontalDir( self, x_pos ):
60 return self.GetShortLongDir( x_pos, DIR_RIGHT, DIR_LEFT )
62 def GetLongestHorizontalDir( self, x_pos ):
63 return self.GetShortLongDir( x_pos, DIR_LEFT, DIR_RIGHT )
65 def GetNumOpponents( self, position, other_positions, direction ):
66 ret = 0
67 (my_x, my_y) = position
68 for ((x,y), unused_dir) in other_positions:
69 if direction == DIR_LEFT:
70 if my_x >= x:
71 ret += 1
72 elif direction == DIR_RIGHT:
73 if my_x <= x:
74 ret += 1
75 elif direction == DIR_UP:
76 if my_y >= y:
77 ret += 1
78 elif direction == DIR_DOWN:
79 if my_y <= y:
80 ret += 1
81 return ret
83 def GetAcceptableDirs( self, position ):
84 # Find all the cuts that give us > 40% of the game board
85 space = {}
86 space[DIR_LEFT] = position[0]
87 space[DIR_RIGHT] = BOARD_SIZE - position[0]
88 space[DIR_UP] = position[1]
89 space[DIR_DOWN] = BOARD_SIZE - position[1]
91 ret = []
92 for dr in ( DIR_LEFT, DIR_RIGHT, DIR_UP, DIR_DOWN ):
93 if space[dr] > ACCEPTABLE_SPACE:
94 ret.append( dr )
96 return ret
98 def GetMostSpaceDir( self, position, dirs ):
99 (x, y) = position
100 max_space = -1000
101 max_space_dir = -1000
102 for dr in dirs:
103 if dr == DIR_LEFT:
104 space = x
105 elif dr == DIR_RIGHT:
106 space = BOARD_SIZE - x
107 elif dr == DIR_UP:
108 space = y
109 elif dr == DIR_DOWN:
110 space = BOARD_SIZE - y
111 if space > max_space:
112 max_space_dir = dr
113 max_space = space
114 return max_space_dir
116 def GetBestDir( self, position, other_positions, acceptable_dirs ):
117 min_num_opp = 1000
118 dirs_min = []
119 for direction in acceptable_dirs:
120 num_opp = self.GetNumOpponents( position, other_positions, direction )
121 if num_opp < min_num_opp:
122 min_num_opp = num_opp
123 dirs_min = [ direction ]
124 elif num_opp == min_num_opp:
125 dirs_min.append( direction )
127 if len( dirs_min ) == 1:
128 return dirs_min[0]
129 else:
130 return self.GetMostSpaceDir( position, dirs_min )
132 def IsVertical( self, direction ):
133 return ( direction == DIR_UP or direction == DIR_DOWN )
135 def FindCut1DirFromBestDir( self, position, best_dir ):
136 """best_dir is the part of the board we want to capture - turn to start cutting it off"""
138 # TODO: examine player positions to decide which side to cut off first.
140 (x, y) = position
141 if self.IsVertical( best_dir ):
142 return self.GetLongestHorizontalDir( x )
143 else:
144 return self.GetLongestVerticalDir( y )
146 def FindCut1Dir( self, position, gameboard ):
147 ret_dir = DIR_LEFT
149 other_positions = gameboard.GetPlayerPositions( position )
151 acceptable_dirs = self.GetAcceptableDirs( position )
153 best_dir = self.GetBestDir( position, other_positions, acceptable_dirs )
155 self.final_dir = best_dir
156 return self.FindCut1DirFromBestDir( position, best_dir )
158 def FindFinalDir( self, position ):
159 return self.final_dir
161 def AnyPixelsBetween( self, my_pos, other_pos, gameboard ):
162 off_x = other_pos[0] - my_pos[0]
163 off_y = other_pos[1] - my_pos[1]
165 max_dist = max( abs( off_x ), abs( off_y ), 1 )
167 inc_x = float( off_x ) / float( max_dist )
168 inc_y = float( off_y ) / float( max_dist )
170 float_x = float( my_pos[0] )
171 float_y = float( my_pos[1] )
172 for i in range( max_dist ):
173 float_x += inc_x
174 float_y += inc_y
175 x = math.floor( float_x )
176 y = math.floor( float_y )
177 if ( (x,y) != my_pos and (x,y) != other_pos and
178 gameboard.GetAbsolutePixel( (x, y) ) != 0 ):
179 return True
181 return False
183 def OppositeDir( self, direction, gameboard ):
184 ret_dir = gameboard.TurnLeft( direction )
185 ret_dir = gameboard.TurnLeft( ret_dir )
186 return ret_dir
188 def WithinKillRange( self, my_coord, other_coord ):
189 return ( abs( my_coord - other_coord ) < 3 )
191 def KillAble( self, position, other_position, other_dir, gameboard, ret_ckm ):
192 ( my_x, my_y ) = position
193 ( x, y ) = other_position
195 if self.WithinKillRange( my_x, x ):
196 if ( y <= my_y and other_dir == DIR_DOWN and
197 not self.AnyPixelsBetween( position, other_position, gameboard ) ):
198 ret_ckm.around_dir = DIR_UP
199 return True
200 if ( y >= my_y and other_dir == DIR_UP and
201 not self.AnyPixelsBetween( position, other_position, gameboard ) ):
202 ret_ckm.around_dir = DIR_DOWN
203 return True
204 if self.WithinKillRange( my_y, y ):
205 if ( x <= my_x and other_dir == DIR_RIGHT and
206 not self.AnyPixelsBetween( position, other_position, gameboard ) ):
207 ret_ckm.around_dir = DIR_LEFT
208 return True
209 if ( x >= my_x and other_dir == DIR_LEFT and
210 not self.AnyPixelsBetween( position, other_position, gameboard ) ):
211 ret_ckm.around_dir = DIR_RIGHT
212 return True
213 return False
215 def CheckKillMode( self, position, gameboard ):
216 # TODO: check you are joined by a pixel line to the opponent?
218 class CKM:
219 def __init__( self ):
220 self.can_kill = False
221 self.state = None
222 self.out_dir = None
223 self.around_dir = None
224 self.down_dir = None
225 self.killing_player = None
227 ret = CKM()
229 other_positions = gameboard.GetPlayerPositions( position )
231 player_num = 0
232 for (other_position, other_dir) in other_positions:
233 if self.KillAble( position, other_position, other_dir, gameboard, ret ):
234 ret.can_kill = True
235 ret.state = STATE_KILL_OUT
236 ret.out_dir = gameboard.TurnLeft( other_dir )
237 if gameboard.GetRelativePixel( position, ret.out_dir, 1, 0 ) > 0:
238 ret.out_dir = self.OppositeDir( ret.out_dir, gameboard )
239 ret.down_dir = self.OppositeDir( ret.out_dir, gameboard )
240 ret.killing_player = player_num
241 break
242 player_num += 1
244 return ret
246 def KillAroundPast( self, position, other_position, kill_around_dir ):
247 if ( ( kill_around_dir == DIR_LEFT and position[0] < other_position[0] ) or
248 ( kill_around_dir == DIR_RIGHT and position[0] > other_position[0] ) or
249 ( kill_around_dir == DIR_UP and position[1] < other_position[1] ) or
250 ( kill_around_dir == DIR_DOWN and position[1] > other_position[1] ) ):
251 return True
252 else:
253 return False
255 def State2Str( self, state ):
256 if state == STATE_START:
257 return "STATE_START"
258 elif state == STATE_CUT1:
259 return "STATE_CUT1"
260 elif state == STATE_TURN:
261 return "STATE_TURN"
262 elif state == STATE_CUT2:
263 return "STATE_CUT2"
264 elif state == STATE_NORMAL_LEFT:
265 return "STATE_NORMAL_LEFT"
266 elif state == STATE_NORMAL_RIGHT:
267 return "STATE_NORMAL_RIGHT"
268 elif state == STATE_KILL_OUT:
269 return "STATE_KILL_OUT"
270 elif state == STATE_KILL_AROUND:
271 return "STATE_KILL_AROUND"
272 elif state == STATE_KILL_DOWN:
273 return "STATE_KILL_DOWN"
275 def SetState( self, state ):
276 self._state = state
277 if state in ( STATE_NORMAL_LEFT, STATE_NORMAL_RIGHT ):
278 self.previous_normal_state = state
279 #print self.State2Str( state )
281 def GetDir( self, position, direction, gameboard ):
282 ret_dir = direction
283 if self._state == STATE_START:
284 ret_dir = self.FindCut1Dir( position, gameboard )
285 self.SetState( STATE_CUT1 )
287 elif self._state == STATE_CUT1:
288 # Turn when we hit a wall
289 if gameboard.GetRelativePixel( position, ret_dir, 1, 0 ) != 0:
290 ret_dir = gameboard.TurnLeft( ret_dir )
291 self.SetState( STATE_TURN )
293 elif self._state == STATE_TURN:
294 # Keep turning
295 ret_dir = gameboard.TurnLeft( ret_dir )
296 self.SetState( STATE_CUT2 )
298 elif self._state == STATE_CUT2:
299 if gameboard.GetRelativePixel( position, ret_dir, 1, 0 ) != 0:
300 ret_dir = self.FindFinalDir( position )
301 self.SetState( STATE_NORMAL_LEFT )
303 elif self._state == STATE_KILL_OUT:
304 self.kill_out_timer -= 1
305 if self.kill_out_timer < 0:
306 self.kill_out_timer = KILL_OUT_PIXELS
307 self.SetState( STATE_KILL_AROUND )
308 elif self._state == STATE_KILL_AROUND:
309 other_position = gameboard.GetPlayerPositions( position )[ self.killing_player ][0]
310 if self.KillAroundPast( position, other_position, self.kill_around_dir ):
311 self.SetState( STATE_KILL_DOWN )
312 else:
313 ret_dir = self.kill_around_dir
314 elif self._state == STATE_KILL_DOWN:
315 ret_dir = self.kill_down_dir
316 else:
317 ckm = self.CheckKillMode( position, gameboard )
318 if ckm.can_kill:
319 other_position = gameboard.GetPlayerPositions( position )[0][0]
320 #print "kill (%d,%d) (%d, %d)" % ( position[0], position[1], other_position[0], other_position[1] )
321 self.SetState( ckm.state )
322 self.kill_around_dir = ckm.around_dir
323 self.kill_down_dir = ckm.down_dir
324 self.killing_player = ckm.killing_player
325 ret_dir = ckm.out_dir
326 else:
327 if self._state == STATE_NORMAL_LEFT:
328 if gameboard.GetRelativePixel( position, ret_dir, 0, -1 ) == 0:
329 # Turn left if we can
330 ret_dir = gameboard.TurnLeft( ret_dir )
331 else:
332 self.turn_around_time -= 1
333 if self.turn_around_time < 0:
334 self.turn_around_time = TURN_AROUND_SIZE
335 self.SetState( STATE_NORMAL_RIGHT )
336 elif self._state == STATE_NORMAL_RIGHT:
337 if gameboard.GetRelativePixel( position, ret_dir, 0, 1 ) == 0:
338 ret_dir = gameboard.TurnRight( ret_dir )
339 else:
340 self.turn_around_time -= 1
341 if self.turn_around_time < 0:
342 self.turn_around_time = TURN_AROUND_SIZE
343 self.SetState( STATE_NORMAL_LEFT )
344 else:
345 print "SelfishGit is in an extremely strange state. The Master Control Program has been informed."
346 self.SetState( STATE_NORMAL_LEFT )
348 # Don't enter tunnels of width 1
349 if ( gameboard.GetRelativePixel( position, ret_dir, 1, 1 ) > 0 and
350 gameboard.GetRelativePixel( position, ret_dir, 1, -1 ) > 0 ):
351 ret_dir = gameboard.TurnRight( ret_dir )
352 # If we're killing, favour the "around" direction to get us out of any trouble
353 if self._state in ( STATE_KILL_OUT, STATE_KILL_OUT, STATE_KILL_DOWN ):
354 ret_dir = self.kill_around_dir
355 if self._state not in ( STATE_NORMAL_LEFT, STATE_NORMAL_RIGHT ):
356 self.SetState( self.previous_normal_state )
358 # If we're killing, favour the "around" direction to get us out of any trouble
359 if ( self._state in ( STATE_KILL_OUT, STATE_KILL_OUT, STATE_KILL_DOWN ) and
360 gameboard.GetRelativePixel( position, ret_dir, 1, 0 ) != 0 ):
361 ret_dir = self.kill_around_dir
362 self.SetState( self.previous_normal_state )
364 # Avoid immediate death by turning right
365 for i in range( 4 ):
366 if gameboard.GetRelativePixel( position, ret_dir, 1, 0 ) == 0:
367 break
368 if self._state not in ( STATE_NORMAL_LEFT, STATE_NORMAL_RIGHT ):
369 self.SetState( self.previous_normal_state )
370 ret_dir = gameboard.TurnRight( ret_dir )
372 return ret_dir
374 # ------ TESTS -------
376 def test_GetAcceptableDirs():
377 player = SelfishGitPlayer()
379 drs = player.GetAcceptableDirs( (100, 100) )
380 assert( DIR_UP in drs )
381 assert( DIR_DOWN in drs )
382 assert( DIR_LEFT in drs )
383 assert( DIR_RIGHT in drs )
385 drs = player.GetAcceptableDirs( (10, 100) )
386 assert( DIR_UP in drs )
387 assert( DIR_DOWN in drs )
388 assert( DIR_LEFT not in drs )
389 assert( DIR_RIGHT in drs )
391 drs = player.GetAcceptableDirs( (190, 100) )
392 assert( DIR_UP in drs )
393 assert( DIR_DOWN in drs )
394 assert( DIR_LEFT in drs )
395 assert( DIR_RIGHT not in drs )
397 drs = player.GetAcceptableDirs( (10, 10) )
398 assert( DIR_UP not in drs )
399 assert( DIR_DOWN in drs )
400 assert( DIR_LEFT not in drs )
401 assert( DIR_RIGHT in drs )
403 drs = player.GetAcceptableDirs( (100, 190) )
404 assert( DIR_UP in drs )
405 assert( DIR_DOWN not in drs )
406 assert( DIR_LEFT in drs )
407 assert( DIR_RIGHT in drs )
409 def test_GetNumOpponents():
410 player = SelfishGitPlayer()
412 # 2 to the top-left
413 position = (100, 100)
414 other_positions = [ ((10, 10), 0 ), ((15, 15), 0 ) ]
415 assert( player.GetNumOpponents( position, other_positions, DIR_LEFT ) == 2 )
416 assert( player.GetNumOpponents( position, other_positions, DIR_UP ) == 2 )
417 assert( player.GetNumOpponents( position, other_positions, DIR_RIGHT ) == 0 )
418 assert( player.GetNumOpponents( position, other_positions, DIR_DOWN ) == 0 )
420 # 1 in each corner
421 position = (30, 30)
422 other_positions = [ ((10, 10), 0 ), ((190, 190), 0 ), ((190,10), 0), ((10, 190), 0) ]
423 assert( player.GetNumOpponents( position, other_positions, DIR_LEFT ) == 2 )
424 assert( player.GetNumOpponents( position, other_positions, DIR_UP ) == 2 )
425 assert( player.GetNumOpponents( position, other_positions, DIR_RIGHT ) == 2 )
426 assert( player.GetNumOpponents( position, other_positions, DIR_DOWN ) == 2 )
428 # 2 to our immediate right
429 position = (70, 70)
430 other_positions = [ ((80, 70), 0 ) ]
431 assert( player.GetNumOpponents( position, other_positions, DIR_LEFT ) == 0 )
432 assert( player.GetNumOpponents( position, other_positions, DIR_UP ) == 1 )
433 assert( player.GetNumOpponents( position, other_positions, DIR_RIGHT ) == 1 )
434 assert( player.GetNumOpponents( position, other_positions, DIR_DOWN ) == 1 )
436 def test_GetMostSpaceDir():
437 player = SelfishGitPlayer()
439 assert( player.GetMostSpaceDir( (150, 75), [ DIR_UP, DIR_DOWN ] ) == DIR_DOWN )
440 assert( player.GetMostSpaceDir( (150, 75), [ DIR_UP, DIR_DOWN, DIR_LEFT ] ) == DIR_LEFT )
441 assert( player.GetMostSpaceDir( (50, 75), [ DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT ] ) == DIR_RIGHT )
442 assert( player.GetMostSpaceDir( (50, 125), [ DIR_UP, DIR_LEFT ] ) == DIR_UP )
444 def test_GetBestDir():
445 player = SelfishGitPlayer()
447 # Someone to our right, lots of room to the left
448 acceptable_dirs = ( DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT )
449 position = (116, 114)
450 other_positions = [ ((140, 140), 0) ]
451 assert( player.GetBestDir( position, other_positions, acceptable_dirs ) == DIR_LEFT )
453 # Someone above, lots of room below
454 acceptable_dirs = ( DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT )
455 position = (114, 116)
456 other_positions = [ ((140, 140), 0) ]
457 assert( player.GetBestDir( position, other_positions, acceptable_dirs ) == DIR_UP )
459 # People above, and to right - more room to left than down
460 acceptable_dirs = ( DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT )
461 position = (115, 100)
462 other_positions = [ ((140, 10), 0) ]
463 assert( player.GetBestDir( position, other_positions, acceptable_dirs ) == DIR_LEFT )
465 # Can only go up or left - choose up because other player is to left
466 acceptable_dirs = ( DIR_UP, DIR_LEFT )
467 position = (180, 180)
468 other_positions = [ ((140, 190), 0) ]
469 assert( player.GetBestDir( position, other_positions, acceptable_dirs ) == DIR_UP )
471 def test_IsVertical():
472 player = SelfishGitPlayer()
474 assert( player.IsVertical( DIR_UP ) )
475 assert( player.IsVertical( DIR_DOWN ) )
476 assert( not player.IsVertical( DIR_LEFT ) )
477 assert( not player.IsVertical( DIR_RIGHT ) )
479 def test_FindCut1DirFromBestDir():
480 player = SelfishGitPlayer()
482 assert( player.FindCut1DirFromBestDir( (20,50), DIR_UP ) == DIR_RIGHT )
483 assert( player.FindCut1DirFromBestDir( (20,50), DIR_LEFT ) == DIR_DOWN )
484 assert( player.FindCut1DirFromBestDir( (120,50), DIR_UP ) == DIR_LEFT )
485 assert( player.FindCut1DirFromBestDir( (120,50), DIR_LEFT ) == DIR_DOWN )
486 assert( player.FindCut1DirFromBestDir( (120,150), DIR_LEFT ) == DIR_UP )
488 class FakeGameBoard( BasicGameBoard ):
490 def __init__( self, other_positions, pixels ):
491 self.other_positions = other_positions
492 self.pixels = pixels
494 def GetAbsolutePixel( self, pos ):
495 if pos in self.pixels:
496 retval = 1
497 else:
498 retval = 0
500 return retval
502 def GetPlayerPositions( self, pos_to_exclude ):
503 return self.other_positions
505 def GetArenaSize( self ):
506 return (200, 200)
508 def test_WithinKillRange():
509 player = SelfishGitPlayer()
511 assert( player.WithinKillRange( 20, 20 ) )
512 assert( player.WithinKillRange( 20, 21 ) )
513 assert( not player.WithinKillRange( 20, 51 ) )
515 def test_CheckKillMode():
516 player = SelfishGitPlayer()
518 # One other player, and the kill is on
519 position = ( 120, 199 )
520 other_positions = [ ((50, 199), DIR_RIGHT ) ]
521 gameboard = FakeGameBoard( other_positions, [] )
522 ckm = player.CheckKillMode( position, gameboard )
523 assert( ckm.can_kill )
524 assert( ckm.state == STATE_KILL_OUT )
525 assert( ckm.out_dir == DIR_UP )
526 assert( ckm.around_dir == DIR_LEFT )
527 assert( ckm.down_dir == DIR_DOWN )
528 assert( ckm.killing_player == 0 )
530 position = ( 120, 0 )
531 other_positions = [ ((110, 0), DIR_RIGHT ) ]
532 gameboard = FakeGameBoard( other_positions, [] )
533 ckm = player.CheckKillMode( position, gameboard )
534 assert( ckm.can_kill )
535 assert( ckm.state == STATE_KILL_OUT )
536 assert( ckm.out_dir == DIR_DOWN )
537 assert( ckm.around_dir == DIR_LEFT )
538 assert( ckm.down_dir == DIR_UP )
539 assert( ckm.killing_player == 0 )
541 position = ( 0, 12 )
542 other_positions = [ ((0, 50), DIR_UP ) ]
543 gameboard = FakeGameBoard( other_positions, [] )
544 ckm = player.CheckKillMode( position, gameboard )
545 assert( ckm.can_kill )
546 assert( ckm.state == STATE_KILL_OUT )
547 assert( ckm.out_dir == DIR_RIGHT )
548 assert( ckm.around_dir == DIR_DOWN )
549 assert( ckm.down_dir == DIR_LEFT )
550 assert( ckm.killing_player == 0 )
552 # One other player, and the kill is not on because they're going the wrong way
553 position = ( 120, 199 )
554 other_positions = [ ((50, 199), DIR_LEFT ) ]
555 gameboard = FakeGameBoard( other_positions, [] )
556 ckm = player.CheckKillMode( position, gameboard )
557 assert( not ckm.can_kill )
559 position = ( 199, 112 )
560 other_positions = [ ((100, 100), DIR_DOWN ) ]
561 gameboard = FakeGameBoard( other_positions, [] )
562 ckm = player.CheckKillMode( position, gameboard )
563 assert( not ckm.can_kill )
565 # 2 players, and the kill is on
566 position = ( 120, 199 )
567 other_positions = [ ((50, 100), DIR_UP), ((50, 199), DIR_RIGHT ) ]
568 gameboard = FakeGameBoard( other_positions, [] )
569 ckm = player.CheckKillMode( position, gameboard )
570 assert( ckm.can_kill )
571 assert( ckm.state == STATE_KILL_OUT )
572 assert( ckm.out_dir == DIR_UP )
573 assert( ckm.around_dir == DIR_LEFT )
574 assert( ckm.down_dir == DIR_DOWN )
575 assert( ckm.killing_player == 1 )
577 # One other player, no kill because there is a wall in the way
578 position = ( 120, 199 )
579 other_positions = [ ((50, 199), DIR_RIGHT ) ]
580 occupied_pixels = [ (100, 199), (100, 198), (100, 197), (100, 196), (100, 195),
581 (100, 194), (100, 193), (100, 192), (100, 191), (100, 190) ]
582 gameboard = FakeGameBoard( other_positions, occupied_pixels )
583 ckm = player.CheckKillMode( position, gameboard )
584 assert( not ckm.can_kill )
586 def test_AnyPixelsBetween():
587 player = SelfishGitPlayer()
589 gameboard = FakeGameBoard( [], [ (15, 120)] )
590 assert( player.AnyPixelsBetween( (10, 10), (20, 10), gameboard ) == False )
591 assert( player.AnyPixelsBetween( (10, 10), (10, 20), gameboard ) == False )
592 assert( player.AnyPixelsBetween( (10, 120), (20, 120), gameboard ) == True )
593 assert( player.AnyPixelsBetween( (15, 100), (15, 130), gameboard ) == True )
595 gameboard = FakeGameBoard( [], [
596 (15, 110),
597 (15, 111),
598 (15, 112),
599 (15, 113),
600 (15, 114),
601 (15, 115),
602 (15, 116),
603 (15, 117),
604 (15, 118),
605 (15, 119),
606 (15, 120),
608 assert( player.AnyPixelsBetween( (10, 111), (20, 119), gameboard ) == True )
610 def test_OppositeDir():
611 player = SelfishGitPlayer()
612 gameboard = FakeGameBoard( [], [] )
614 assert( player.OppositeDir( DIR_UP, gameboard ) == DIR_DOWN )
615 assert( player.OppositeDir( DIR_LEFT, gameboard ) == DIR_RIGHT )
616 assert( player.OppositeDir( DIR_DOWN, gameboard ) == DIR_UP )
617 assert( player.OppositeDir( DIR_RIGHT, gameboard ) == DIR_LEFT )
619 def test_KillAroundPast():
620 player = SelfishGitPlayer()
622 assert( player.KillAroundPast( ( 50, 5 ), ( 51, 0 ), DIR_LEFT ) == True )
623 assert( player.KillAroundPast( ( 53, 5 ), ( 48, 0 ), DIR_LEFT ) == False )
625 assert( player.KillAroundPast( ( 50, 195 ), ( 51, 199 ), DIR_RIGHT ) == False )
626 assert( player.KillAroundPast( ( 53, 195 ), ( 48, 199 ), DIR_RIGHT ) == True )
628 assert( player.KillAroundPast( ( 5, 195 ), ( 0, 199 ), DIR_UP ) == True )
629 assert( player.KillAroundPast( ( 5, 195 ), ( 0, 190 ), DIR_UP ) == False )
631 assert( player.KillAroundPast( ( 5, 195 ), ( 0, 199 ), DIR_DOWN ) == False )
632 assert( player.KillAroundPast( ( 5, 195 ), ( 0, 190 ), DIR_DOWN ) == True )
634 def run_tests():
635 test_GetAcceptableDirs()
636 test_GetNumOpponents()
637 test_GetMostSpaceDir()
638 test_GetBestDir()
639 test_IsVertical()
640 test_FindCut1DirFromBestDir()
641 test_AnyPixelsBetween()
642 test_WithinKillRange()
643 test_CheckKillMode()
644 test_OppositeDir()
645 test_KillAroundPast()
646 print "Selfish Git tests passed."