Page Title https://cdnjs.cloudflare.com/ajax/libs/brython/3.7.1/brython.min.js
# Brython Chess Board UI (by HonFu) from browser import document, html, prompt, alert class ChessPiece: def __init__(self, color, board, i, j, king=None): self._king = king or self self._color = color self._board = board self._i = i self._j = j if isinstance(self, King): self._subjects = [] else: self._king._subjects.append(self) def move(self, i, j, serious=True): if (i, j) in self.moves(): b = self._king.tacticalchart() b[self._i][self._j]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) return 1 return 0 def _move(self, i, j): if self._board[i][j]: self._board[i][j]._king._subjects.remove(self._board[i][j]) self._board[i][j] = self self._board[self._i][self._j] = 0 self._i = i self._j = j def moves(self): m = [] for d in self._directions(): for i, j in d: if not self._board[i][j]: m.append((i, j)) elif self._board[i][j]._king is not self._king: m.append((i, j)) break else: break return m def _orthogonally(self): return [ zip(range(self._i+1, 8), [self._j]*7), zip(range(self._i-1, -1, -1), [self._j]*7), zip([self._i]*7, range(self._j+1, 8)), zip([self._i]*7, range(self._j-1, -1, -1)) ] def _diagonally(self): return [ zip(range(self._i+1, 8), range(self._j+1, 8)), zip(range(self._i+1, 8), range(self._j-1, -1, -1)), zip(range(self._i-1, -1, -1), range(self._j+1, 8)), zip(range(self._i-1, -1, -1), range(self._j-1, -1, -1)) ] class King(ChessPiece): def __init__(self, color, board, i, j, king=None): super().__init__(color, board, i, j, king) self._unmoved = True def __repr__(self): return ‘K’ if self._color == ‘white’ else ‘k’ def move(self, i, j, serious=True): if self._j in (j+2, j-2) and self._unmoved: return self._rochade(i, j, serious) m = super().move(i, j, serious) if m and serious: self._unmoved = False return m def _rochade(self, i, j, serious=True): step = 1 if j>self._j else -1 rook = 7 if step==1 else 0 if ( self._board[i][rook]._unmoved and not self._board[i][self._j+step] and not self._board[i][self._j+2*step] and not self._incheck(self._board) ): b = self.tacticalchart() b[self._i][self._j]._move(i, j-step) if b[i][j-step]._king._incheck(b): return 0 b[self._i][self._j+step]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) self._board[i][rook]._move(i, j-step) self._unmoved = False return 1 def moves(self): m = [] for i in range(self._i-1, self._i+2): for j in range(self._j-1, self._j+2): if i==self._i and j==self._j: continue if 0<=i<8 and 0<=j<8 and ( not self._board[i][j] or self._board[i][j]._king is not self._king ): m.append((i, j)) return m def _incheck(self, chart): for enemy in self._enemy._subjects + [self._enemy._king]: if any( move==(self._i, self._j) for move in enemy.moves() ): return True return False def tacticalchart(self): b = [[0 for j in range(8)] for i in range(8)] thisking = King(self._color, b, self._i, self._j) b[self._i][self._j] = thisking otherking = King(self._enemy._color, b, self._enemy._i, self._enemy._j) b[self._enemy._i][self._enemy._j] = otherking thisking._enemy = otherking otherking._enemy = thisking for king, nking in ( (self, thisking), (self._enemy, otherking) ): for subject in king._subjects: i, j = subject._i, subject._j b[i][j] = type(subject)( subject._color, b, i, j, nking) if hasattr(subject, '_unmoved'): b[i][j]._unmoved = subject._unmoved if hasattr(subject, '_hasjustrun'): b[i][j]._hasjustrun = subject._hasjustrun return b class Knight(ChessPiece): def __repr__(self): return 'N' if self._color == 'white' else 'n' def moves(self): m = [] for i, j in ( (self._i-2, self._j-1), (self._i-1, self._j-2), (self._i-2, self._j+1), (self._i-1, self._j+2), (self._i+2, self._j-1), (self._i+1, self._j-2), (self._i+2, self._j+1), (self._i+1, self._j+2) ): if 0<=i<8 and 0<=j<8 and ( not self._board[i][j] or self._board[i][j]._king is not self._king ): m.append((i, j)) return m class Rook(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = self._orthogonally self._unmoved = True def __repr__(self): return 'R' if self._color == 'white' else 'r' def move(self, i, j, serious=True): m = super().move(i, j, serious) if m and serious: self._unmoved = False return m class Bishop(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = self._diagonally def __repr__(self): return 'B' if self._color == 'white' else 'b' class Queen(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = lambda: self._orthogonally()+self._diagonally() def __repr__(self): return 'Q' if self._color == 'white' else 'q' class Pawn(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._step = -1 if color=='white' else 1 self._goal = 0 if color=='white' else 7 self._unmoved = True self._hasjustrun = False def __repr__(self): return 'P' if self._color == 'white' else 'p' def move(self, i, j, serious=True): if (i, j) in self.moves(): b = self._king.tacticalchart() b[self._i][self._j]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) if i==self._goal: return 2 return 1 return 0 def _move(self, i, j): if not self._board[i][j] and j!=self._j: self._board[i-self._step][j]._king._subjects\ .remove(self._board[i-self._step][j]) self._board[i-self._step][j] = 0 self._hasjustrun = ( True if self._i in (i-2, i+2) else False ) self._unmoved = False if self._board[i][j]: self._board[i][j]._king._subjects.remove(self._board[i][j]) self._board[i][j] = self self._board[self._i][self._j] = 0 self._i = i self._j = j def moves(self): i, j = self._i+self._step, self._j if 0<=i<=7 and not self._board[i][j]: yield i, j if ( self._unmoved and not self._board[i+self._step][j] ): yield i+self._step, j for j in j-1, j+1: if ( 0<=j<8 and self._board[i][j] and self._board[i][j]._king is not self._king ): yield i, j if ( 0<=j<8 and isinstance(self._board[i-self._step][j], Pawn) and self._board[i-self._step][j]._hasjustrun ): yield i, j class ChessBoard: def __init__(self): self._board = [ [0 for j in range(8)] for i in range(8) ] self._board[7][4] = King('white', self._board, 7, 4) self._whiteking = self._board[7][4] self._board[0][4] = King('black', self._board, 0, 4) self._blackking = self._board[0][4] self._whiteking._enemy = self._blackking self._blackking._enemy = self._whiteking self._board[0][3] = Queen('black', self._board, 0, 3, self._blackking) self._board[7][3] = Queen('white', self._board, 7, 3, self._whiteking) for i, j, color, king in ( (7, 0, 'white', self._whiteking), (7, 7, 'white', self._whiteking), (0, 0, 'black', self._blackking), (0, 7, 'black', self._blackking) ): self._board[i][j] = Rook(color, self._board, i, j, king) for i, j, color, king in ( (7, 1, 'white', self._whiteking), (7, 6, 'white', self._whiteking), (0, 1, 'black', self._blackking), (0, 6, 'black', self._blackking) ): self._board[i][j] = Knight(color, self._board, i, j, king) for i, j, color, king in ( (7, 2, 'white', self._whiteking), (7, 5, 'white', self._whiteking), (0, 2, 'black', self._blackking), (0, 5, 'black', self._blackking) ): self._board[i][j] = Bishop(color, self._board, i, j, king) for j in range(8): self._board[1][j] = Pawn('black', self._board, 1, j, self._blackking) self._board[6][j] = Pawn('white', self._board, 6, j, self._whiteking) self._remis_counter = 0 self._player = 0 self._colors = ['white', 'black'] self._from = None def _move(self, point): i, j = self._from k, l = self._to self._from = None if not self._board[i][j]: return if self._board[i][j]._color!=self._colors[self._player]: alert( f'Not {self._colors[not self._player]}\'s move!') return res = self._board[i][j].move(k, l) if not res: return self._player = (self._player + 1)%2 if res==2: while True: choice = prompt( 'Which one do you choose? (q, r, b, n)' ).strip().lower() if choice in list('qrbn'): break self._board[k][l] = { 'q': Queen, 'r': Rook, 'b': Bishop, 'n': Knight }[choice]( self._board[k][l]._color, self._board, k, l, self._board[k][l]._king ) draw_board(self._board) king = (self._whiteking, self._blackking)[self._player] moves = {} for subject in king._subjects: moves[subject] = list(subject.moves()) kingsmoves = list(1 for i, j in king.moves() if king.move(i, j, False)) b = king.tacticalchart() if not kingsmoves: for subject in moves: while moves[subject]: if subject.move(*moves[subject].pop(), False): break else: continue break else: if b[king._i][king._j]._incheck(b): alert('Checkmate!') elif not sum(len(m) for m in moves.values()): alert('Stalemate!') def draw_board(board): for i in range(8): for j in range(8): f = document.getElementById(f'{i} {j}') if board[i][j]: f.innerHTML = pieces[str(board[i][j])] else: f.innerHTML = '' def move(event): point = tuple( int(n) for n in event.target.id.split() ) to = {'#db9': '#fdb' , '#b63': '#d85'} back = {'#fdb': '#db9', '#d85': '#b63'} if not cb._from: bgc = document.getElementById( event.target.id ).style color = convert(bgc) cb._from = point bgc.backgroundColor = to[color] else: bgc = document.getElementById( '{} {}'.format(*cb._from) ).style color = convert(bgc) cb._to = point bgc.backgroundColor = back[color] cb._move(point) def convert(styleobj): color = ''.join( c for c in styleobj.backgroundColor if c.isdigit() or c.isspace() ).split() return '#'+''.join(hex(int(n))[-1] for n in color) board = document.getElementById('board') pieces = { 'K': '\u2654', 'Q': '\u2655', 'R': '\u2656', 'B': '\u2657', 'N': '\u2658', 'P': '\u2659', 'k': '\u265A', 'q': '\u265B', 'r': '\u265C', 'b': '\u265D', 'n': '\u265E', 'p': '\u265F' } for i in range(8): for j in range(8): board <= html.DIV( id=f'{i} {j}', style=dict( display='flex', justifyContent='center', alignItems='center', backgroundColor=( '#db9', '#b63' )[(i+j)%2], ) ) document.getElementById( f'{i} {j}').addEventListener( 'click', move, False ) cb = ChessBoard() draw_board(cb._board)


