oberon/brandubh.py

206 lines
7.3 KiB
Python
Raw Normal View History

2019-04-26 03:11:47 +00:00
# https://boardgamegeek.com/thread/344992/brandubh-or-starting-examine-tafl-games-play
# https://en.wikipedia.org/wiki/Tafl_games
class Brandubh:
def __init__(self, data):
self.game_name = '\nBrandubh\n'
self.pieces = [' a ', ' d ']
self.winner = data['winner']
self.current_player = data['current_ps_turn']
self.piece = self.pieces[data['piece_index']]
self.instructions = 'Coming soon...'
self.p1 = data['p1']
self.p2 = data['p2']
self.board = data['board']
self.piece_index = data['piece_index']
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 alpha_to_number(self, move):
table_str = {"a": 0, "b": 1, "c": 2, "d": 3, "e": 4, "f": 5, "g": 6}
table_num = {"1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6}
if move[0] in table_str and move[1] in table_num:
return [table_str[move[0]], table_num[move[1]]]
return False
def print_board(self):
letters = ['A','B','C','D','E','F','G']
print('\n\n ' + ''.join([' ' + str(i) + ' ' for i in range(1,8)]))
for x in range(7):
print(' ' + letters[x] + ''.join(self.board[x]))
print('')
def get_input(self):
print("Enter your move as piece then destination (ex 'B1 B5')")
print('Or (q)uit, (f)orfeit, (instructions).\n')
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.winnder = 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
elif len(move) != 5:
issue = 'many' if len(move) > 5 else 'few'
print("Invalid entry, too {} characters".format(issue))
continue
else:
moves = move.split(" ", 1)
if len(moves) != 2:
print("Invalid entry")
continue
moves[0] = list(moves[0].strip().lower())
moves[1] = list(moves[1].strip().lower())
start = self.alpha_to_number(moves[0])
end = self.alpha_to_number(moves[1])
piece = self.board[start[0]][start[1]]
if not start or not end:
print("Invalid coordinates")
continue
if piece.lower() != self.piece:
print("That is not a valid piece to move. Try again...")
continue
validation = self.validate_move(start, end, piece)
if not validation["success"]:
print(validation["error"])
continue
self.do_move(start, end)
self.do_captures(end)
status = self.game_over()
res = {'winner': self.winner, 'board': self.board, 'move': True}
if status:
res["winner"] = status
res["message"] = "{} won the match!".format(status)
else:
res['message'] = "Your move has been placed."
return res
def validate_move(self, beg, end, icon):
king = (icon == " D ")
if beg[0] < 0 or beg[1] < 0 or end[0] < 0 or end[1] < 0 or beg[0] > 6 or beg[1] > 6 or end[0] > 6 or end[1] > 6:
return {
"success": False,
"error": "That move would take you off the board!"
}
if beg[0] != end[0] and beg[1] != end[1]:
return {
"success": False,
"error": "You must move orthagonally..."
}
if not king and end in [[0,0],[0,6],[6,0],[6,6],[3,3]]:
return {
"success": False,
"error": "Only the king ('D') can move to that space!"
}
direction = self.get_direction(beg, end)
run = beg.copy()
while run != end:
run = [run[0] + direction[0], run[1] + direction[1]]
if self.board[run[0]][run[1]] in [' a ', ' d ', ' D ']:
return {
"success": False,
"error": "There is a piece in the way!"
}
return {"success": True, "error": ""}
def do_move(self, beg, end):
end_piece = self.board[end[0]][end[1]]
self.board[end[0]][end[1]] = self.board[beg[0]][beg[1]]
self.board[beg[0]][beg[1]] = end_piece
if beg == [3,3]:
self.board[3][3] = ' * '
def get_direction(self, b, e):
dir1 = e[0] - b[0]
dir2 = e[1] - b[1]
if dir1 > 0:
dir1 = 1
elif dir1 < 0:
dir1 = -1
if dir2 > 0:
dir2 = 1
elif dir2 < 0:
dir2 = -1
return [dir1, dir2]
def do_captures(self, pos):
enemy = self.pieces[abs(self.piece_index - 1)]
friend = self.piece
dirs = [[0,1],[0,-1],[1,0],[-1,0]]
for x in dirs:
start = pos.copy()
remove = []
steps = 0
while True:
prev = start.copy()
start[0] += x[0]
start[1] += x[1]
if start[0] < 0 or start[1] < 0 or start[0] > 6 or start[1] > 6:
break
steps += 1
if steps % 2 == 0:
if self.board[start[0]][start[1]].lower() in [friend, ' * '] and start != [3,3]:
self.board[prev[0]][prev[1]] = ' - '
continue
else:
break
else:
if self.board[start[0]][start[1]].lower() == enemy:
continue
else:
break
def game_over(self):
count = self.count_pieces()
if count[" D "] == 0:
return self.p1
elif count[" a "] == 0:
return self.p2
elif self.board[0][0] == " D " or self.board[0][6] == " D " or self.board[6][0] == " D " or self.board[6][6] == " D ":
return self.p2
return False
def count_pieces(self):
holder = {" a ": 0, " d ": 0, " D ": 0}
for x in self.board:
for y in x:
if y in [" a ", " d ", " D "]:
holder[y] += 1
return holder
def is_king(self, row, col):
piece = self.board[row][col]
if piece == ' D ':
return True
return False