Skip to content

Instantly share code, notes, and snippets.

@mekhami
Last active March 21, 2016 19:10
Show Gist options
  • Select an option

  • Save mekhami/08634d36007a5eba0a14 to your computer and use it in GitHub Desktop.

Select an option

Save mekhami/08634d36007a5eba0a14 to your computer and use it in GitHub Desktop.
import sys
import unittest
class ChessGame(object):
fen_startpos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
fen_test = "rnbqkb1r/1p2pppp/p2p1n2/8/3NP3/2N5/PPP2PPP/R1BQKB1R w KQkq -"
def __init__(self):
self.board = [["#"]*12 for i in range(12)]
self.turn = "-"
self.castling = "-"
self.ep = "-"
self.set_fen(ChessGame.fen_startpos)
def set_fen(self, fen):
parts = fen.split(" ")
# Board setup
sq = 110
for a in range(0, len(parts[0])):
if(parts[0][a].isalpha()):
self.board[sq%12][sq/12] = parts[0][a]
sq += 1
elif(parts[0][a] == "/"):
sq -= 20
else:
for b in range(0, int(parts[0][a])):
self.board[(sq+b)%12][(sq+b)/12] = "-"
sq += int(parts[0][a])
# Side to play
if(len(parts) >= 1):
if(parts[1] == "w"):
self.turn = "w"
elif(parts[1] == "b"):
self.turn = "b"
else:
self.turn = "w"
# Castling
if(len(parts) >= 2):
self.castling = parts[2]
def get_fen(self):
fen = ""
fen += " "
fen += self.turn
fen += " "
fen += self.castling
fen += " -"
return fen
def get_url(self):
return "http://lichess.org/editor/{}".format(self.fen)
def print_board(self):
for y in range(0, 8):
for x in range(0, 8):
sys.stdout.write(self.board[x+2][7-y+2])
sys.stdout.write("\n")
print("Turn: {}".format(self.turn))
print("Castling: {}".format(self.castling))
def pos_get_col(self, str):
if(str[0] == "a"):
return 0;
if(str[0] == "b"):
return 1;
if(str[0] == "c"):
return 2;
if(str[0] == "d"):
return 3;
if(str[0] == "e"):
return 4;
if(str[0] == "f"):
return 5;
if(str[0] == "g"):
return 6;
if(str[0] == "h"):
return 7;
def pos_get_row(self, str):
if(str[1] == "1"):
return 0;
if(str[1] == "2"):
return 1;
if(str[1] == "3"):
return 2;
if(str[1] == "4"):
return 3;
if(str[1] == "5"):
return 4;
if(str[1] == "6"):
return 5;
if(str[1] == "7"):
return 6;
if(str[1] == "8"):
return 7;
def board_get(self, col, row):
return self.board[col+2][row+2]
def find_move_wP(self, col_to, row_to, hint="-"):
if(hint != "-"):
return [self.pos_get_col(hint), row_to-1]
else:
if(self.board_get(col_to, row_to-1) == "P"):
return [col_to, row_to-1]
elif(self.board_get(col_to, row_to-2) == "P"):
return [col_to, row_to-2]
else:
return None
def find_move_bP(self, col_to, row_to, hint="-"):
if(hint != "-"):
return [self.pos_get_col(hint), row_to+1]
else:
if(self.board_get(col_to, row_to+1) == "p"):
return [col_to, row_to+1]
elif(self.board_get(col_to, row_to+2) == "p"):
return [col_to, row_to+2]
else:
return None
def find_move_N(self, piece, col_to, row_to, hint="-"):
if(self.board_get(col_to-1, row_to+2) == piece): # Up 2 left 1
return [col_to-1, row_to+2]
elif(self.board_get(col_to+1, row_to+2) == piece): # Up 2 right 1
return [col_to+1, row_to+2]
elif(self.board_get(col_to-1, row_to-2) == piece): # Down 2 left 1
return [col_to-1, row_to-2]
elif(self.board_get(col_to+1, row_to-2) == piece): # Down 2 right 1
return [col_to+1, row_to-2]
elif(self.board_get(col_to+2, row_to+1) == piece): # Right 2 up 1
return [col_to+2, row_to+1]
elif(self.board_get(col_to+2, row_to-1) == piece): # Right 2 down 1
return [col_to+2, row_to-1]
elif(self.board_get(col_to-2, row_to+1) == piece): # Left 2 up 1
return [col_to-2, row_to+1]
elif(self.board_get(col_to-2, row_to-1) == piece): # Left 2 down 1
return [col_to-2, row_to-1]
else:
return None
def find_move_B(self, piece, col_to, row_to, hint="-"):
# Up and right
for a in range(0, 8):
if(self.board_get(col_to+a, row_to+a) != "-"):
if(self.board_get(col_to+a, row_to+a) == piece):
return [col_to+a, row_to+a]
else:
break
# Up and left
for a in range(0, 8):
if(self.board_get(col_to-a, row_to+a) != "-"):
if(self.board_get(col_to-a, row_to+a) == piece):
return [col_to-a, row_to+a]
else:
break
# Down and right
for a in range(0, 8):
if(self.board_get(col_to+a, row_to-a) != "-"):
if(self.board_get(col_to+a, row_to-a) == piece):
return [col_to+a, row_to-a]
else:
break
# Down and left
for a in range(0, 8):
if(self.board_get(col_to-a, row_to-a) != "-"):
if(self.board_get(col_to-a, row_to-a) == piece):
return [col_to-a, row_to-a]
else:
break
return None
def find_move_R(self, piece, col_to, row_to, hint="-"):
# Right
for a in range(0, 8):
if(self.board_get(col_to+a, row_to) != "-"):
if(self.board_get(col_to+a, row_to) == piece):
return [col_to+a, row_to]
else:
break
# Left
for a in range(0, 8):
if(self.board_get(col_to-a, row_to) != "-"):
if(self.board_get(col_to-a, row_to) == piece):
return [col_to-a, row_to]
else:
break
# Up
for a in range(0, 8):
if(self.board_get(col_to, row_to+a) != "-"):
if(self.board_get(col_to, row_to+a) == piece):
return [col_to, row_to+a]
else:
break
# Down
for a in range(0, 8):
if(self.board_get(col_to, row_to-a) != "-"):
if(self.board_get(col_to, row_to-a) == piece):
return [col_to, row_to-a]
else:
break
return None
def find_move_Q(self, piece, col_to, row_to, hint="-"):
result = self.find_move_B(piece, col_to, row_to, hint);
if(result != None):
return result
result = self.find_move_R(piece, col_to, row_to, hint);
if(result):
return result
return None
def make_move(self, from_col, from_row, to_col, to_row, promotion="-"):
if(from_col < 0 or from_col >= 8 or to_col < 0 or to_row >= 8):
return
if(promotion == "-"):
self.board[to_col+2][to_row+2] = self.board[from_col+2][from_row+2]
else:
self.board[to_col+2][to_row+2] = promotion
self.board[from_col+2][from_row+2] = "-"
return
def make_move_wKSC(self):
self.make_move(4,0, 6,0)
self.make_move(7,0, 5,0)
def make_move_bKSC(self):
self.make_move(4,7, 6,7)
self.make_move(7,7, 5,7)
def parse_move(self, move):
# Special case of castling
if(move == "O-O"):
if(self.turn == "w"):
self.make_move_wKSC()
return
elif(self.turn == "b"):
self.make_move_bKSC()
return
elif(move == "O-O-O"):
if(self.turn == "w"):
self.make_move_wQSC()
return
elif(self.turn == "b"):
self.make_move_bQSC()
return
strip = "!?+#x-:="
for a in strip:
move = move.replace(a, "")
sys.stdout.write(move + "\t")
type = "P"
if(move[0].isupper()):
type = move[0]
move = move[1:]
promotion = "-"
if(move[-1:].isalpha()):
promotion = move[-1:]
move = move[:-1]
sys.stdout.write(type + " ")
str_from = move[:2]
sys.stdout.write(str_from + " ")
str_to = move[-2:]
sys.stdout.write(str_to + " ")
col_to = self.pos_get_col(str_to)
row_to = self.pos_get_row(str_to)
sys.stdout.write("(" + str(col_to) + "," + str(row_to) + ") ")
sys.stdout.write(promotion + " ")
hint = "-"
if(str_from == str_to):
pass
else:
hint = str_from[0]
sys.stdout.write(hint + " ")
move_found = None
if(self.turn == "w"):
if(type == "P"):
move_found = self.find_move_wP(col_to, row_to, hint)
elif(type == "N"):
move_found = self.find_move_N("N", col_to, row_to, hint)
elif(type == "B"):
move_found = self.find_move_B("B", col_to, row_to, hint)
elif(type == "R"):
move_found = self.find_move_R("R", col_to, row_to, hint)
elif(type == "Q"):
move_found = self.find_move_Q("Q", col_to, row_to, hint)
elif(self.turn == "b"):
if(type == "P"):
move_found = self.find_move_bP(col_to, row_to, hint)
elif(type == "N"):
move_found = self.find_move_N("n", col_to, row_to, hint)
elif(type == "B"):
move_found = self.find_move_B("b", col_to, row_to, hint)
elif(type == "R"):
move_found = self.find_move_R("r", col_to, row_to, hint)
elif(type == "Q"):
move_found = self.find_move_Q("q", col_to, row_to, hint)
if(move_found != None):
sys.stdout.write("(" + str(move_found[0]) + "," + str(move_found[1]) + ") ")
self.make_move(move_found[0], move_found[1], col_to, row_to, promotion)
sys.stdout.write("\n")
return
def parse_moves(self, moves):
split = moves.split(" ")
for a in split:
if(a[0].isdigit() == True):
continue
self.parse_move(a)
if(self.turn == "w"):
self.turn = "b"
else:
self.turn = "w"
self.print_board()
print("")
return
class FenTest(unittest.TestCase):
def test_get_fen_of_new_game(self):
board = ChessGame()
self.assertEqual(board.get_fen(),
"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
if __name__ == '__main__':
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment