GAME / FREE / MIT EXAMPLE SOURCE
Quiet moves
A board for two
Local chess with legal moves, king safety, castling, en passant, promotion, checkmate, and stalemate.

Take it for a spin.
Select a piece, then a highlighted destination. Choose promotion with Q, N, B, or T for rook. R resets.
Extract the Windows download to a writable folder and open chess.exe. Escape closes it. Database examples keep their local data in the working folder.
See how it works.
Value snapshots, pure move simulation, attack maps, and rule composition.
Local two-player chess. No AI, clocks, online play, repetition claims, or fifty-move draw adjudication.
READ / CHANGE / UNDERSTAND
The whole example is yours.
These are the exact files in the source download. Start with the model, then follow the window’s event loop. Comments explain the decisions.
// Signed pieces encode side: positive is White, negative is Black.
// 1 pawn, 2 knight, 3 bishop, 4 rook, 5 queen, 6 king. Zero is empty.
Side(int piece) returns int
{
if piece>0
{
return 1
}
if piece<0
{
return -1
}
return 0
}
Abs(int value) returns int
{
if value<0
{
return -value
}
return value
}
Column(int square) returns int
{
return square-square/8*8
}
Step(int value) returns int
{
if value<0
{
return -1
}
if value>0
{
return 1
}
return 0
}
PieceName(int piece) returns text
{
list of text names=["","P","N","B","R","Q","K"]
return names[Abs(piece)]
}
class Chess
{
list of int board=[]
int turn=1
int passant=-1
bool whiteKing=true
bool whiteQueen=true
bool blackKing=true
bool blackQueen=true
text status="White to move"
int moves=0
Chess()
{
this.Reset()
}
Reset()
{
this.board=[-4, -2, -3, -5, -6, -3, -2, -4, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 4, 2, 3, 5, 6, 3, 2, 4]
this.turn=1
this.passant=-1
this.whiteKing=true
this.whiteQueen=true
this.blackKing=true
this.blackQueen=true
this.status="White to move"
this.moves=0
}
ClearPath(list of int position,int from,int to) returns bool
{
int x=Column(from)+Step(Column(to)-Column(from))
int y=from/8+Step(to/8-from/8)
while x!=Column(to) or y!=to/8
{
if position[y*8+x]!=0
{
return false
}
x=x+Step(Column(to)-Column(from))
y=y+Step(to/8-from/8)
}
return true
}
// Attack tests deliberately ignore king safety and castling. Pawns attack
// diagonally even when the target is empty; this matters for castling checks.
Attacks(list of int position,int from,int to) returns bool
{
int piece=Abs(position[from])
int dx=Column(to)-Column(from)
int dy=to/8-from/8
if piece==1
{
return Abs(dx)==1 and dy==-Side(position[from])
}
if piece==2
{
return (Abs(dx)==1 and Abs(dy)==2) or (Abs(dx)==2 and Abs(dy)==1)
}
if piece==6
{
return Abs(dx)<=1 and Abs(dy)<=1 and from!=to
}
bool shape=(piece==3 and Abs(dx)==Abs(dy)) or (piece==4 and (dx==0 or dy==0)) or (piece==5 and (dx==0 or dy==0 or Abs(dx)==Abs(dy)))
return from!=to and shape and this.ClearPath(position,from,to)
}
Checked(list of int position,int side) returns bool
{
int king=-1
for piece at i in position
{
if piece==side*6
{
king=i
}
}
if king<0
{
return true
}
for piece at i in position
{
if Side(piece)==-side and this.Attacks(position,i,king)
{
return true
}
}
return false
}
Apply(list of int position,int from,int to,int promotion=5) returns list of int
{
int piece=position[from]
// Lists are value data here. Simulations must never mutate the live board.
if Abs(piece)==1 and to==this.passant and position[to]==0
{
position[to+Side(piece)*8]=0
}
if Abs(piece)==6 and Abs(to-from)==2
{
int rook=from+3
int destination=from+1
if to<from
{
rook=from-4
destination=from-1
}
position[destination]=position[rook]
position[rook]=0
}
position[to]=piece
position[from]=0
if Abs(piece)==1 and (to/8==0 or to/8==7)
{
position[to]=Side(piece)*promotion
}
return position
}
Legal(int from,int to) returns bool
{
if from<0 or from>=64 or to<0 or to>=64 or from==to
{
return false
}
int piece=this.board[from]
int side=Side(piece)
int type=Abs(piece)
if side!=this.turn or Side(this.board[to])==side or Abs(this.board[to])==6
{
return false
}
int dx=Column(to)-Column(from)
int dy=to/8-from/8
bool valid=false
if type==1
{
int home=6
if side==-1
{
home=1
}
valid=(dx==0 and dy==-side and this.board[to]==0) or (dx==0 and dy==-side*2 and from/8==home and this.board[to]==0 and this.board[from-side*8]==0) or (Abs(dx)==1 and dy==-side and (Side(this.board[to])==-side or (to==this.passant and this.board[to+side*8]==-side)))
}
else
{
valid=this.Attacks(this.board,from,to)
}
if type==6 and dy==0 and Abs(dx)==2 and ((side==1 and from==60) or (side==-1 and from==4))
{
bool rights=this.whiteKing
if dx<0
{
rights=this.whiteQueen
}
if side==-1
{
rights=this.blackKing
if dx<0
{
rights=this.blackQueen
}
}
int rook=from+3
if dx<0
{
rook=from-4
}
valid=rights and this.board[rook]==side*4 and this.ClearPath(this.board,from,rook) and !this.Checked(this.board,side) and !this.Checked(this.Apply(this.board,from,from+Step(dx)),side)
}
return valid and !this.Checked(this.Apply(this.board,from,to),side)
}
Move(int from,int to,int promotion=5) returns bool
{
if !this.Legal(from,to) or promotion<2 or promotion>5
{
return false
}
int piece=this.board[from]
this.board=this.Apply(this.board,from,to,promotion)
// Rights are irreversible, including when a home rook is captured.
if from==60
{
this.whiteKing=false
this.whiteQueen=false
}
if from==4
{
this.blackKing=false
this.blackQueen=false
}
if from==63 or to==63
{
this.whiteKing=false
}
if from==56 or to==56
{
this.whiteQueen=false
}
if from==7 or to==7
{
this.blackKing=false
}
if from==0 or to==0
{
this.blackQueen=false
}
this.passant=-1
if Abs(piece)==1 and Abs(to-from)==16
{
this.passant=(to+from)/2
}
this.turn=-this.turn
this.moves=this.moves+1
this.status="White to move"
if this.turn==-1
{
this.status="Black to move"
}
bool any=false
for a from 0 < 64
{
if Side(this.board[a])==this.turn
{
for b from 0 < 64
{
if this.Legal(a,b)
{
any=true
end
}
}
}
if any
{
end
}
}
bool check=this.Checked(this.board,this.turn)
if check
{
this.status=this.status+" / check"
}
if !any
{
this.status="Stalemate"
if check
{
this.status="Checkmate"
}
}
return true
}
}
