MCPcopy Create free account
hub / github.com/CodeClash-ai/CodeClash / _apply

Function _apply

codeclash/arenas/chess/replay.py:125–186  ·  view source on GitHub ↗

Apply one SAN move for the side to move. Returns (new_board, from, to, new_ep).

(board, san, white, ep)

Source from the content-addressed store, hash-verified

123
124
125def _apply(board, san, white, ep):
126 """Apply one SAN move for the side to move. Returns (new_board, from, to, new_ep)."""
127 m = san.rstrip("+#!?")
128 b = _clone(board)
129
130 if m in ("O-O", "O-O-O", "0-0", "0-0-0"):
131 row = 7 if white else 0
132 k = "K" if white else "k"
133 rk = "R" if white else "r"
134 if m in ("O-O", "0-0"):
135 b[row][4], b[row][6], b[row][7], b[row][5] = "", k, "", rk
136 return b, (row, 4), (row, 6), None
137 b[row][4], b[row][2], b[row][0], b[row][3] = "", k, "", rk
138 return b, (row, 4), (row, 2), None
139
140 promo = ""
141 if "=" in m:
142 m, promo = m.split("=")
143 promo = promo[0]
144 m = m.replace("x", "")
145 dest = m[-2:]
146 tr, tc = _sq(dest)
147 head = m[:-2]
148 kind = head[0] if head and head[0] in "NBRQK" else "P"
149 hint = head[1:] if kind != "P" else head # disambiguation (file/rank), or pawn's from-file
150 want = kind if white else kind.lower()
151
152 candidates = []
153 for r in range(8):
154 for c in range(8):
155 if board[r][c] == want and _reaches(board, want, r, c, tr, tc, ep):
156 candidates.append((r, c))
157 for ch in hint: # filter by file/rank disambiguation
158 if ch.isalpha():
159 candidates = [(r, c) for (r, c) in candidates if c == ord(ch) - ord("a")]
160 elif ch.isdigit():
161 candidates = [(r, c) for (r, c) in candidates if r == 8 - int(ch)]
162 if len(candidates) > 1: # remaining ambiguity = pins; keep only king-safe moves
163 safe = []
164 for r, c in candidates:
165 t = _clone(board)
166 t[tr][tc] = t[r][c]
167 t[r][c] = ""
168 kp = _king(t, white)
169 if kp and not _attacked(t, kp[0], kp[1], not white):
170 safe.append((r, c))
171 if safe:
172 candidates = safe
173 fr, fc = candidates[0]
174
175 piece = b[fr][fc]
176 new_ep = None
177 if kind == "P":
178 if (tr, tc) == ep and board[tr][tc] == "": # en passant: remove passed pawn
179 b[fr][tc] = ""
180 if abs(tr - fr) == 2: # double push sets the en-passant square
181 new_ep = ((fr + tr) // 2, fc)
182 if promo:

Callers 1

parseMethod · 0.85

Calls 5

_cloneFunction · 0.85
_sqFunction · 0.85
_reachesFunction · 0.85
_kingFunction · 0.85
_attackedFunction · 0.85

Tested by

no test coverage detected