diff --git a/__pycache__/gomoku.cpython-36.pyc b/__pycache__/gomoku.cpython-36.pyc index a5aaf32..7de0225 100644 Binary files a/__pycache__/gomoku.cpython-36.pyc and b/__pycache__/gomoku.cpython-36.pyc differ diff --git a/__pycache__/isola.cpython-36.pyc b/__pycache__/isola.cpython-36.pyc new file mode 100644 index 0000000..592e292 Binary files /dev/null and b/__pycache__/isola.cpython-36.pyc differ diff --git a/gomoku.py b/gomoku.py index 93ab323..8e17bed 100644 --- a/gomoku.py +++ b/gomoku.py @@ -94,7 +94,7 @@ class Gomoku: 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 True + return res elif verify in ['n', 'no']: print('Forfeit canceled') return False diff --git a/isola.py b/isola.py new file mode 100644 index 0000000..439ddcb --- /dev/null +++ b/isola.py @@ -0,0 +1,140 @@ +class Isola: + def __init__(self, data): + self.pieces = [' X ', ' O '] + self.game_id = data['id'] + self.p1 = data['p1'] + self.p2 = data['p2'] + self.board = data['board']['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, move to any adjacent tile (shown as: - ),\nthen destroy any unocupied tile on the baord. The loser is the first to have nowhere to move on their turn.' + self.directions = [[1,0],[1,-1],[0,-1],[-1,-1]] + self.game_name = '\nIsola\n' + self.p1coords = data['board']['p1'] + self.p2coords = data['board']['p2'] + + + 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 ' + ''.join([' ' + str(i) + ' ' for i in range(7)])) + for x in range(7): + print(' ' + str(x) + ''.join(self.board[x])) + print('') + + + def get_input(self): + move_type = ['MOVEMENT', 'DESTRUCTION'] + move_phase = 0 + print('Enter your move (or destruction) as row-column (ex. 4-5)') + print('Or (q)uit, (f)orfeit, (i)nstructions.\n') + while True: + move = input('{} > '.format(move_type[move_phase])) + 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]) + col = int(move[1]) + except ValueError: + print('Invalid entry!') + continue + + if not move_phase: + if self.validate_move([row, col]): + self.do_move([row, col]) + move_phase = 1 + continue + else: + print('That is not a legal move. Try again.') + continue + else: + if self.validate_destruction([row, col]): + self.do_destruction([row, col]) + else: + print('That is not a legal square to destroy. Try again.') + continue + + res_board_data = {'board': self.board, 'p1': self.p1coords, 'p2': self.p2coords} + + res = {'winner': self.winner, 'board': res_board_data, 'move': True} + + if self.game_over(): + res['winner'] = self.current_player + res['message'] = '{} won the match!'.format(self.current_player) + else: + res['message'] = 'Your move has been placed.' + return res + + + def validate_move(self, mov): + old_position = self.p1coords if self.piece == self.pieces[0] else self.p2coords + + if mov[0] < 0 or mov[0] > 6 or mov[1] < 0 or mov[1] > 6 or self.board[mov[0]][mov[1]] != ' - ': + return False + + if abs(mov[0] - old_position[0]) > 1 or abs(mov[1] - old_position[1]) > 1: + return False + + return True + + + def do_move(self, mov): + old_position = self.p1coords if self.piece == self.pieces[0] else self.p2coords + + if self.turn_number < 3: + self.board[old_position[0]][old_position[1]] = ' ' + else: + self.board[old_position[0]][old_position[1]] = ' - ' + + self.board[mov[0]][mov[1]] = self.piece + + if self.turn_number % 2 != 0: + self.p1coords = mov + else: + self.p2coords = mov + + + def validate_destruction(self, des): + if des[0] < 0 or des[0] > 6 or des[1] < 0 or des[1] > 6 or self.board[des[0]][des[1]] != ' - ': + return False + return True + + + def do_destruction(self, des): + self.board[des[0]][des[1]] = ' ' + + + def game_over(self): + board = self.board + enemy_coords = self.p1coords if self.piece == self.pieces[1] else self.p2coords + row = enemy_coords[0] + col = enemy_coords[1] + if (row + 1 <= 6 and board[row + 1][col] == ' - ') or (col + 1 <= 6 and board[row][col + 1] == ' - ') or (row - 1 >= 0 and board[row - 1][col] == ' - ') or (col - 1 >= 0 and board[row][col - 1] == ' - ') or (row - 1 >= 0 and col - 1 >= 0 and board[row - 1][col - 1] == ' - ') or (row + 1 <= 6 and col + 1 <= 6 and board[row + 1][col + 1] == ' - ') or (row + 1 <= 6 and col - 1 >= 0 and board[row + 1][col - 1] == ' - ') or (row - 1 >= 0 and col + 1 <= 6 and board[row - 1][col + 1] == ' - '): + return False + return True diff --git a/oberon b/oberon index afc8e6d..dbf69d0 100755 --- a/oberon +++ b/oberon @@ -6,8 +6,9 @@ import os import subprocess import json from gomoku import Gomoku +from isola import Isola -version = '0.5.2' +version = '0.7.1' home_folder = os.path.expanduser('~') username = os.path.split(home_folder)[-1] database = '/var/lib/oberon/oberon.sqlite' @@ -85,6 +86,7 @@ def play_game(gid): play = game.get_input() if not play: + # A false value for play would occur from a forfeit sys.exit(0) else: q2 = "UPDATE games SET game_board = ?, turn = ?, winner = ? WHERE rowid = ?" @@ -106,11 +108,11 @@ def list_games(): print('Database error. Contact the sysadmin or try another time.') return False print_header() - print('{:^8} {:^10} {:^10} {:^22}'.format('ID', 'Player 1', 'Player 2', 'Game Status')) - print('-------- ---------- ---------- ----------------------') + print('{:^8} {:^10} {:^10} {:^22} {:^12}'.format('ID', 'Player 1', 'Player 2', 'Game Status', 'Game Type')) + print('-------- ---------- ---------- ---------------------- ------------') for x in res: pturn = x[2] if x[5] % 2 == 0 else x[1] - print("{:^8} {:^10} {:^10} {:^22}".format(x[0], x[1], x[2], pturn +"'s turn")) + print("{:^8} {:^10} {:^10} {:^22} {:^12}".format(x[0], x[1], x[2], pturn +"'s turn", x[3])) if not len(res): print('You are not currently playing any games...') print('') @@ -140,9 +142,29 @@ def create_game(enemy): # print('There is no avialable player with the name {}.\nGame not created.'.format(enemy)) # return False - game_board = [[' · ' for y in range(15)] for x in range(15)] + print_header() + print('Which game would you like to play?\n\n(1) Gomoku/Five In a Row\n(2) Isola\n\nor (Q)uit') + while True: + game = input('> ') + if game.lower() == 'q': + sys.exit(0) + elif not game in ['1', '2']: + continue + + break + + if game == '1': + game_board = [[' · ' for y in range(15)] for x in range(15)] + game_choice = 'gomoku' + else: + board = [[ ' - ' for y in range(7)] for x in range(7)] + board[0][3] = ' X ' + board[6][3] = ' O ' + game_board = {'board': board, 'p1': [0,3], 'p2': [6,3]} + game_choice = 'isola' + q = "INSERT INTO games VALUES (?, ?, ?, ?, ?, ?, ?)" - v = (username, enemy, 'gomoku', 'playing', json.dumps(game_board), 1, None) + v = (username, enemy, game_choice, 'playing', json.dumps(game_board), 1, None) res = db_do(q, v, True) if res: print('Game between {} and {} created!'.format(username, enemy))