oberon/gomoku.py

133 lines
4.9 KiB
Python

class Gomoku:
def __init__(self, data):
self.pieces = ['', '']
self.game_id = data['id']
self.p1 = data['p1']
self.p2 = data['p2']
self.board = data['board']
self.turn_number = data['turn_number']
self.winner = data['winner']
self.current_player = data['current_ps_turn']
self.piece = self.pieces[data['piece_index']]
self.instructions = 'Instructions:\nOn your turn play a piece on any unoccupied space.\nThe goal is to get five of your pieces in a row,\ndiagonally or orthagonally.'
self.directions = [[1,0],[1,-1],[0,-1],[-1,-1]]
self.game_name = '\nGomoku\n'
def print_challenge_text(self):
print(self.game_name)
if self.winner:
print('{} vs. {}: {} won!'.format(self.p1, self.p2, self.winner))
else:
print('{} vs. {}: {}\'s turn {}'.format(self.p1, self.p2, self.current_player, self.piece))
def print_board(self):
print('\n\n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15')
for i, x in enumerate(self.board):
output_row = str(i + 1) + ''.join(x)
print('{}{}'.format(' ' if i + 1 < 10 else '', output_row))
print('')
def validate_input(self, r,c, board):
if r < 0 or r > 14 or c < 0 or c > 14:
return False
if self.board[r][c] != ' · ':
return False
return True
def check_win_state(self, point, piece, board):
ends = [
self.walk_to_ends(point, 0, piece, board),
self.walk_to_ends(point, 1, piece, board),
self.walk_to_ends(point, 2, piece, board),
self.walk_to_ends(point, 3, piece, board)
]
game_over = False
for x in range(4):
if self.count_to_five(ends[x], x, piece, board):
game_over = True
break
return game_over
def count_to_five(self, start, direction, piece, board, count=1):
look_toward = [self.directions[direction][0] * -1, self.directions[direction][1] * -1]
new_point = [start[0] + look_toward[0], start[1] + look_toward[1]]
if count == 5:
return True
if new_point[0] < 0 or new_point[0] > 14 or new_point[1] < 0 or new_point[1] > 14 or board[new_point[0]][new_point[1]] != self.piece:
return False
return self.count_to_five(new_point, direction, piece, board, count + 1)
def walk_to_ends(self, point, direction, piece, board):
look_toward = self.directions[direction]
new_point = [point[0] + look_toward[0], point[1] + look_toward[1]]
if new_point[0] < 0 or new_point[0] > 14 or new_point[1] < 0 or new_point[1] > 14 or board[new_point[0]][new_point[1]] != self.piece:
return point
return self.walk_to_ends(new_point, direction, piece, board)
def get_input(self):
print('Enter your move as row-column (ex. 4-10)\n\nOr (q)uit, (f)orfeit, (i)nstructions.')
while True:
move = input('> ')
if move in ['q', 'quit', 'exit']:
return False
elif move in ['f', 'forfeit']:
while True:
verify = input('Are you sure (y/n)? ')
if verify in ['y', 'yes']:
self.winner = self.p1 if self.p2 == self.current_player else self.p2
res = {'winner': self.winner, 'board': self.board, 'move': False, 'message': '{} forfeit, {} wins!'.format(self.current_player, self.winner)}
return res
elif verify in ['n', 'no']:
print('Forfeit canceled')
return False
elif move in ['i', 'instructions']:
print(self.instructions)
continue
else:
move = move.split('-')
if not len(move) == 2:
print('Invalid entry!')
continue
try:
row = int(move[0]) - 1
col = int(move[1]) - 1
except ValueError:
print('Invalid entry!')
continue
if not self.validate_input(row, col, self.board):
print('Invalid entry!')
continue
self.board[row][col] = self.piece
res = {'winner': self.winner, 'board': self.board, 'move': True}
if self.check_win_state([row, col], self.piece, self.board):
res['winner'] = self.current_player
res['message'] = '{} won the match!'.format(self.current_player)
elif self.turn_number > 225:
res['winner'] = 'tie'
res['message'] = 'There is no winner. Tie game.'
else:
res['message'] = 'Your move has been placed.'
return res