Here is my answer (this is OPTIMAL):

-- -- -- BQ BP -- WQ WP --
WQ BR WP BN WR BB BQ BP --
BQ BP WK WQ WP BR -- WR --
-- -- WR WP BR BQ BB WQ BP
BP BB BR -- WQ WR WP BK BQ
WP BQ WQ BP BN WB WR BR --
-- WP WB WR WN BP BR BQ WQ
-- WR BP BR BQ WQ WN -- WP
-- WQ BQ -- -- WP BP -- --
and the score is as stated above:
259.3
I have used
the CP-SAT solver simply.
| Question |
Short answer |
| Why I have chosen CP-SAT over other solvers? |
Pure 0-1 decision model + many “at-most-one” rules → CP-SAT’s native territory. It bundles SAT learning, CP filtering and MILP, giving more speed than generic MILP or handcrafted backtracking. |
| Why is it (usually) the best tool here? |
• Handles all constraints with single-line primitives (AddAtMostOne, etc.) • Exploits multi-core CPUs automatically • No licence cost, yet :D world-class performance on all-integer puzzles like 9×9 Chess-Sudoku. |
| How do we know a solution is optimal? |
The solver tracks two numbers: best solution and a proven upper bound. When they coincide it returns status OPTIMAL—a mathematical certificate that no better arrangement exists. |
| Key tricks under the hood |
Branch-and-bound, constraint propagation, SAT-style conflict (no-good) learning, and parallel search -> all working together to prune the search tree aggressively. |
Here is the python code, it takes 2 seconds to get the answer:
from ortools.sat.python import cp_model
def main():
n = 9
rows = range(n)
cols = range(n)
colors = ['W', 'B']
pieces = ['N', 'K', 'R', 'B', 'Q', 'P']
score = dict(N=27, K=0, R=50, B=33, Q=80, P=10) # ×10 for integers
lb = dict(N=2, K=1, R=2, B=2, Q=1, P=8)
ub = {p: 1 if p == 'K' else n * n for p in pieces}
m = cp_model.CpModel()
#------------------------------------------------------------------#
# Variables
#------------------------------------------------------------------#
V = {(c, p, i, j): m.NewBoolVar(f'{c}{p}_{i}_{j}')
for c in colors for p in pieces for i in rows for j in cols}
E = {(i, j): m.NewBoolVar(f'E_{i}_{j}') for i in rows for j in cols}
# Exactly one status per square
for i in rows:
for j in cols:
m.Add(sum(V[c, p, i, j] for c in colors for p in pieces) + E[i, j] == 1)
#------------------------------------------------------------------#
# Global piece-count bounds
#------------------------------------------------------------------#
for c in colors:
for p in pieces:
total = sum(V[c, p, i, j] for i in rows for j in cols)
m.Add(total >= lb[p])
m.Add(total <= ub[p])
#------------------------------------------------------------------#
# ≥ 1 empty square constraints
#------------------------------------------------------------------#
for i in rows: # row
m.Add(sum(E[i, j] for j in cols) >= 1)
for j in cols: # column
m.Add(sum(E[i, j] for i in rows) >= 1)
for bi in range(0, n, 3): # 3×3 box
for bj in range(0, n, 3):
m.Add(sum(E[i, j]
for i in range(bi, bi + 3)
for j in range(bj, bj + 3)) >= 1)
#------------------------------------------------------------------#
# ≥ 1 pawn of each colour per row, column, and box
#------------------------------------------------------------------#
for i in rows: # rows
m.Add(sum(V['W', 'P', i, j] for j in cols) >= 1)
m.Add(sum(V['B', 'P', i, j] for j in cols) >= 1)
for j in cols: # columns
m.Add(sum(V['W', 'P', i, j] for i in rows) >= 1)
m.Add(sum(V['B', 'P', i, j] for i in rows) >= 1)
for bi in range(0, n, 3): # 3×3 boxes
for bj in range(0, n, 3):
m.Add(sum(V['W', 'P', i, j]
for i in range(bi, bi + 3)
for j in range(bj, bj + 3)) >= 1)
m.Add(sum(V['B', 'P', i, j]
for i in range(bi, bi + 3)
for j in range(bj, bj + 3)) >= 1)
#------------------------------------------------------------------#
# ≥ 1 empty per diagonal
#------------------------------------------------------------------#
diags_pos = [[(i, j) for i in rows for j in cols if i + j == d]
for d in range(0, 2 * n - 1)]
diags_neg = [[(i, j) for i in rows for j in cols if i - j == d]
for d in range(1 - n, n)]
for diag in diags_pos + diags_neg:
m.Add(sum(E[i, j] for i, j in diag) >= 1)
#------------------------------------------------------------------#
# “At-most-one” rules for non-pawn pieces
#------------------------------------------------------------------#
def at_most_one(vars_): m.AddAtMostOne(vars_)
nobox = [p for p in pieces if p != 'P']
for c in colors:
for p in nobox:
for i in rows: # row
at_most_one([V[c, p, i, j] for j in cols])
for j in cols: # column
at_most_one([V[c, p, i, j] for i in rows])
for bi in range(0, n, 3): # box
for bj in range(0, n, 3):
at_most_one([V[c, p, i, j]
for i in range(bi, bi + 3)
for j in range(bj, bj + 3)])
# Bishop & queen diagonals (at-most-one)
for c in colors:
for p in ['B', 'Q']:
for diag in diags_pos + diags_neg:
at_most_one([V[c, p, i, j] for i, j in diag])
#------------------------------------------------------------------#
# Objective
#------------------------------------------------------------------#
m.Maximize(sum(score[p] * V[c, p, i, j]
for c in colors for p in pieces for i in rows for j in cols))
# Solve
solver = cp_model.CpSolver()
solver.parameters.num_search_workers = 8
status = solver.Solve(m)
#------------------------------------------------------------------#
# Output
#------------------------------------------------------------------#
board = [['--' for _ in cols] for _ in rows]
for (c, p, i, j), var in V.items():
if solver.BooleanValue(var):
board[i][j] = c + p
print('\nBOARD:')
for i in rows:
print(' '.join(board[i]))
print(f'\nTotal score = {solver.ObjectiveValue()/10:.1f}')
if status == cp_model.OPTIMAL:
print('Status: OPTIMAL → proven best.')
elif status == cp_model.FEASIBLE:
print('Status: FEASIBLE → good but not proven optimal.')
else:
print('Status:', solver.StatusName(status))
if __name__ == '__main__':
main()
Please note that this code deliberately omits check and check-mate detection to keep things simple; an answer above includes a version that does handle check-mate.
Feel free to use my game link below if you'd like to explore a better solution or verify its validity (assuming I haven’t made a mistake somewhere!) Let me know if I have.
Weighted Sudoku Chess Gameplay
- you can use text to get score and get errors
- you can use PC to play interactively (unfortunately not very friendly with phone)