Tic-Tac-Toe and Chess, with fewest [distinct] characters In this form of the game Tic-Tac-Chec, the goal is to move chess pieces to get four-in-a-row. Your goal here is to figure out if a position has a winning move.
Rules
The rules are similar, but not identical, to those of Tic-Tac-Chec.
The board is 4 by 4 squares. Each player has a rook, bishop, knight, and queen. On your turn, you have two options. You can move one of your pieces already on the board, following  standard chess rules. Or you can place a piece not already on the board, on any unoccupied place.
If you move an existing piece onto an opponent's piece, their piece is taken off the board and returned to them. However, you may not place a new piece on top of an opponent's piece.
As soon as one player has all of their pieces in a row (or column, or diagonal), they win.
Challenge
Write a full program that accepts a board from STDIN, and outputs whether the white player can win on the next turn.
Input
Four strings of 4 characters each. Each character is either a space or a chess piece. Only rooks, bishops, knights, and queens are used, and at most one of each (per color) may appear. Neither player already has a four-in-a-row.
You can choose whether to accept as input the Unicode symbols for the chess pieces, or letters. If you choose letters, RBKQ represents white pieces, and rbkq represents black pieces.
Output
If the white player can win on the next turn, output true or 1. Otherwise, output false or 0.
Program
Choose a number X. Your program may contain at most X distinct characters, and no character may appear more than X times.
Winning
Lowest X wins. In case of a tie, fewest characters wins.
Examples
These examples assume the input uses letters to represent the pieces.
rkb 
    
    
RB Q
true - the white player can place the knight to complete the bottom row.
-----------------------------------
rk    
    
    
RBbQ
false - the black bishop prevents the white knight from completing the row.
-----------------------------------
rk  
 K  
    
RBbQ
true - the white knight can capture the black bishop and complete the row.
-----------------------------------
rkRB
    
 Qb 
K   
true - the white rook can move down one to complete the diagonal.
APL (Dyalog Unicode), 369 characters, score 28

{Q←(QQ←⍴⍵)[1]
R←∨/¨⍵=⊂'RBQK'
B←({⍵(⍵[↑(⍳Q),¨¨⊂1--Q-⍳Q])}↑(⍳Q)=⊂⍳Q),{⍵,{⍵[{⍵[(1--1)1]}¨⍳QQ]}¨⍵}(⊂QQ)⍴¨(⍳Q)=⊂⍳Q
K←(Q-1)={∨/1↑⍴{(,⍵)/,⍳⍴⍵}⍵}¨B×⊂R
1-∨/K:1-1
K←↑∨/K/B
BB←{(,⍵)/,⍳⍴⍵}K×1-R
R←↑∨/BB-B←{(,⍵)/,⍳⍴⍵}R×1-K
1-⍴B:⍵[BB]=1↑''
BB←(1-∨/¨'RBQK'=⊂⍵[(,K)/,⍳⍴K])/'RBQK'
'K'=BB:×/∨/¨(⍳1--1)=⊂R∨-R
1-∨/(1-(⍳1--1)='RB'⍳BB)×(=/,{∨/1-×⍵})R∨-R:1-1
×/(1↑'')=⍵[B--(×⊂R)×⍳-1-∨/R]}↑⍞⍞⍞⍞

Try it online!
Character statistics:
 -  1  B  )  (  ⍵  /  Q  ⍳  R  '  ∨  LF   K  ,  =  ←  }  { ⊂ × ¨ ⍴ ↑ ] [ ⍞ :
27 26 22 20 20 19 19 18 15 15 14 12  12  12 12 11 10 10 10 9 9 9 8 8 7 7 4 4
chars 28

Decisions made during optimizing the score:

Boolean guard : is needed for early returns from a dfn {}. Either LF (\n) or a statement separator character ⋄ cannot be removed as a side effect.
I didn't try to avoid four letters RBQK as avoiding it requires at least ⎕A and the code would get messy.
Removed composition ∘, reflex/flip ⍨, and self ⊢ in favor of dfns and explicitly writing down arguments with parentheses.
Removed ≢ (tally) in favor of ⍴ (shape/reshape), as tally = first element of shape, and reshape is unavoidable.
Removed ⍉ (transpose) and ⌽ (reverse/rotate) in favor of explicit indexing [] combined with index generator ⍳. Although there are one-char functions to do the indexing (⌷, ⊃), none is suitable for transpose operation.
Removed ⊃ (first/pick) in favor of ↑ (mix/take), as take is unavoidable and indexing+mix can simulate both uses of ⊃.
Removed ∧ (logical and) in favor of × (times), and | (abs/mod) by using the workaround x∨-x for |x (abs) and explicit membership ∊ (which was removed later) for x|y (mod). ⊤ was also removed that way.
Removed ∘.f in favor of f⊂ or f¨⊂. Similar trick was used to simulate ∊ (membership) and ~ (set minus): x∊y → ∨/¨x=⊂y, x~y → (1-∨/¨x=⊂y)/x
Removed ⍸ (extract indices of ones) with the workaround (,x)/,⍳⍴x.
Removed zero with 1-1, four by extracting from ⍴⍵, and + with --.
Removing blanks in plain code is easy, but this code has ' '. I avoided it with 1↑'', which &quot;overtakes&quot; length 1 from an empty string and gives a single blank. (It is a slightly different thing from the literal ' ', but they are compatible in most cases.)

Ungolfed with comments
{
  ⍝ 4×4 boolean matrix where 1 means a white piece
  whites←⍵∊'RBKQ'
  ⍝ one matrix per a winning position; roughly looks like
  ⍝ 1 0 0 0 ... 1 1 1 1 ... 1 0 0 0
  ⍝ 1 0 0 0     0 0 0 0     0 1 0 0
  ⍝ 1 0 0 0     0 0 0 0     0 0 1 0
  ⍝ 1 0 0 0     0 0 0 0     0 0 0 1
  masks←((⊂,⊂∘⌽)∘.=⍨⍳4),(⊢,⍉¨)(⍳4)⌽¨⊂4 4⍴4↑1
  ⍝ 1 if the white is about to win in that specific winning position
  filter←3=masks{≢⍸⍺∧⍵}¨⊂whites
  ⍝ No three-in-a-row: return false
  ~∨/filter:0

  ⍝ fetch the mask closest to white's winning
  mask←(⍸filter)⊃masks
  ⍝ coordinates of misplaced piece (from) and empty position (to)
  from←⍸whites&gt;mask
  to←⍸whites&lt;mask
  ⍝ No from: the remaining place must be empty
  ~≢from:' '=⍵[to]

  ⍝ get the type of the piece to move
  type←'RBKQ'~⍵[⍸mask]
  ⍝ Knight: true if 1×2 steps away, ignoring any obstacles
  'K'=type:∧/1 2∊|⊃from-to
  ⍝ two booleans indicating if it can move in diagonals (BQ) or
  ⍝ cardinal directions (RQ)
  diag cross←0 2⊤⊃'RB'⍳type
  ⍝ two booleans indicating if the direction to move is actually
  ⍝ diagonal or cardinal
  isdiag←=/|⊃from-to
  iscross←0∊|⊃from-to
  ⍝ Not aligned with the piece to move: return false
  diag cross⍱.∧isdiag iscross:0
  ⍝ If aligned, true if all cells between from and to are blanks
  ∧/' '=¯1↓⍵[from+(×v)×⍳⌈/⊃|v←to-from]
}↑{⍞}¨⍳4  ⍝ Take 4 lines of input, format as matrix and pass to function