Cursussen/Courses Codesnippets     Top 
B4A-chess - Special moves


1. Castling
When there are no pieces between the king and the rook (of the same color) on the left or right side of the king then the rook can move next to the king and the king jumps over the rook to the left or right.
This requires two moves: one from the rook and one from the king.
The player should know that the king is not in a check position and that the king has never moved before. When performing the castling the empty squares between the king and the rook are not a check position for the king.
The app will only perform the moves and will not verify the conditions of the castling.
On to the code.
When a player moves the rook to the square next to the king (on either side) than we will ask the player if a castling is needed.
For this we write a subroutine asking that question:
Private Sub castling_question(crrowcol As String)
	Dim answ As Object = xui.Msgbox2Async("Perform castling?","Castling","yes","","no",Null)
	Wait For (answ) Msgbox_Result (Result As Int)
	If Result = xui.DialogResponse_Positive Then
		xui.MsgboxAsync("Castling in progress...","Castling")
		castlingstr = "-O"
		Private crrow As Int = crrowcol.SubString2(0,1)
		Private crcol As Int = crrowcol.SubString(1)
		castling(crrow,crcol)
		refresh_board
		show_board_log
	End If
End Sub
Private Sub castling(rrow As Int, rcol As Int)
	Log("castling: " & rrow & " " & rcol)
	If rrow = 0 And rcol = 3 And board(0,4) = "BK1" Then	' long black king
		board(0,2) = "BK1"
		board(0,4) = "EEE"
	End If
	If rrow = 0 And rcol = 5 And board(0,4) = "BK1" Then	' short black king
		board(0,6) = "BK1"
		board(0,4) = "EEE"
	End If
	If rrow = 7 And rcol = 3 And board(7,4) = "WK1" Then	' long white king
		board(7,2) = "WK1"
		board(7,4) = "EEE"
	End If
	If rrow = 7 And rcol = 5 And board(7,4) = "WK1" Then	' short white king
		board(7,6) = "WK1"
		board(7,4) = "EEE"
	End If
End Sub
If the answer is "yes" than the castling subroutine is executed.
The board array is changed for the king and later in the do_move subroutine the move from the rook is performed.
The call to the castling question subroutine is done in the pnl_click subroutine after the line destrowcol = rowcol:
		If srctext.SubString2(1,2) = "R" Then
			If destrowcol.SubString2(0,1) = 0 And srctext.SubString2(0,1) = "B" Then
				If destrowcol.SubString(1) = 3 Or destrowcol.SubString(1) = 5 Then
					castling_question(destrowcol)
					Sleep(3000)
				End If
			End If
			If destrowcol.SubString2(0,1) = 7 And srctext.SubString2(0,1) = "W" Then
				If destrowcol.SubString(1) = 3 Or destrowcol.SubString(1) = 5 Then
					castling_question(destrowcol)
					Sleep(3000)
				End If
			End If
		End If
The rook is about to move to one of the castling squares. Then it is time to ask the castling question.
The sleep command pauses the app to make sure that the move of the rook and the addition of the note are performed.
To clear the castling string (and the other special move strings) we add the lines above the switch_turn call in the pnl_Click subroutine:
		castlingstr = ""
		inpassingstr = ""
		promostr = ""
Here's an example of castling:


2. In passing
When a white pawn is on row 3 and the black pawn has just moved next to the white pawn on row 3 then the white pawn can take the black pawn as if it was on row 2 diagonal. This situation is the same for the black pawn and row 4 and row 5 diagonal.
In the pawn_hints subroutine the squares that can be used to perform in passing are already in place.
The pawn of the opposite color needs to be taken from the square one row up or down and in the same column.
This we do in the do_move subroutine below the taken test and above the board array adjustment:
	If drow = 2 And srctext.StartsWith("WP") And board((drow+1),dcol).StartsWith("BP") Then
		add_piece_to_pnltaken(board((drow+1),dcol),imagemap.Get(board((drow+1),dcol)))
		board((drow+1),dcol) = "EEE"
		take = "x"
		inpassingstr = "ep"
	End If
	If drow = 5 And srctext.StartsWith("BP") And board((drow-1),dcol).StartsWith("WP") Then
		add_piece_to_pnltaken(board((drow-1),dcol),imagemap.Get(board((drow-1),dcol)))
		board((drow-1),dcol) = "EEE"
		take = "x"
		inpassingstr = "ep"
	End If
An example:


3. Promotion
When a pawn reaches the other side of the board (row 0 for a white pawn or row 7 for a black pawn) then that pawn can be promoted to a queen (or rook or bishop or knight).
In this app the pawn is replaced by a queen of the same color by default.
If you want the player to have a choice than you can write a subroutine to ask which piece should be used for promotion.
In the do_move subroutine above the call to the add_note_to_clvinfo subroutine you can add the following code:
	If drow = 0 And srctext.StartsWith("WP") Then
		board(drow,dcol) = "WQ1"
		promostr = "=Q"
	End If
	If drow = 7 And srctext.StartsWith("BP") Then
		board(drow,dcol) = "BQ1"
		promostr = "=Q"
	End If
Here's an example what happens when a pawn reaches the other side of the board:


4. King's check
To determine if a king piece is in a check position depends on a lot of factors.
Is there a piece directly threatening the king piece?
Is there a piece that is pinned between the king piece and a piece from the other player and that piece is moved?
Can the king piece move to a square where it is not in a check position?
Is the king piece in a stalemate situation and no other pieces from the same color can move?
Is the king in a checkmate position?
The app doesn't give an answer to all these questions.
The app shows a check situation resulting from a move of a piece from the opposite color player and that piece threatens the king piece.
A check_indication subroutine can show if a king piece is in a check position.
Private Sub check_indication
	Private pcscolor As String = srctext.SubString2(0,1)
	Private pcsletter As String = srctext.SubString2(1,2)
	hintslst.Clear
	hintslst = get_hints(destrowcol,pcscolor,pcsletter)
	Private chrowcol As String
	If pcscolor = "W" Then chrowcol = bkrowcol		' black king position
	If pcscolor = "B" Then chrowcol = wkrowcol		' white king position
	Log("check indication: " & hintslst)
	If hintslst.IndexOf(chrowcol) <> -1 And pcsletter <> "K" Then
		Log("king check!")
		xui.MsgboxAsync("King check!","Check")
		Private pnlcheck As Panel = get_board_panel(destrowcol,pnlmain)
		cnvscell.Initialize(pnlcheck)
		show_cell_border(Colors.Red,10dip,cnvscell)
		Private pnlcheck As Panel = get_board_panel(chrowcol,pnlmain)
		cnvscell.Initialize(pnlcheck)
		show_cell_border(Colors.Red,10dip,cnvscell)
	End If
	hintslst.Clear
End Sub
The bkrowcol and wkrowcol string variables hold the position of the king on the board.
To update the positions of the kings we add 2 lines of code in the resfresh_board subroutine (in the inner loop above the next line):
			If board(r,c) = "BK1" Then bkrowcol = r&c
			If board(r,c) = "WK1" Then wkrowcol = r&c
We can call the check_indication subroutine in the pnl_Click subroutine above the line clickcnt = 0:
		check_indication
Here's an example of a check situation: