Skip to content

Instantly share code, notes, and snippets.

@littmus
Last active May 17, 2016 10:23
Show Gist options
  • Save littmus/4b119461f47287668ced to your computer and use it in GitHub Desktop.
Save littmus/4b119461f47287668ced to your computer and use it in GitHub Desktop.
E4
C5
G4
B1
D7
C1
D5
B2
D4
C8
A1
D8
B1
E8
A2
L7
B2
L9
A15
I8
A13
L8
B14
K8
(4, 4) - ok
J2
A1
L2
B1
J4
C15
K3
B2
M5
J12
A1
L12
B1
J14
C15
L14
B2
K13
D2
A1
F2
B1
D4
C15
G5
B2
E3
D12
A1
F12
B1
D14
C1
F14
B2
E13
G7
A1
I7
B1
I9
C15
G9
B2
H8
A1
G2
A2
G4
A3
I2
A4
I4
B1
H3
F1
B6
G1
B8
H1
D6
I1
D8
C1
C7
import sys
import os
import argparse
import time
import itertools
from subprocess import Popen, PIPE
import logging
from threading import Timer
import signal
import re
WHITE = '●'
BLACK = '○'
CON = ('0011100','001110','011100')
JUMP1 = ('00110100','0011010','0110100')
JUMP2 = ('00101100','0010110','0101100')
def mybin(n, s):
b=bin(n)[2:]
if len(b) < s:
b=b.zfill(s)
elif len(b) > s:
b = b[:s]
return b
def mybin2(n, s):
b=bin(n)[2:]
if len(b) < s:
b=b.zfill(s)
elif len(b) > s:
b = b[len(b)-s:]
return b
#mybin = lambda n,s: bin(n)[2:].zfill(s)
board_iter = lambda size:itertools.product(range(size), range(size))
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(message)s')
handler = logging.FileHandler('game.log')
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
logger.addHandler(handler)
def print_board(b, size):
for i in b:
print (mybin(i, size))
print()
def draw(n, cords, marker=None):
if os.name == 'posix':
os.system('clear')
else:
os.system('cls')
print(' '+' '.join([chr(d) for d in range(ord('A'), ord('A') + n)]))
for i, j in board_iter(n):
if j == 0:
sys.stdout.write("%2d"%(n-i))
if (j, i, WHITE) in cords:
sys.stdout.write(WHITE)
elif (j, i, BLACK) in cords:
sys.stdout.write(BLACK)
else:
if i==0:
if j==0:
sys.stdout.write('┌')
elif j==n-1:
sys.stdout.write('┐')
else:
sys.stdout.write('┬')
elif i==n-1:
if j==0:
sys.stdout.write('└')
elif j==n-1:
sys.stdout.write('┘')
else:
sys.stdout.write('┴')
else:
if j==0:
sys.stdout.write('├')
elif j==n-1:
sys.stdout.write('┤')
else:
sys.stdout.write('┼')
if j == n - 1:
sys.stdout.write("%2d\n"%(n-i))
print(' '+' '.join([chr(d) for d in range(ord('A'), ord('A') + n)]))
#print('x '+' '.join([str(d - ord('A')) for d in range(ord('A'), ord('A') + n)]))
def rotate(board, size):
rotate = [0]*size
for i, j in board_iter(size):
if board[i] & 2**j:
rotate[size-j-1] ^= 2**(size-i-1)
"""
to_rotate = []
for j, i in board_iter(size):
if board[i] & 2**j:
to_rotate.append((i, j))
for j, i in to_rotate:
rotate[size-j-1] ^= 2**(size-i-1)
"""
return rotate
def rotate2(board, size):
rotate = [[c for c in mybin(n, size)] for n in board]
to_rotate = [['0' for _ in range(size)] for _ in range(size)]
for j, i in board_iter(size):
if rotate[j][i] == '1':
to_rotate[i][j] = '1'
for i in range(size):
to_rotate[i] = int(''.join(to_rotate[i]), 2)
return to_rotate
def check_win(win, board):
size = len(board)
def check(board):
is_win = False
for j in range(size - win + 1):
is_win = board[j]
for k in range(1, win):
is_win = is_win & board[j+k]
if is_win:
if j > 0:
if is_win & board[j-1]:
return False
if j+k+1 < size:
if is_win & board[j+k+1]:
return False
break
#is_win = False
return is_win
win_vertical = check(board)
if win_vertical:
return win_vertical
board_rotate = rotate(board, size)
win_horizontal = check(board_rotate)
if win_horizontal:
return win_horizontal
sl_board = [0]*size
sr_board = [0]*size
for j in range(size):
sl_board[j] = board[j] << j
sr_board[j] = board[j] << (size - j - 1)
win_diagonal_left = check(sl_board)
if win_diagonal_left:
return win_diagonal_left
win_diagonal_right = check(sr_board)
if win_diagonal_right:
return win_diagonal_right
def open_three(x, y, board, op_board):
size = len(board)
if x == 0 or x == size-1 or y == 0 or y == size-1:
return False
r = 0
#r = [0] * (4 * 3)
#r_near = [None] * (4 * 3)
whole_board = [0]*size
for j in range(size):
whole_board[j] = board[j] ^ op_board[j]
board_rotate = rotate(board, size)
whole_board_rotate = rotate(whole_board, size)
def check(patterns, row, wrow, pos, isnear=True):
if isinstance(row, int):
row = mybin(row, size)
if isinstance(wrow, int):
wrow = mybin(wrow, size)
pattern, op_pattern1, op_pattern2 = patterns
limit = len(pattern) - 1
l = max(0, pos-limit)
r = min(size, pos+limit+2)
index = row.find(pattern, l, r)
if index != -1:
#print(patterns, pos)
#print(row[l:r], wrow[l:r])
w1 = wrow.find(op_pattern1, l, r)
w2 = wrow.find(op_pattern2, l, r)
#print (w1, w2)
windex = w1 != -1 or w2 != -1
if windex:
return True
#print(index, windex)
"""
if index == windex:
near = None
if isnear:
diff = pos - index
if pattern == CON:
if diff == 1:
near = (+1, +2)
elif diff == 2:
near = (-1, +1)
elif diff == 3:
near = (-2, -1)
elif pattern == JUMP1:
if diff == 1:
near = (+1, +3)
elif diff == 2:
near = (-1, +2)
elif diff == 4:
near = (-3, -2)
elif pattern == JUMP2:
if diff == 1:
near = (+2, +3)
elif diff == 3:
near = (-2, +1)
elif diff == 4:
near = (-3, -1)
return True
"""
return False
#print(mybin(board[y], size), mybin(whole_board[y], size))
#print(mybin(board_rotate[x], size), mybin(whole_board_rotate[x], size))
for patterns in (CON, JUMP1, JUMP2):
rr = check(patterns, board[y], whole_board[y], x)
if rr:
#print(patterns, 'found horizontal')
break
r += rr
for patterns in (CON, JUMP1, JUMP2):
rr = check(patterns, board_rotate[x], whole_board_rotate[x], y)
if rr:
#print(patterns, 'found vertical')
break
r += rr
if r >= 2:
return True
# diagonal
def flat_diagonal(x_, y_, b, wb):
diagonal_left = []
whole_diagonal_left = []
diagonal_right = []
whole_diagonal_right = []
lb = x_ + y_ # y=-x+b /
rb = y_ - x_ # y=x+b \
crx_l = range(max(0, lb-(size-1)), min(size-1, lb)+1)
cry_l = range(min(size-1, lb), max(0, lb-(size-1))-1, -1)
for _x, _y in zip(crx_l, cry_l):
s = mybin(b[_y], size)
ws = mybin(wb[_y], size)
diagonal_left.append(s[_x])
whole_diagonal_left.append(ws[_x])
diagonal_left = ''.join(diagonal_left)
whole_diagonal_left = ''.join(whole_diagonal_left)
crx_r = range(max(0, 0-rb), min(size-1, size-1-rb)+1)
cry_r = range(max(0, 0+rb), min(size-1, size-1+rb)+1)
for _x, _y in zip(crx_r, cry_r):
s = mybin(b[_y], size)
ws = mybin(wb[_y], size)
diagonal_right.append(s[_x])
whole_diagonal_right.append(ws[_x])
diagonal_right = ''.join(diagonal_right)
whole_diagonal_right = ''.join(whole_diagonal_right)
adjusted_lx = x_
adjusted_rx = x_
if x_ + y_ > size - 1:
adjusted_lx = x_ - (lb - (size - 1))
if x_ > y_:
adjusted_rx = x_ + rb
return diagonal_left, whole_diagonal_left, diagonal_right, whole_diagonal_right, adjusted_lx, adjusted_rx
dl, wdl, dr, wdr, lx, rx = flat_diagonal(x, y, board, whole_board)
#print(dl, wdl)
#print(dr, wdr)
for patterns in (CON, JUMP1, JUMP2):
rr = check(patterns, dl, wdl, lx)
if rr:
#print(patterns, 'found left diag')
break
r += rr
if r >= 2:
return True
for patterns in (CON, JUMP1, JUMP2):
rr = check(patterns, dr, wdr, rx)
if rr:
#print(patterns, 'found right diag')
break
r += rr
if r >= 2:
return True
"""
if sum(r) == 1: # 다른 pos에서 완성이 될 수 있는 경우
for i in range(3 * 4):
if r_near[i]:
for nx, ny in r_near[i]:
rr = False
if i != 0:
rr, near = check(CON, board[ny], whole_board[ny], nx, False)
if rr: return True
if i != 1:
rr, near = check(CON, board_rotate[nx], whole_board_rotate[nx], ny, False)
if rr: return True
if i != 2:
rr, near = check(JUMP1, board[ny], whole_board[ny], nx, False)
if rr: return True
if i != 3:
rr, near = check(JUMP1, board_rotate[nx], whole_board_rotate[nx], ny, False)
if rr: return True
if i != 4:
rr, near = check(JUMP2, board[ny], whole_board[ny], nx, False)
if rr: return True
if i != 5:
rr, near = check(JUMP2, board_rotate[nx], whole_board_rotate[nx], ny, False)
if rr: return True
dl, wdl, dr, wdr, lx, rx = flat_diagonal(nx, ny, board, whole_board)
if i != 6:
rr, near = check(CON, dl, wdl, lx, False)
if rr: return True
if i != 7:
rr, near = check(JUMP1, dl, wdl, lx, False)
if rr: return True
if i != 8:
rr, near = check(JUMP2, dl, wdl, lx, False)
if rr: return True
if i != 9:
rr, near = check(CON, dr, wdr, rx, False)
if rr: return True
if i != 10:
rr, near = check(JUMP1, dr, wdr, rx, False)
if rr: return True
if i != 11:
rr, near = check(JUMP2, dr, wdr, rx, False)
if rr: return True
"""
return False
def exit_game(loser):
loser.kill()
print(str(loser), 'Lose')
os.kill(os.getpid(), signal.SIGTERM)
def readline_timeout(player, timeout):
t = Timer(timeout, exit_game, [player])
t.start()
r = player.stdout.readline()
t.cancel()
if t.isAlive():
return r
else:
return None
def main(args):
p1 = args.p1
p2 = args.p2
size = args.n
win_condition = args.w
if size < win_condition:
print('Invalid Game!')
return
cords = set()
p1_board = [0]*size
p2_board = [0]*size
draw(size, cords)
if p1 != 'human':
p1 = Popen(p1, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True, bufsize=1, shell=True)
#p1 = Popen(' '.join([p1, "-n", str(size), "-w", str(win_condition)]), stdin=PIPE, stdout=PIPE, universal_newlines=True, bufsize=1, shell=True)
if p2 != 'human':
p2 = Popen(p2, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True, bufsize=1, shell=True)
else:
p2 = 'human2'
timer = {p1:0., p2:0.}
_x, _y = -1, -1
win = None
first = True
for player, marker, board, op_board in itertools.cycle([(p1, BLACK, p1_board, p2_board), (p2, WHITE, p2_board, p1_board)]):
failed = False
while True:
start = time.time()
if player == 'human' or player == 'human2':
if first:
first = False
r = input("Input position : ")
else:
if first:
print ("START", file=player.stdin, flush=True)
first = False
else:
print('%c%d'%(_x+ord('A'), size - _y), file=player.stdin, flush=True) #send
r = player.stdout.readline()
#r = readline_timeout(player, 1)
elapsed = time.time() - start
if player not in ['human', 'human2'] and elapsed > 1 + 0.05: # 랙 고려
failed = True
print('Time out')
break
timer[player] += elapsed
try:
x = ord(r[0]) - ord('A')
y = size - int(r[1:])
if x not in range(size) or y not in range(size):
raise Exception
if (x,y,WHITE) in cords or (x,y,BLACK) in cords:
print('You can not input there ', r)
failed = True
else:
cords.add((x,y,marker))
draw(size, cords)
board[y] ^= 2**(size-x-1)
_x, _y = x, y
break
except:
print('Invalid input : ', r)
failed = True
break
if failed:
win = BLACK if marker == WHITE else WHITE
break
if check_win(win_condition, board):
win = marker
break
elif len(cords) == size**2:
print ('DRAW')
break
elif len(cords) > 8:
failed = open_three(_x, _y, board, op_board)
if failed:
print('3*3 DETECTED!')
win = BLACK if marker == WHITE else WHITE
break
print(win, 'WIN')
logger.info('TIME - P1 {} / P2 {}'.format(timer[p1], timer[p2]))
#print('TIME - P1 {} / P2 {}'.format(timer[p1], timer[p2]))
logger.info('winner : {}'.format('BLACK' if win == BLACK else 'WHITE'))
return
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-n', type=int, default=15)
parser.add_argument('-w', type=int, default=5)
parser.add_argument('p1', type=str, default=None)
parser.add_argument('p2', type=str, default=None)
args = parser.parse_args()
main(args)
import random
import sys
import time
import argparse
import copy
import itertools
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.FileHandler('player.log')
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
mybin = lambda n,s: bin(n)[2:].zfill(s)
conv = lambda x,y,size: "%c%d" % (chr(x + ord('A')), size-y)
board_iter = lambda size:itertools.product(range(size), range(size))
bit = lambda n, k:(n & 2**k) != 0
def print_board(b, size):
for i in range(size):
logger.info ('%2d %s'%(size-i, mybin(b[i], size)))
logger.info(' '+''.join([str(d+1) for d in range(size)]))
def check_open_three(board, size, x, y):
if x == 0 or x == size - 1 or y == 0 or y == size - 1:
return False
test_board = copy.deepcopy(board)
# case 1
test_board[y] ^= 2**(size-x-1)
print_board(test_board, size)
"""
가로에 2개
010 010
010 1x1
1x1 010
"""
row = test_board[y]
horizontal = 0
vertical = 0
for i in range(max(0, x-2), min(x+1, size-2)):
x1 = bit(row, size-i-1)
x2 = bit(row, size-i-2)
x3 = bit(row, size-i-3)
logger.info('{} hor : {} {} {}'.format(i, x1, x2, x3))
b = x1 & x2 & x3
if b:
horizontal = i + 1
y = size - y - 1
for j in range(max(0, y-2), min(y+1, size-2)):
y1=bit(test_board[size-j-1], size-x-1)
y2=bit(test_board[size-j-2], size-x-1)
y3=bit(test_board[size-j-3], size-x-1)
logger.info('{} ver : {} {} {}'.format(size-j, y1, y2, y3))
b = y1 & y2 & y3
if b:
vertical = j + 1
logger.info('hor : %d / ver : %d' % (horizontal, vertical))
if horizontal and vertical:
# 가로 세로 삼삼
return True
if x not in [0, size-1] and y not in [0, size - 1]:
diagonal_left = 0
diagonal_right = 0
left_up = bit(test_board[y-1], )
left_down = bit(test_board[y+1], )
right_up = bit(test_board[y-1], )
right_down = bit(test_board[y+1], )
def check_win(size, win, board):
def check(board):
is_win = False
for j in range(size - win + 1):
is_win = board[j]
for k in range(1, win):
is_win = is_win & board[j+k]
if is_win:
break
is_win = False
return is_win
win_vertical = check(board)
if win_vertical:
return win_vertical
rotate = [0]*size
for i, j in board_iter(size):
#if board[i] & 2**j:
if bit(board[i], j):
rotate[size-j-1] ^= 2**(size-i-1)
win_horizontal = check(rotate)
if win_horizontal:
return win_horizontal
sl_board = [0]*size
sr_board = [0]*size
for j in range(size):
sl_board[j] = board[j] << j
sr_board[j] = board[j] << (size - j - 1)
#print_board(sl_board, size)
#print_board(sr_board, size)
win_diagonal_left = check(sl_board)
if win_diagonal_left:
return win_diagonal_left
win_diagonal_right = check(sr_board)
if win_diagonal_right:
return win_diagonal_right
def score(my_board, op_board):
if check_win(my_board):
return 10
elif check_win(op_board):
return -10
else:
return 0
def main(args):
logger.info("New Game START================\n")
size = args.n
win = args.w
board = set()
my_board = [0]*size
op_board = [0]*size
def play(m_board, o_board):
lose_candidate = []
for i, j in board_iter(size):
if (i, j) not in board:
copy_my_board = copy.deepcopy(m_board)
copy_my_board[j] ^= 2**(size-i-1)
#print_board(copy_my_board, size)
#print_board(copy_op_board, size)
if check_win(size, win, copy_my_board):
logger.info('i win if ' + conv(i, j, size) + ' %d %d' % (j, i))
#win_candidate.append((i,j))
return (i,j)
copy_op_board = copy.deepcopy(o_board)
copy_op_board[j] ^= 2**(size-i-1)
if check_win(size, win, copy_op_board):
logger.info('op win if ' + conv(i, j, size) + ' %d %d' % (j, i))
lose_candidate.append((i,j))
if lose_candidate:
return lose_candidate[0]
while True:
x = random.randint(0, size-1)
y = random.randint(0, size-1)
if (x, y) not in board:
break
return (x, y)
while True:
r = input()
logger.info('op : ' + r)
if r != 'START':
try:
x = ord(r[0]) - ord('A')
y = size - int(r[1:])
except:
print(r)
break
#check_open_three(op_board, size, x, y)
op_board[y] ^= 2**(size-x-1)
board.add((x,y))
x, y = play(my_board, op_board)
my_board[y] ^= 2**(size-x-1)
board.add((x,y))
output = conv(x, y, size)
print(output)
logger.info('I : ' + output)
#check_open_three(my_board, size, x, y)
logger.info('\n')
return
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-n', type=int, default=15)
parser.add_argument('-w', type=int, default=5)
#parser.add_argument('-d', type=int, default=0)
args = parser.parse_args()
main(args)
from threading import Timer
def input_timeout(timeout):
t = Timer(timeout, print, ['Timeout!'])
t.start()
r = input()
t.cancel()
if t.isAlive():
return r
else:
return None
r = input_timeout(1)
print(r)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment