online multiplayer chess game (note server currently down)
Diffstat (limited to 'SanParse/SanParse.gd')
-rw-r--r--SanParse/SanParse.gd156
1 files changed, 156 insertions, 0 deletions
diff --git a/SanParse/SanParse.gd b/SanParse/SanParse.gd
new file mode 100644
index 0000000..3669672
--- /dev/null
+++ b/SanParse/SanParse.gd
@@ -0,0 +1,156 @@
+extends Node
+class_name SanParser
+
+const end := "(\\+|\\#)?(\\?\\?|\\?|\\?!|!|!!)?$" # annotation
+
+var regexs := {
+ "pawn_move": compile("^([a-h])([1-8])"),
+ "long_pawn_move": compile("^([a-h])([1-8])([a-h])([1-8])"), # long-san
+ "piece_movement": compile("^([KQBNR])([a-h])([1-8])"),
+ "specific_row_piece_movement": compile("^([KQBNR])([0-9])([a-h])([1-8])"),
+ "specific_column_piece_movement": compile("^([KQBNR])([a-h])([a-h])([1-8])"),
+ "long_piece_movement": compile("^([KQBNR])([a-h])([0-9])([a-h])([1-8])"),
+ "pawn_capture": compile("^([a-h])x([a-h])([1-8])(?:=?([KQBNR]))?"),
+ "long_pawn_capture": compile("^([a-h])([1-8])x([a-h])([1-8])(?:=?([KQBNR]))?"),
+ "piece_capture": compile("^([KQBNR])x([a-h])([1-8])"),
+ "specific_column_piece_capture": compile("^([KQBNR])([a-h])x([a-h])([1-8])"),
+ "specific_row_piece_capture": compile("^([KQBNR])([0-9])x([a-h])([1-8])"),
+ "long_piece_capture": compile("^([KQBNR])([a-h])([0-9])x([a-h])([1-8])"),
+ "pawn_promotion": compile("^([a-h])([1-8])=?([KQBNR])"),
+ "castling": compile("^(O-O-O|O-O)"),
+}
+
+
+static func pos(col: String, row: String) -> Vector2:
+ return Utils.from_algebraic(col + row)
+
+
+const UNKNOWN_POS = Vector2(-1, -1)
+enum { PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING }
+
+
+func from_str(string: String) -> int:
+ var find = " NBRQK".find(string)
+ if find != -1:
+ return find
+ else:
+ return "PNBRQK".find(string)
+
+
+func compile(regxstr: String, app_end := true) -> RegEx: #app_end because append end get it
+ var reg = RegEx.new()
+ reg.compile(regxstr + end if app_end else regxstr)
+ return reg
+
+
+func parse(san: String) -> Move:
+ var mv = regexmatch(san)
+ mv.generated_from = san # for debugging i just moved the thing over so i can do this
+ return mv
+
+
+func regexmatch(san: String) -> Move:
+ var re: RegExMatch = regexs.pawn_move.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(PAWN, [UNKNOWN_POS, pos(cap[1], cap[2])])
+ mov.set_check_type(cap[3])
+ return mov
+
+ re = regexs.long_pawn_move.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(PAWN, [pos(cap[1], cap[2]), pos(cap[3], cap[4])])
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.piece_movement.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [UNKNOWN_POS, pos(cap[2], cap[3])])
+ mov.set_check_type(cap[4])
+ return mov
+
+ re = regexs.specific_row_piece_movement.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [Vector2(-1, Utils.row_pos(cap[2])), pos(cap[3], cap[4])])
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.specific_column_piece_movement.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [Vector2(Utils.col_pos(cap[2]), -1), pos(cap[3], cap[4])])
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.long_piece_movement.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [pos(cap[2], cap[3]), pos(cap[4], cap[5])])
+ mov.set_check_type(cap[6])
+ return mov
+
+ re = regexs.pawn_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(PAWN, [Vector2(Utils.col_pos(cap[1]), -1), pos(cap[2], cap[3])], true)
+ mov.promotion = from_str(cap[4])
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.long_pawn_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(PAWN, [pos(cap[1], cap[2]), pos(cap[3], cap[4])], true)
+ mov.promotion = from_str(cap[5])
+ mov.set_check_type(cap[6])
+ return mov
+
+ re = regexs.piece_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [Vector2(Utils.col_pos(cap[2]), -1), pos(cap[3], cap[4])], true)
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.specific_column_piece_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [Vector2(Utils.col_pos(cap[2]), -1), pos(cap[3], cap[4])], true)
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.specific_row_piece_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [Vector2(-1, Utils.row_pos(cap[2])), pos(cap[3], cap[4])], true)
+ mov.set_check_type(cap[5])
+ return mov
+
+ re = regexs.long_piece_capture.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(from_str(cap[1]), [pos(cap[2], cap[3]), pos(cap[4], cap[5])], true)
+ mov.set_check_type(cap[6])
+ return mov
+
+ re = regexs.pawn_promotion.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(PAWN, [UNKNOWN_POS, pos(cap[1], cap[2])], true)
+ mov.promotion = from_str(cap[3])
+ mov.set_check_type(cap[4])
+ return mov
+
+ re = regexs.castling.search(san)
+ if re:
+ var cap = re.strings
+ var mov = Move.new(KING, Move.castle_type(cap[1]))
+ mov.set_check_type(cap[2])
+ return mov
+
+ push_error("regex exhausted: no matches(%s)" % san)
+
+ return null