Page Title https://cdnjs.cloudflare.com/ajax/libs/brython/3.7.1/brython.min.js
# Brython Chess Board UI (by HonFu) from browser import document, html, prompt, alert class ChessPiece: def __init__(self, color, board, i, j, king=None): self._king = king or self self._color = color self._board = board self._i = i self._j = j if isinstance(self, King): self._subjects = [] else: self._king._subjects.append(self) def move(self, i, j, serious=True): if (i, j) in self.moves(): b = self._king.tacticalchart() b[self._i][self._j]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) return 1 return 0 def _move(self, i, j): if self._board[i][j]: self._board[i][j]._king._subjects.remove(self._board[i][j]) self._board[i][j] = self self._board[self._i][self._j] = 0 self._i = i self._j = j def moves(self): m = [] for d in self._directions(): for i, j in d: if not self._board[i][j]: m.append((i, j)) elif self._board[i][j]._king is not self._king: m.append((i, j)) break else: break return m def _orthogonally(self): return [ zip(range(self._i+1, 8), [self._j]*7), zip(range(self._i-1, -1, -1), [self._j]*7), zip([self._i]*7, range(self._j+1, 8)), zip([self._i]*7, range(self._j-1, -1, -1)) ] def _diagonally(self): return [ zip(range(self._i+1, 8), range(self._j+1, 8)), zip(range(self._i+1, 8), range(self._j-1, -1, -1)), zip(range(self._i-1, -1, -1), range(self._j+1, 8)), zip(range(self._i-1, -1, -1), range(self._j-1, -1, -1)) ] class King(ChessPiece): def __init__(self, color, board, i, j, king=None): super().__init__(color, board, i, j, king) self._unmoved = True def __repr__(self): return ‘K’ if self._color == ‘white’ else ‘k’ def move(self, i, j, serious=True): if self._j in (j+2, j-2) and self._unmoved: return self._rochade(i, j, serious) m = super().move(i, j, serious) if m and serious: self._unmoved = False return m def _rochade(self, i, j, serious=True): step = 1 if j>self._j else -1 rook = 7 if step==1 else 0 if ( self._board[i][rook]._unmoved and not self._board[i][self._j+step] and not self._board[i][self._j+2*step] and not self._incheck(self._board) ): b = self.tacticalchart() b[self._i][self._j]._move(i, j-step) if b[i][j-step]._king._incheck(b): return 0 b[self._i][self._j+step]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) self._board[i][rook]._move(i, j-step) self._unmoved = False return 1 def moves(self): m = [] for i in range(self._i-1, self._i+2): for j in range(self._j-1, self._j+2): if i==self._i and j==self._j: continue if 0<=i<8 and 0<=j<8 and ( not self._board[i][j] or self._board[i][j]._king is not self._king ): m.append((i, j)) return m def _incheck(self, chart): for enemy in self._enemy._subjects + [self._enemy._king]: if any( move==(self._i, self._j) for move in enemy.moves() ): return True return False def tacticalchart(self): b = [[0 for j in range(8)] for i in range(8)] thisking = King(self._color, b, self._i, self._j) b[self._i][self._j] = thisking otherking = King(self._enemy._color, b, self._enemy._i, self._enemy._j) b[self._enemy._i][self._enemy._j] = otherking thisking._enemy = otherking otherking._enemy = thisking for king, nking in ( (self, thisking), (self._enemy, otherking) ): for subject in king._subjects: i, j = subject._i, subject._j b[i][j] = type(subject)( subject._color, b, i, j, nking) if hasattr(subject, '_unmoved'): b[i][j]._unmoved = subject._unmoved if hasattr(subject, '_hasjustrun'): b[i][j]._hasjustrun = subject._hasjustrun return b class Knight(ChessPiece): def __repr__(self): return 'N' if self._color == 'white' else 'n' def moves(self): m = [] for i, j in ( (self._i-2, self._j-1), (self._i-1, self._j-2), (self._i-2, self._j+1), (self._i-1, self._j+2), (self._i+2, self._j-1), (self._i+1, self._j-2), (self._i+2, self._j+1), (self._i+1, self._j+2) ): if 0<=i<8 and 0<=j<8 and ( not self._board[i][j] or self._board[i][j]._king is not self._king ): m.append((i, j)) return m class Rook(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = self._orthogonally self._unmoved = True def __repr__(self): return 'R' if self._color == 'white' else 'r' def move(self, i, j, serious=True): m = super().move(i, j, serious) if m and serious: self._unmoved = False return m class Bishop(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = self._diagonally def __repr__(self): return 'B' if self._color == 'white' else 'b' class Queen(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._directions = lambda: self._orthogonally()+self._diagonally() def __repr__(self): return 'Q' if self._color == 'white' else 'q' class Pawn(ChessPiece): def __init__(self, color, board, i, j, king): super().__init__(color, board, i, j, king) self._step = -1 if color=='white' else 1 self._goal = 0 if color=='white' else 7 self._unmoved = True self._hasjustrun = False def __repr__(self): return 'P' if self._color == 'white' else 'p' def move(self, i, j, serious=True): if (i, j) in self.moves(): b = self._king.tacticalchart() b[self._i][self._j]._move(i, j) if b[i][j]._king._incheck(b): return 0 if serious: self._move(i, j) if i==self._goal: return 2 return 1 return 0 def _move(self, i, j): if not self._board[i][j] and j!=self._j: self._board[i-self._step][j]._king._subjects\ .remove(self._board[i-self._step][j]) self._board[i-self._step][j] = 0 self._hasjustrun = ( True if self._i in (i-2, i+2) else False ) self._unmoved = False if self._board[i][j]: self._board[i][j]._king._subjects.remove(self._board[i][j]) self._board[i][j] = self self._board[self._i][self._j] = 0 self._i = i self._j = j def moves(self): i, j = self._i+self._step, self._j if 0<=i<=7 and not self._board[i][j]: yield i, j if ( self._unmoved and not self._board[i+self._step][j] ): yield i+self._step, j for j in j-1, j+1: if ( 0<=j<8 and self._board[i][j] and self._board[i][j]._king is not self._king ): yield i, j if ( 0<=j<8 and isinstance(self._board[i-self._step][j], Pawn) and self._board[i-self._step][j]._hasjustrun ): yield i, j class ChessBoard: def __init__(self): self._board = [ [0 for j in range(8)] for i in range(8) ] self._board[7][4] = King('white', self._board, 7, 4) self._whiteking = self._board[7][4] self._board[0][4] = King('black', self._board, 0, 4) self._blackking = self._board[0][4] self._whiteking._enemy = self._blackking self._blackking._enemy = self._whiteking self._board[0][3] = Queen('black', self._board, 0, 3, self._blackking) self._board[7][3] = Queen('white', self._board, 7, 3, self._whiteking) for i, j, color, king in ( (7, 0, 'white', self._whiteking), (7, 7, 'white', self._whiteking), (0, 0, 'black', self._blackking), (0, 7, 'black', self._blackking) ): self._board[i][j] = Rook(color, self._board, i, j, king) for i, j, color, king in ( (7, 1, 'white', self._whiteking), (7, 6, 'white', self._whiteking), (0, 1, 'black', self._blackking), (0, 6, 'black', self._blackking) ): self._board[i][j] = Knight(color, self._board, i, j, king) for i, j, color, king in ( (7, 2, 'white', self._whiteking), (7, 5, 'white', self._whiteking), (0, 2, 'black', self._blackking), (0, 5, 'black', self._blackking) ): self._board[i][j] = Bishop(color, self._board, i, j, king) for j in range(8): self._board[1][j] = Pawn('black', self._board, 1, j, self._blackking) self._board[6][j] = Pawn('white', self._board, 6, j, self._whiteking) self._remis_counter = 0 self._player = 0 self._colors = ['white', 'black'] self._from = None def _move(self, point): i, j = self._from k, l = self._to self._from = None if not self._board[i][j]: return if self._board[i][j]._color!=self._colors[self._player]: alert( f'Not {self._colors[not self._player]}\'s move!') return res = self._board[i][j].move(k, l) if not res: return self._player = (self._player + 1)%2 if res==2: while True: choice = prompt( 'Which one do you choose? (q, r, b, n)' ).strip().lower() if choice in list('qrbn'): break self._board[k][l] = { 'q': Queen, 'r': Rook, 'b': Bishop, 'n': Knight }[choice]( self._board[k][l]._color, self._board, k, l, self._board[k][l]._king ) draw_board(self._board) king = (self._whiteking, self._blackking)[self._player] moves = {} for subject in king._subjects: moves[subject] = list(subject.moves()) kingsmoves = list(1 for i, j in king.moves() if king.move(i, j, False)) b = king.tacticalchart() if not kingsmoves: for subject in moves: while moves[subject]: if subject.move(*moves[subject].pop(), False): break else: continue break else: if b[king._i][king._j]._incheck(b): alert('Checkmate!') elif not sum(len(m) for m in moves.values()): alert('Stalemate!') def draw_board(board): for i in range(8): for j in range(8): f = document.getElementById(f'{i} {j}') if board[i][j]: f.innerHTML = pieces[str(board[i][j])] else: f.innerHTML = '' def move(event): point = tuple( int(n) for n in event.target.id.split() ) to = {'#db9': '#fdb' , '#b63': '#d85'} back = {'#fdb': '#db9', '#d85': '#b63'} if not cb._from: bgc = document.getElementById( event.target.id ).style color = convert(bgc) cb._from = point bgc.backgroundColor = to[color] else: bgc = document.getElementById( '{} {}'.format(*cb._from) ).style color = convert(bgc) cb._to = point bgc.backgroundColor = back[color] cb._move(point) def convert(styleobj): color = ''.join( c for c in styleobj.backgroundColor if c.isdigit() or c.isspace() ).split() return '#'+''.join(hex(int(n))[-1] for n in color) board = document.getElementById('board') pieces = { 'K': '\u2654', 'Q': '\u2655', 'R': '\u2656', 'B': '\u2657', 'N': '\u2658', 'P': '\u2659', 'k': '\u265A', 'q': '\u265B', 'r': '\u265C', 'b': '\u265D', 'n': '\u265E', 'p': '\u265F' } for i in range(8): for j in range(8): board <= html.DIV( id=f'{i} {j}', style=dict( display='flex', justifyContent='center', alignItems='center', backgroundColor=( '#db9', '#b63' )[(i+j)%2], ) ) document.getElementById( f'{i} {j}').addEventListener( 'click', move, False ) cb = ChessBoard() draw_board(cb._board)