Split game into second file. More games can be added this way.
This commit is contained in:
parent
2c2612c019
commit
f8434c16b2
Binary file not shown.
|
@ -0,0 +1,132 @@
|
|||
|
||||
|
||||
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 True
|
||||
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
|
286
oberon
286
oberon
|
@ -5,195 +5,23 @@ import sqlite3 as sql
|
|||
import os
|
||||
import subprocess
|
||||
import json
|
||||
from gomoku import Gomoku
|
||||
|
||||
|
||||
version = '0.4.2'
|
||||
version = '0.5.2'
|
||||
home_folder = os.path.expanduser('~')
|
||||
username = os.path.split(home_folder)[-1]
|
||||
database = '/var/lib/oberon/oberon.sqlite'
|
||||
directions = [[1,0],[1,-1],[0,-1],[-1,-1]]
|
||||
pieces = [' ◍ ', ' ○ ']
|
||||
|
||||
|
||||
def print_header():
|
||||
print('\nO B E R O N v{}\n'.format(version))
|
||||
|
||||
|
||||
# Binds to the CREATE command
|
||||
def create_game(enemy):
|
||||
if enemy == username:
|
||||
print('This system is designed for multiuser games. You cannot create a game against yourself.')
|
||||
return False
|
||||
enemies = get_user_list()
|
||||
|
||||
# create guard clause to prevent play against self and refer to single player game
|
||||
if not enemy in enemies:
|
||||
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)]
|
||||
q = "INSERT INTO games VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
v = (username, enemy, 'gomoku', 'playing', json.dumps(game_board), 1, None)
|
||||
res = db_do(q, v, True)
|
||||
if res:
|
||||
print('Game between {} and {} created!'.format(username, enemy))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def validate_input(r,c, board):
|
||||
if r < 0 or r > 14 or c < 0 or c > 14:
|
||||
return False
|
||||
|
||||
if board[r][c] != ' · ':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Binds to the AVAILABLE command
|
||||
def available_moves():
|
||||
q = "SELECT p1, p2, turn FROM games WHERE winner is null and (p1 = ? or p2 = ?)"
|
||||
v = (username, username)
|
||||
res = db_do(q, v)
|
||||
p1 = len([x for x in res if x[0] == username and x[2] % 2 != 0])
|
||||
p2 = len([x for x in res if x[1] == username and x[2] % 2 == 0])
|
||||
if p1 + p2 > 0:
|
||||
print('It is your turn in oberon!\n')
|
||||
|
||||
|
||||
def check_win_state(point, piece, board):
|
||||
ends = [
|
||||
walk_to_ends(point, 0, piece, board),
|
||||
walk_to_ends(point, 1, piece, board),
|
||||
walk_to_ends(point, 2, piece, board),
|
||||
walk_to_ends(point, 3, piece, board)
|
||||
]
|
||||
|
||||
game_over = False
|
||||
|
||||
for x in range(4):
|
||||
if count_to_five(ends[x], x, piece, board):
|
||||
game_over = True
|
||||
break
|
||||
|
||||
return game_over
|
||||
|
||||
|
||||
def count_to_five(start,direction, piece, board, count=1):
|
||||
look_toward = [directions[direction][0] * -1, 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]] != pieces[piece]:
|
||||
return False
|
||||
|
||||
return count_to_five(new_point, direction, piece, board, count + 1)
|
||||
|
||||
|
||||
|
||||
def walk_to_ends(point, direction, piece, board):
|
||||
look_toward = 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]] != pieces[piece]:
|
||||
return point
|
||||
return walk_to_ends(new_point, direction, piece, board)
|
||||
|
||||
|
||||
def set_winner(game, winner):
|
||||
q = "UPDATE games SET winner = ? WHERE rowid = ?"
|
||||
v = (winner, game)
|
||||
return db_do(q, v, True)
|
||||
|
||||
|
||||
# Binds to the PLAY command
|
||||
def play_game(gid):
|
||||
q = "SELECT rowid, p1, p2, game_board, turn FROM games WHERE rowid = ?"
|
||||
v = (gid,)
|
||||
res = db_do(q,v)
|
||||
if not res:
|
||||
print('Invalid game id')
|
||||
return False
|
||||
board = json.loads(res[0][3])
|
||||
pturn = res[0][2] if res[0][4] % 2 == 0 else res[0][1]
|
||||
ppiece = 1 if res[0][4] % 2 == 0 else 0
|
||||
|
||||
print_header()
|
||||
print('{} vs. {}: {}\'s turn {}'.format(res[0][1], res[0][2], pturn, pieces[ppiece]))
|
||||
print_board(board)
|
||||
|
||||
if not pturn == username:
|
||||
print('\nIt is your opponents turn.\n')
|
||||
return True
|
||||
|
||||
print('Enter your move as row-column (ex. 4-10)\n\nType "q" to cancel and play another time.\nType "f" to forfeit.')
|
||||
|
||||
while True:
|
||||
move = input('> ')
|
||||
if move in ['q', 'quit', 'exit']:
|
||||
return True
|
||||
elif move == 'f':
|
||||
while True:
|
||||
verify = input('Are you sure (y/n)? ')
|
||||
if verify in ['y', 'yes']:
|
||||
winner = res[0][1] if res[0][4] % 2 == 0 else res[0][2]
|
||||
if not set_winner(gid, winner):
|
||||
print('Error updating database')
|
||||
return False
|
||||
print('Game forfeited. {} wins.'.format(winner))
|
||||
return True
|
||||
elif verify in ['n', 'no']:
|
||||
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 validate_input(row, col, board):
|
||||
print('Invalid entry!')
|
||||
continue
|
||||
|
||||
board[row][col] = pieces[ppiece]
|
||||
|
||||
q2 = "UPDATE games SET game_board = ?, turn = ? WHERE rowid = ?"
|
||||
v2 = (json.dumps(board), res[0][4] + 1, gid)
|
||||
res2 = db_do(q2, v2, True)
|
||||
if not res2:
|
||||
print('Error updating database')
|
||||
return False
|
||||
|
||||
if check_win_state([row, col], ppiece, board):
|
||||
if not set_winner(gid, pturn):
|
||||
print('Error updating database')
|
||||
return False
|
||||
print('{} has won the game!'.format(pturn))
|
||||
break
|
||||
elif res[0][4] > 225:
|
||||
if not set_winner(gid, 'tie'):
|
||||
print('Error updating database')
|
||||
return False
|
||||
print('There is no winner. Tie game.')
|
||||
# update game in db
|
||||
break
|
||||
else:
|
||||
print('Your move has been placed.')
|
||||
return True
|
||||
|
||||
|
||||
def print_board(gb):
|
||||
print('\n\n 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15')
|
||||
for i, x in enumerate(gb):
|
||||
output_row = str(i + 1) + ''.join(x)
|
||||
print('{}{}'.format(' ' if i + 1 < 10 else '', output_row))
|
||||
print('')
|
||||
|
||||
##############################
|
||||
######------------------#######
|
||||
###### Top Lvl Cmds ########
|
||||
######------------------#######
|
||||
##############################
|
||||
|
||||
# Binds to the HISTORY command
|
||||
def show_game_record():
|
||||
|
@ -209,10 +37,66 @@ def show_game_record():
|
|||
print('{:^8} {:^10} {:^10} {:^10}'.format(x[0], x[1], x[2], x[3]))
|
||||
if not len(res):
|
||||
print('You have not completed any games yet...')
|
||||
print('')
|
||||
print('\nTo view a historical game, run "oberon play [game_id]"')
|
||||
return True
|
||||
|
||||
|
||||
# Binds to the PLAY command
|
||||
def play_game(gid):
|
||||
q = "SELECT rowid, p1, p2, game_board, turn, game_type, winner FROM games WHERE rowid = ?"
|
||||
v = (gid,)
|
||||
res = db_do(q,v)
|
||||
if not res:
|
||||
print('Invalid game id')
|
||||
return False
|
||||
elif res[0][1] != username and res[0][2] != username:
|
||||
print('Invalid selection. You are not playing game {}'.format(gid))
|
||||
return False
|
||||
|
||||
state = {
|
||||
'id': res[0][0],
|
||||
'p1': res[0][1],
|
||||
'p2': res[0][2],
|
||||
'board': json.loads(res[0][3]),
|
||||
'turn_number': res[0][4],
|
||||
'game_type': res[0][5],
|
||||
'winner': res[0][6],
|
||||
'current_ps_turn': res[0][2] if res[0][4] % 2 == 0 else res[0][1],
|
||||
'piece_index': 1 if res[0][4] % 2 == 0 else 0
|
||||
}
|
||||
|
||||
if state['game_type'] == 'gomoku':
|
||||
game = Gomoku(state)
|
||||
elif state['game_type'] == 'isola':
|
||||
game = Isola(state)
|
||||
|
||||
print_header()
|
||||
game.print_challenge_text()
|
||||
game.print_board()
|
||||
|
||||
if not state['current_ps_turn'] == username:
|
||||
print('\nIt is your opponents turn.\n')
|
||||
return True
|
||||
|
||||
if game.winner:
|
||||
print('You are viewing a game that has already finished')
|
||||
return True
|
||||
|
||||
play = game.get_input()
|
||||
|
||||
if not play:
|
||||
sys.exit(0)
|
||||
else:
|
||||
q2 = "UPDATE games SET game_board = ?, turn = ?, winner = ? WHERE rowid = ?"
|
||||
v2 = (json.dumps(play['board']), state['turn_number'] + 1, play['winner'], gid)
|
||||
res2 = db_do(q2, v2, True)
|
||||
if not res2:
|
||||
print('Error updating database, sorry.\nTry again later?\n...or contact the sysadmin.')
|
||||
return False
|
||||
print(play['message'])
|
||||
|
||||
|
||||
|
||||
# Binds to the LIST command
|
||||
def list_games():
|
||||
q = "SELECT rowid, p1, p2, game_type, game_status, turn FROM games WHERE winner is NULL and (p1 = ? or p2 = ?)"
|
||||
|
@ -245,6 +129,43 @@ def display_help():
|
|||
print('')
|
||||
|
||||
|
||||
# Binds to the CREATE command
|
||||
def create_game(enemy):
|
||||
# if enemy == username:
|
||||
# print('This system is designed for multiuser games. You cannot create a game against yourself.')
|
||||
# return False
|
||||
# enemies = get_user_list()
|
||||
|
||||
# if not enemy in enemies:
|
||||
# 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)]
|
||||
q = "INSERT INTO games VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
v = (username, enemy, 'gomoku', 'playing', json.dumps(game_board), 1, None)
|
||||
res = db_do(q, v, True)
|
||||
if res:
|
||||
print('Game between {} and {} created!'.format(username, enemy))
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Binds to the AVAILABLE command
|
||||
def available_moves():
|
||||
q = "SELECT p1, p2, turn FROM games WHERE winner is null and (p1 = ? or p2 = ?)"
|
||||
v = (username, username)
|
||||
res = db_do(q, v)
|
||||
p1 = len([x for x in res if x[0] == username and x[2] % 2 != 0])
|
||||
p2 = len([x for x in res if x[1] == username and x[2] % 2 == 0])
|
||||
if p1 + p2 > 0:
|
||||
print('It is your turn in oberon!\n')
|
||||
|
||||
|
||||
##############################
|
||||
######------------------#######
|
||||
###### Sys Utilities ########
|
||||
######------------------#######
|
||||
##############################
|
||||
def parse_args():
|
||||
args = sys.argv
|
||||
arg_len = len(args)
|
||||
|
@ -307,6 +228,11 @@ def get_user_list():
|
|||
return res_list
|
||||
|
||||
|
||||
##############################
|
||||
######------------------#######
|
||||
###### DB Utilities ########
|
||||
######------------------#######
|
||||
##############################
|
||||
def check_and_build_db(db_path):
|
||||
if not os.path.isfile(db_path):
|
||||
conn = sql.connect(db_path)
|
||||
|
|
Loading…
Reference in New Issue