206 lines
7.3 KiB
Python
206 lines
7.3 KiB
Python
|
# 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
|