Functional version of the game.
This commit is contained in:
parent
7706647f9a
commit
9d3069f358
|
@ -6,18 +6,25 @@ import os
|
|||
import subprocess
|
||||
import json
|
||||
|
||||
version = '0.2.2'
|
||||
|
||||
version = '0.3.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))
|
||||
|
||||
|
||||
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()
|
||||
enemies = ['test', 'sloum'] #delete this test data
|
||||
|
||||
# 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))
|
||||
|
@ -33,8 +40,59 @@ def create_game(enemy):
|
|||
return False
|
||||
|
||||
|
||||
def update_board():
|
||||
pass
|
||||
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
|
||||
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def play_game(gid):
|
||||
|
@ -46,13 +104,18 @@ def play_game(gid):
|
|||
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))
|
||||
print_board(board)
|
||||
|
||||
if not pturn == username:
|
||||
print('\nIt is your opponents turn.\n')
|
||||
return True
|
||||
print('Enter your move as row-column.\nFor example: 4-10\nType "q" to cancel and play another time.\nType "f" to forfeit.')
|
||||
|
||||
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']:
|
||||
|
@ -72,24 +135,40 @@ def play_game(gid):
|
|||
print('Invalid entry!')
|
||||
continue
|
||||
try:
|
||||
row = int(move[0])
|
||||
col = int(move[1])
|
||||
row = int(move[0]) - 1
|
||||
col = int(move[1]) - 1
|
||||
except ValueError:
|
||||
print('Invalid entry!')
|
||||
continue
|
||||
valid_move = update_board(row, col, board)
|
||||
if not valid_move:
|
||||
if not validate_input(row, col, board):
|
||||
print('Invalid entry!')
|
||||
continue
|
||||
|
||||
update_board(row, col, board)
|
||||
board[row][col] = pieces[ppiece]
|
||||
|
||||
if check_win_state(row, col):
|
||||
print('You have won!')
|
||||
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
|
||||
|
||||
print('Your move has been placed.')
|
||||
return True
|
||||
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):
|
||||
|
@ -101,7 +180,20 @@ def print_board(gb):
|
|||
|
||||
|
||||
def show_game_record():
|
||||
pass
|
||||
q = "SELECT rowid, p1, p2, winner FROM games WHERE winner is not NULL and (p1 = ? or p2 = ?)"
|
||||
v = (username, username)
|
||||
res = db_do(q, v)
|
||||
if res == False:
|
||||
print('Database error. Contact the sysadmin or try another time')
|
||||
print_header()
|
||||
print('{:^8} {:^10} {:^10} {:^10}'.format('ID', 'Player 1', 'Player 2', 'Winner'))
|
||||
print('-------- ---------- ---------- ----------')
|
||||
for x in res:
|
||||
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('')
|
||||
return True
|
||||
|
||||
|
||||
def list_games():
|
||||
|
@ -115,9 +207,9 @@ def list_games():
|
|||
print('{:^8} {:^10} {:^10} {:^12}'.format('ID', 'Player 1', 'Player 2', 'Game Status'))
|
||||
print('-------- ---------- ---------- ------------')
|
||||
for x in res:
|
||||
print("{:^8} {:^10} {:^10} {:^12}".format(x[0], x[1], x[2] or '-', x[4]))
|
||||
print("{:^8} {:^10} {:^10} {:^12}".format(x[0], x[1], x[2], x[4]))
|
||||
if not len(res):
|
||||
print('There are no open games')
|
||||
print('You are not currently playing any games...')
|
||||
print('')
|
||||
return True
|
||||
|
||||
|
@ -125,11 +217,11 @@ def list_games():
|
|||
def display_help():
|
||||
print_header()
|
||||
print('syntax: oberon [command [option]]\n')
|
||||
print('{:25} {}'.format('help','display this message'))
|
||||
print('{:25} {}'.format('list', 'display your currently open games'))
|
||||
print('{:25} {}'.format('history', 'display your win/loss record'))
|
||||
print('{:25} {}'.format('create [user]', 'create a game against the user provided'))
|
||||
print('{:25} {}'.format('play [game_id]', 'make a move or view the board for the game id provided'))
|
||||
print('{:20} {}'.format('help','display this message'))
|
||||
print('{:20} {}'.format('list', 'display your currently open games'))
|
||||
print('{:20} {}'.format('history', 'display your win/loss record'))
|
||||
print('{:20} {}'.format('create [user]', 'create a game against the user provided'))
|
||||
print('{:20} {}'.format('play [game_id]', 'make a move or view the board for the game id provided'))
|
||||
print('')
|
||||
|
||||
|
268
oberon.py
268
oberon.py
|
@ -1,268 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
#
|
||||
# Oberon: an application for managing correspondance gameplay
|
||||
# for board style games
|
||||
# by Brian Evans
|
||||
#_
|
||||
|
||||
import sys
|
||||
import os
|
||||
import sqlite3 as sql
|
||||
import re
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
class c:
|
||||
black = ''
|
||||
red = '\033[0;31m'
|
||||
b_red = '\033[1;31m'
|
||||
yellow = '\033[1;33m'
|
||||
green = '\033[0;32m'
|
||||
b_green = '\033[1;32m'
|
||||
cyan = '\033[0;36m'
|
||||
b_cyan = '\033[1;36m'
|
||||
purple = '\033[1;35m'
|
||||
blue = '\033[0;34m'
|
||||
b_blue = '\033[1;34m'
|
||||
white = '\033[1;37m'
|
||||
end = '\033[0m'
|
||||
|
||||
#--------->
|
||||
|
||||
class User:
|
||||
def __init__(self):
|
||||
self.home_folder = os.path.expanduser('~')
|
||||
self.name = os.path.split(self.home_folder)[-1]
|
||||
self.current_games = self.get_games()
|
||||
self.history = self.get_history()
|
||||
|
||||
|
||||
def get_games(self):
|
||||
db_data = False # do db query
|
||||
# Retrieve current games
|
||||
return db_data
|
||||
|
||||
|
||||
def get_history(self):
|
||||
db_data = False # do db query
|
||||
# Retrieve history for this user
|
||||
return db_data
|
||||
|
||||
#-------->
|
||||
|
||||
class Interface:
|
||||
def __init__(self):
|
||||
self.user = User()
|
||||
self.screen = 'menu'
|
||||
self.userlist = self.get_user_list()
|
||||
self.db_path = '/home/sloum/oberon.sqlite'
|
||||
self.game = Game()
|
||||
self.mainloop()
|
||||
|
||||
|
||||
def main_menu(self):
|
||||
menu = [
|
||||
'{:^80}'.format('1) Create Game'),
|
||||
'{:^80}'.format('2) List Games'),
|
||||
'{:^80}'.format('3) View history'),
|
||||
'{:^80}'.format('4) Quit/Exit')
|
||||
]
|
||||
|
||||
print('\n{:^80}'.format('O B E R O N'))
|
||||
print('{:^80}\n'.format('Correspondence gaming system'))
|
||||
for x in menu:
|
||||
print('{:^80}'.format(x))
|
||||
selection = ''
|
||||
while selection not in ['1', '2', '3', '4', 'q', 'quit', 'exit']:
|
||||
selection = input(' oberon > ')
|
||||
if selection == '1':
|
||||
self.screen = 'create'
|
||||
elif selection == '2':
|
||||
self.screen = 'list'
|
||||
elif selection == '3':
|
||||
self.screen = 'history'
|
||||
elif selection in ['4','q','quit','exit']:
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
def get_user_list(self):
|
||||
res = subprocess.run(['awk', '-F', ':', '{if ($7 == "/usr/local/bin/colorsh" && $1 != "brian")}', '/etc/passwd'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
res_list = res.stdout.decode('utf-8').split('\n')
|
||||
if res_list[0] == '':
|
||||
return []
|
||||
return res_list
|
||||
|
||||
|
||||
def create_game(self):
|
||||
select_player = ''
|
||||
p2 = ''
|
||||
game_type = 'gomoku'
|
||||
game_status = ''
|
||||
next_menu = 'menu'
|
||||
|
||||
while True:
|
||||
select_player = input('Do you want to challenge another player (y/n) > ')
|
||||
if select_player in ['y', 'yes', 'no', 'n']:
|
||||
break
|
||||
|
||||
if select_player in ['y', 'yes']:
|
||||
if not len(self.userlist):
|
||||
self.screen = 'menu'
|
||||
print('\n')
|
||||
print('{}{:^80}{}'.format(c.white, 'There are no players available', c.end))
|
||||
print('\n')
|
||||
return False
|
||||
print('{:^80}'.format('The following players are available:\n'))
|
||||
for x in self.userlist:
|
||||
print('{:^80}'.format(x))
|
||||
print('\n')
|
||||
while not p2 in self.userlist:
|
||||
p2 = input('Enter the name of the user would you like to challenge > ')
|
||||
if not p2 in self.userlist:
|
||||
print('{}Invalid entry{}'.format(c.red, c.end))
|
||||
continue
|
||||
game_status = 'playing'
|
||||
next_menu = 'play'
|
||||
else:
|
||||
p2 = None
|
||||
game_status = 'Open'
|
||||
next_menu = 'menu'
|
||||
q = "INSERT INTO games VALUES (?, ?, ?, ?, ?, ?, ?)"
|
||||
v = (self.user.name, p2, game_type, game_status, json.dumps(self.game.game_board), 1, None)
|
||||
db_do(q, v, True)
|
||||
self.screen = next_menu
|
||||
|
||||
|
||||
def list_games(self):
|
||||
game_id = ''
|
||||
q = "SELECT rowid, p1, p2, game_type, game_status FROM games WHERE winner is NULL"
|
||||
res = db_do(q)
|
||||
print('{:^8} {:^10} {:^10} {:^12}'.format('ID', 'Player 1', 'Player 2', 'Game Status'))
|
||||
print('-------- ---------- ---------- ------------\n')
|
||||
for x in res:
|
||||
print("{:^8} {:^10} {:^10} {:^12}".format(x[0], x[1], x[2] or '-', x[4]))
|
||||
if not len(res):
|
||||
print('There are no open games')
|
||||
print('')
|
||||
print('To join an open game, enter the game ID\nTo go back type "back"\n')
|
||||
while True:
|
||||
game_id = input('Choice > ')
|
||||
if game_id == 'back':
|
||||
self.screen = 'menu'
|
||||
return
|
||||
else:
|
||||
try:
|
||||
gid = int(game_id)
|
||||
if gid in [x[0] for x in res]:
|
||||
break
|
||||
except:
|
||||
print('{}Invalid entry{}'.format(c.red, c.end))
|
||||
q2 = "UPDATE games SET p2 = ?, game_status = 'playing' WHERE rowid = ?"
|
||||
v2 = (self.user.name, gid)
|
||||
db_do(q2, v2, True)
|
||||
|
||||
|
||||
def get_game_list():
|
||||
# query for available open games and current games for player
|
||||
print('\nComing soon...\n')
|
||||
self.screen = 'menu'
|
||||
|
||||
|
||||
def show_history(self):
|
||||
# query for this palyers win records
|
||||
# display them
|
||||
# options for back or quit
|
||||
print('\nComing soon...\n')
|
||||
self.screen = 'menu'
|
||||
pass
|
||||
|
||||
|
||||
def play_game(self):
|
||||
# acts as a router to game logic functions
|
||||
# based on which game is selected
|
||||
pass
|
||||
|
||||
|
||||
def mainloop(self):
|
||||
while True:
|
||||
if self.screen == 'menu':
|
||||
self.main_menu()
|
||||
elif self.screen == 'create':
|
||||
self.create_game()
|
||||
elif self.screen == 'list':
|
||||
self.list_games()
|
||||
elif self.screen == 'history':
|
||||
self.show_history()
|
||||
elif self.screen == 'play':
|
||||
self.play_game()
|
||||
|
||||
|
||||
class Game:
|
||||
def __init__(self):
|
||||
self.game_id = None
|
||||
self.game_board = None
|
||||
self.turn = None
|
||||
self.create_game_board()
|
||||
|
||||
def create_game_board(self):
|
||||
self.game_board = [[' · ' for y in range(15)] for x in range(15)]
|
||||
|
||||
def get_game_board(self):
|
||||
pass
|
||||
|
||||
|
||||
def validate_turn(self):
|
||||
pass
|
||||
|
||||
|
||||
def make_move(self):
|
||||
pass
|
||||
|
||||
|
||||
def validate_move(self):
|
||||
pass
|
||||
|
||||
|
||||
def check_win_state(self):
|
||||
pass
|
||||
|
||||
|
||||
def check_and_build_db(db_path):
|
||||
if not os.path.isfile(db_path):
|
||||
conn = sql.connect(db_path)
|
||||
c = conn.cursor()
|
||||
|
||||
c.execute("CREATE TABLE games (p1 text NOT NULL, p2 text DEFAULT NULL, game_type text NOT NULL, game_status text DEFAULT NULL, game_board text, turn INTEGER, winner text DEFAULT NULL)")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def db_do(query, var=False, noresval=False):
|
||||
global messages
|
||||
db_path = '/home/sloum/oberon.sqlite'
|
||||
if os.path.isfile(db_path):
|
||||
conn = sql.connect(db_path)
|
||||
c = conn.cursor()
|
||||
if var:
|
||||
c.execute(query, var)
|
||||
else:
|
||||
c.execute(query)
|
||||
if noresval:
|
||||
out = c.rowcount
|
||||
else:
|
||||
out = []
|
||||
for row in c:
|
||||
out.append(row)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return out
|
||||
else:
|
||||
messages.append("{}ERROR:{} Database cannot be found or is corrupt".format(c.red, c.end))
|
||||
return False
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
check_and_build_db('/home/sloum/oberon.sqlite')
|
||||
game = Interface()
|
||||
|
Loading…
Reference in New Issue