Split game into second file. More games can be added this way.

This commit is contained in:
sloumdrone 2019-01-17 21:27:39 -08:00
parent 2c2612c019
commit f8434c16b2
3 changed files with 238 additions and 180 deletions

Binary file not shown.

132
gomoku.py Normal file
View File

@ -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
View File

@ -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)