Just thought I'd introduce myself.
I'm Abigail, I'm 16 from England and I am new to RPG Maker, but I've been programming for some time.
I'm Abigail, I'm 16 from England and I am new to RPG Maker, but I've been programming for some time.
This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.
1. Starting position: Win32API.new("Chess.dll", "reset", "", "V")
2. Does a move exist?: Win32API.new("Chess.dll", "move_exists", ['I','I'], "I")
3. Make a move: Win32API.new("Chess.dll", "do_move", ['I','I'], "I")
4. Take back move: Win32API.new("Chess.dll", "undo_move", "", "I")
5. Computer moves: Win32API.new("Chess.dll", "best_move", "", "L")
6. Get piece on given square (or empty): Win32API.new("Chess.dll", "get_square", "I", "I")
7. Get side to move: Win32API.new("Chess.dll", "side_to_move", "", "I")
@console = Win32API.new("Chess.dll", "console", "", "V")
#==============================================================================
# ** Scene_Chess
#------------------------------------------------------------------------------
# This class performs chess game UI and AI
#==============================================================================
class Scene_Chess < Scene_Base
#--------------------------------------------------------------------------
# * Constants
#--------------------------------------------------------------------------
WHITE = 0; BLACK = 1;
W_PAWN=0; W_ROOK=1; W_KNIGHT=2; W_BISHOP=3; W_QUEEN=4; W_KING=5;
B_PAWN=6; B_ROOK=7; B_KNIGHT=8; B_BISHOP=9; B_QUEEN=10; B_KING=11;
EMPTY = 12;
BOARD_SIZE = 480
SQ_SIZE = BOARD_SIZE/8
#--------------------------------------------------------------------------
# * Start Processing
#--------------------------------------------------------------------------
def start
super
setup_engine
setup_graphics
@new_game.call()
#@console.call()
refresh
end
#--------------------------------------------------------------------------
# * Setup Engine
#--------------------------------------------------------------------------
def setup_engine
@new_game = Win32API.new("Chess.dll", "reset", "", "V")
@move_exists = Win32API.new("Chess.dll", "move_exists", ['I','I'], "I")
@do_move = Win32API.new("Chess.dll", "do_move", ['I','I'], "I")
@undo_move = Win32API.new("Chess.dll", "undo_move", "", "I")
@best_move = Win32API.new("Chess.dll", "best_move", "", "L")
@get_square = Win32API.new("Chess.dll", "get_square", "I", "I")
@side_to_move = Win32API.new("Chess.dll", "side_to_move", "", "I")
@console = Win32API.new("Chess.dll", "console", "", "V")
end
#--------------------------------------------------------------------------
# * Setup Graphics
#--------------------------------------------------------------------------
def setup_graphics
Graphics.resize_screen(640, 480)
# Cursor
@cursor = 55
@cursor_spr = Sprite.new
@cursor_spr.z = 50
@cursor_spr.opacity = 200
@cursor_spr.bitmap = Bitmap.new(SQ_SIZE, SQ_SIZE)
@cursor_spr.bitmap.fill_rect(0, 0, SQ_SIZE, SQ_SIZE, Color.new(255,255,100))
# From (blue indicating which piece has been selected)
@from = -1
@from_spr = Sprite.new
@from_spr.visible = false
@from_spr.z = 50
@from_spr.opacity = 255
@from_spr.bitmap = Bitmap.new(SQ_SIZE, SQ_SIZE)
@from_spr.bitmap.fill_rect(0, 0, SQ_SIZE, SQ_SIZE, Color.new(50,100,255))
# Board grid bitmap
@board_spr = Sprite.new
@board_spr.bitmap = Bitmap.new(BOARD_SIZE, BOARD_SIZE)
i = 0;
while(i < 64)
odd = (i/8+i%8) % 2
odd = 1 - odd;
x = SQ_SIZE * (i % 8)
y = SQ_SIZE * (i / 8)
color = Color.new(100+155*odd, 140+115*odd, 140+115*odd)
@board_spr.bitmap.fill_rect(x, y, SQ_SIZE, SQ_SIZE, color);
i+=1;
end
# Pieces bitmap
@piece_bitmap = Bitmap.new("pieces.png")
# Pieces sprite
@piece_sprite = Sprite.new()
@piece_sprite.x = 0; @piece_sprite.y = 0;
@piece_sprite.z = 100;
@piece_sprite.bitmap = Bitmap.new(BOARD_SIZE, BOARD_SIZE)
end
#--------------------------------------------------------------------------
# * Update
#--------------------------------------------------------------------------
def update
super
# Enter pressed
if(Input.trigger?(Input::C))
move_is_legal = move_exists?(@from, @cursor)
if(move_is_legal || !square_selectable?)
if(move_is_legal)
# Player move
do_move(@from, @cursor)
refresh
Graphics.update
# Computer move
best_move
refresh
else
@from = -1;
@from_spr.visible = false;
end
else #square holds your piece
@from = @cursor
@from_spr.x = SQ_SIZE * (@from % 8)
@from_spr.y = SQ_SIZE * (@from / 8)
@from_spr.visible = true;
end
end
# Undo pressed
if(Input.trigger?(Input::B))
@undo_move.call()
@undo_move.call()
refresh
Graphics.update
end
# Move cursor
@cursor -= 1 if(Input.trigger?(Input::LEFT))
@cursor += 1 if(Input.trigger?(Input::RIGHT))
@cursor -= 8 if(Input.trigger?(Input::UP))
@cursor += 8 if(Input.trigger?(Input::DOWN))
@cursor_spr.x = SQ_SIZE * (@cursor % 8)
@cursor_spr.y = SQ_SIZE * (@cursor / 8)
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
@piece_sprite.bitmap.clear
i = 0
while(i < 64)
pce_id = @get_square.call(i)
if(pce_id != EMPTY)
x = SQ_SIZE * (i % 8)
y = SQ_SIZE * (i / 8)
col = pce_id > W_KING ? 1 : 0
pce = pce_id - (col * B_PAWN)
source = Rect.new(pce*60, col*60, 60, 60)
@piece_sprite.bitmap.blt(x, y, @piece_bitmap, source);
end
i += 1
end
end
#--------------------------------------------------------------------------
# * Do Move
#--------------------------------------------------------------------------
def do_move(from, to)
@do_move.call(from, to)
@from_spr.visible = true
@from_spr.x = (to % 8) * SQ_SIZE;
@from_spr.y = (to / 8) * SQ_SIZE;
end
#--------------------------------------------------------------------------
# * Do Best Move
#--------------------------------------------------------------------------
def best_move()
best_move = @best_move.call
# From and To are stored in bits
from = 63 & (best_move >> 6);
to = 63 & best_move;
do_move(from, to)
end
#--------------------------------------------------------------------------
# * Move Exists
#--------------------------------------------------------------------------
def move_exists?(from, to)
result = @move_exists.call(from, to)
return result == 1
end
#--------------------------------------------------------------------------
# * Square is Selectable
#--------------------------------------------------------------------------
def square_selectable?
if(@get_square.call(@cursor) == EMPTY)
return false
elsif(@get_square.call(@cursor) <= W_KING && @side_to_move.call() == WHITE)
return true
elsif(@get_square.call(@cursor) >= B_PAWN && @side_to_move.call() == BLACK)
return true
else
return false
end
end
end
module Chess
#--------------------------------------------------------------------------
# * Color
#--------------------------------------------------------------------------
WHITE = true
BLACK = false
#--------------------------------------------------------------------------
# * Pieces
#--------------------------------------------------------------------------
W_PAWN = 0
W_ROOK = 1
W_KNIGHT = 2
W_BISHOP = 3
W_QUEEN = 4
W_KING = 5
B_PAWN = 6
B_ROOK = 7
B_KNIGHT = 8
B_BISHOP = 9
B_QUEEN = 10
B_KING = 11
NO_PIECE = 12
OFF_BOARD = -2;
#--------------------------------------------------------------------------
# * Squares
#--------------------------------------------------------------------------
A8 = 21; B8 = 22; C8 = 23; D8 = 24; E8 = 25; F8 = 26; G8 = 27; H8 = 28;
A7 = 31; B7 = 32; C7 = 33; D7 = 34; E7 = 35; F7 = 36; G7 = 37; H7 = 38;
A6 = 41; B6 = 42; C6 = 43; D6 = 44; E6 = 45; F6 = 46; G6 = 47; H6 = 48;
A5 = 51; B5 = 52; C5 = 53; D5 = 54; E5 = 55; F5 = 56; G5 = 57; H5 = 58;
A4 = 61; B4 = 62; C4 = 63; D4 = 64; E4 = 65; F4 = 66; G4 = 67; H4 = 68;
A3 = 71; B3 = 72; C3 = 73; D3 = 74; E3 = 75; F3 = 76; G3 = 77; H3 = 78;
A2 = 81; B2 = 82; C2 = 83; D2 = 84; E2 = 85; F2 = 86; G2 = 87; H2 = 88;
A1 = 91; B1 = 92; C1 = 93; D1 = 94; E1 = 95; F1 = 96; G1 = 97; H1 = 98;
NO_SQUARE = -1;
#--------------------------------------------------------------------------
# * Ranks
#--------------------------------------------------------------------------
RANK_1 = 8; RANK_2 = 7; RANK_3 = 6; RANK_4 = 5;
RANK_5 = 4; RANK_6 = 3; RANK_7 = 2; RANK_8 = 1;
#--------------------------------------------------------------------------
# * Files
#--------------------------------------------------------------------------
FILE_A = 1; FILE_B = 2; FILE_C = 3; FILE_D = 4;
FILE_E = 5; FILE_F = 6; FILE_G = 7; FILE_H = 8;
#--------------------------------------------------------------------------
# * Strings
#--------------------------------------------------------------------------
SFILES = []
SFILES[FILE_A] = "a"; SFILES[FILE_B] = "b"; SFILES[FILE_C] = "c";
SFILES[FILE_D] = "d"; SFILES[FILE_E] = "e"; SFILES[FILE_F] = "f";
SFILES[FILE_G] = "g"; SFILES[FILE_H] = "h";
#--------------------------------------------------------------------------
# * Values
#--------------------------------------------------------------------------
PVALUE = []
PVALUE[NO_PIECE] = 0
PVALUE[W_PAWN] = 100
PVALUE[W_KNIGHT] = 300
PVALUE[W_BISHOP] = 300
PVALUE[W_ROOK] = 600
PVALUE[W_QUEEN] = 900
PVALUE[W_KING] = 0
PVALUE[B_PAWN] = -100
PVALUE[B_KNIGHT] = -300
PVALUE[B_BISHOP] = -300
PVALUE[B_ROOK] = -600
PVALUE[B_QUEEN] = -900
PVALUE[B_KING] = 0
DRAW = 0
CHECKMATE = 1000
INFINITY = CHECKMATE + 1
end
class Chess_MoveGeneration
#--------------------------------------------------------------------------
# * Move exists?
#--------------------------------------------------------------------------
def move_exists(pos, move)
legalMoves = []
legalMoves += generateCapture(pos)
legalMoves += generateQuiet(pos)
legalMoves.each_index do |i|
if(legalMoves[i][0] == move[0] && legalMoves[i][1] == move[1])
return true
end
end
return false
end
#--------------------------------------------------------------------------
# * Generate quiet moves
#--------------------------------------------------------------------------
def generateQuiet(pos)
moves = []
i = -1
while(i < 120)
i += 1
p = pos.board[i]
next if(p == nil || p == Chess::OFF_BOARD || p == Chess::NO_PIECE)
color = (p <= Chess::W_KING) ? Chess::WHITE : Chess::BLACK
next if(color != pos.side_to_move)
is_rook = (p == Chess::W_ROOK || p == Chess::B_ROOK)
is_knight = (p == Chess::W_KNIGHT || p == Chess::B_KNIGHT)
is_bishop = (p == Chess::W_BISHOP || p == Chess::B_BISHOP)
is_queen = (p == Chess::W_QUEEN || p == Chess::B_QUEEN)
is_king = (p == Chess::W_KING || p == Chess::B_KING)
#
# Pawns
#
if(p == Chess::W_PAWN)
if(pos.board[i - 10] == Chess::NO_PIECE)
moves.push([i, i - 10])
if(i >= Chess::A2 && pos.board[i - 20] == Chess::NO_PIECE)
moves.push([i, i - 20])
end
end
end
if(p == Chess::B_PAWN)
if(pos.board[i + 10] == Chess::NO_PIECE)
moves.push([i, i + 10])
if(i <= Chess::H7 && pos.board[i + 20] == Chess::NO_PIECE)
moves.push([i, i + 20])
end
end
end
#
# Knight movement
#
if(is_knight)
moves.push([i, i+21]) if(pos.board[i+21] == Chess::NO_PIECE)
moves.push([i, i+19]) if(pos.board[i+19] == Chess::NO_PIECE)
moves.push([i, i+12]) if(pos.board[i+12] == Chess::NO_PIECE)
moves.push([i, i+8]) if(pos.board[i+8] == Chess::NO_PIECE)
moves.push([i, i-21]) if(pos.board[i-21] == Chess::NO_PIECE)
moves.push([i, i-19]) if(pos.board[i-19] == Chess::NO_PIECE)
moves.push([i, i-12]) if(pos.board[i-12] == Chess::NO_PIECE)
moves.push([i, i-8]) if(pos.board[i-8] == Chess::NO_PIECE)
end
#
# Linear movement
#
if(is_rook || is_queen)
j = 1
while(pos.board[i + j] == Chess::NO_PIECE)
moves.push([i, i+j])
j += 1
end
j = 1
while(pos.board[i - j] == Chess::NO_PIECE)
moves.push([i, i-j])
j += 1
end
j = 1
while(pos.board[i + j*10] == Chess::NO_PIECE)
moves.push([i, i+j*10])
j += 1
end
j = 1
while(pos.board[i - j*10] == Chess::NO_PIECE)
moves.push([i, i-j*10])
j += 1
end
end
#
# Diagonal movement
#
if(is_bishop || is_queen)
j = 1
while(pos.board[i + j*10 + j] == Chess::NO_PIECE)
moves.push([i, i+j*10 + j])
j += 1
end
j = 1
while(pos.board[i - j*10 + j] == Chess::NO_PIECE)
moves.push([i, i-j*10 + j])
j += 1
end
j = 1
while(pos.board[i + j*10 - j] == Chess::NO_PIECE)
moves.push([i, i+j*10 - j])
j += 1
end
j = 1
while(pos.board[i - j*10 - j] == Chess::NO_PIECE)
moves.push([i, i-j*10 - j])
j += 1
end
end
#
# King movement
#
if(is_king)
moves.push([i, i+1]) if(pos.board[i+1] == Chess::NO_PIECE)
moves.push([i, i-1]) if(pos.board[i-1] == Chess::NO_PIECE)
moves.push([i, i+10]) if(pos.board[i+10] == Chess::NO_PIECE)
moves.push([i, i-10]) if(pos.board[i-10] == Chess::NO_PIECE)
moves.push([i, i+11]) if(pos.board[i+11] == Chess::NO_PIECE)
moves.push([i, i-11]) if(pos.board[i-11] == Chess::NO_PIECE)
moves.push([i, i+9]) if(pos.board[i+9] == Chess::NO_PIECE)
moves.push([i, i-9]) if(pos.board[i-9] == Chess::NO_PIECE)
end
end
return moves
end
#--------------------------------------------------------------------------
# * Generate capture moves
#--------------------------------------------------------------------------
def generateCapture(pos)
moves = []
i = -1
while(i < 120)
i += 1
p = pos.board[i]
next if(p == nil || p == Chess::OFF_BOARD || p == Chess::NO_PIECE)
color = (p <= Chess::W_KING) ? Chess::WHITE : Chess::BLACK
next if(color != pos.side_to_move)
#
# Pawns
#
if(p == Chess::W_PAWN)
moves.push([i, i - 11]) if pos.is_black(pos.board[i - 11])
moves.push([i, i - 9]) if pos.is_black(pos.board[i - 9])
end
if(p == Chess::B_PAWN)
moves.push([i, i + 11]) if pos.is_white(pos.board[i + 11])
moves.push([i, i + 9]) if pos.is_white(pos.board[i + 9])
end
#
# Knight movement
#
if(p == Chess::W_KNIGHT)
moves.push([i, i+21]) if pos.is_black(pos.board[i+21])
moves.push([i, i+19]) if pos.is_black(pos.board[i+19])
moves.push([i, i+12]) if pos.is_black(pos.board[i+12])
moves.push([i, i+8]) if pos.is_black(pos.board[i+8])
moves.push([i, i-21]) if pos.is_black(pos.board[i-21])
moves.push([i, i-19]) if pos.is_black(pos.board[i-19])
moves.push([i, i-12]) if pos.is_black(pos.board[i-12])
moves.push([i, i-8]) if pos.is_black(pos.board[i-8])
end
if(p == Chess::B_KNIGHT)
moves.push([i, i+21]) if pos.is_white(pos.board[i+21])
moves.push([i, i+19]) if pos.is_white(pos.board[i+19])
moves.push([i, i+12]) if pos.is_white(pos.board[i+12])
moves.push([i, i+8]) if pos.is_white(pos.board[i+8])
moves.push([i, i-21]) if pos.is_white(pos.board[i-21])
moves.push([i, i-19]) if pos.is_white(pos.board[i-19])
moves.push([i, i-12]) if pos.is_white(pos.board[i-12])
moves.push([i, i-8]) if pos.is_white(pos.board[i-8])
end
#
# Linear movement
#
if(p == Chess::W_ROOK || p == Chess::W_QUEEN)
j = 1
j += 1 while(pos.board[i + j] == Chess::NO_PIECE)
moves.push([i, i+j]) if pos.is_black(pos.board[i + j])
j = 1
j += 1 while(pos.board[i - j] == Chess::NO_PIECE)
moves.push([i, i-j]) if pos.is_black(pos.board[i - j])
j = 1
j += 1 while(pos.board[i + j*10] == Chess::NO_PIECE)
moves.push([i, i+j*10]) if pos.is_black(pos.board[i + j*10])
j = 1
j += 1 while(pos.board[i - j*10] == Chess::NO_PIECE)
moves.push([i, i-j*10]) if pos.is_black(pos.board[i - j*10])
end
if(p == Chess::B_ROOK || p == Chess::B_QUEEN)
j = 1
j += 1 while(pos.board[i + j] == Chess::NO_PIECE)
moves.push([i, i+j]) if pos.is_white(pos.board[i + j])
j = 1
j += 1 while(pos.board[i - j] == Chess::NO_PIECE)
moves.push([i, i-j]) if pos.is_white(pos.board[i - j])
j = 1
j += 1 while(pos.board[i + j*10] == Chess::NO_PIECE)
moves.push([i, i+j*10]) if pos.is_white(pos.board[i + j*10])
j = 1
j += 1 while(pos.board[i - j*10] == Chess::NO_PIECE)
moves.push([i, i-j*10]) if pos.is_white(pos.board[i - j*10])
end
#
# Diagonal movement
#
if(p == Chess::W_BISHOP || p == Chess::W_QUEEN)
j = 1
j += 1 while(pos.board[i + j*10 + j] == Chess::NO_PIECE)
moves.push([i, i+j*10+j]) if pos.is_black(pos.board[i + j*10+j])
j = 1
j += 1 while(pos.board[i - j*10+j] == Chess::NO_PIECE)
moves.push([i, i-j*10+j]) if pos.is_black(pos.board[i - j*10+j])
j = 1
j += 1 while(pos.board[i + j*10-j] == Chess::NO_PIECE)
moves.push([i, i+j*10-j]) if pos.is_black(pos.board[i + j*10-j])
j = 1
j += 1 while(pos.board[i - j*10-j] == Chess::NO_PIECE)
moves.push([i, i-j*10-j]) if pos.is_black(pos.board[i - j*10-j])
end
if(p == Chess::B_BISHOP || p == Chess::B_QUEEN)
j = 1
j += 1 while(pos.board[i + j*10 + j] == Chess::NO_PIECE)
moves.push([i, i+j*10+j]) if pos.is_white(pos.board[i + j*10+j])
j = 1
j += 1 while(pos.board[i - j*10+j] == Chess::NO_PIECE)
moves.push([i, i-j*10+j]) if pos.is_white(pos.board[i - j*10+j])
j = 1
j += 1 while(pos.board[i + j*10-j] == Chess::NO_PIECE)
moves.push([i, i+j*10-j]) if pos.is_white(pos.board[i + j*10-j])
j = 1
j += 1 while(pos.board[i - j*10-j] == Chess::NO_PIECE)
moves.push([i, i-j*10-j]) if pos.is_white(pos.board[i - j*10-j])
end
#
# King movement
#
if(p == Chess::W_KING)
moves.push([i, i+1]) if pos.is_black(pos.board[i+1])
moves.push([i, i-1]) if pos.is_black(pos.board[i-1])
moves.push([i, i+10]) if pos.is_black(pos.board[i+10])
moves.push([i, i-10]) if pos.is_black(pos.board[i-10])
moves.push([i, i+11]) if pos.is_black(pos.board[i+11])
moves.push([i, i-11]) if pos.is_black(pos.board[i-11])
moves.push([i, i+9]) if pos.is_black(pos.board[i+9])
moves.push([i, i-9]) if pos.is_black(pos.board[i-9])
end
if(p == Chess::B_KING)
moves.push([i, i+1]) if pos.is_white(pos.board[i+1])
moves.push([i, i-1]) if pos.is_white(pos.board[i-1])
moves.push([i, i+10]) if pos.is_white(pos.board[i+10])
moves.push([i, i-10]) if pos.is_white(pos.board[i-10])
moves.push([i, i+11]) if pos.is_white(pos.board[i+11])
moves.push([i, i-11]) if pos.is_white(pos.board[i-11])
moves.push([i, i+9]) if pos.is_white(pos.board[i+9])
moves.push([i, i-9]) if pos.is_white(pos.board[i-9])
end
end
return moves
end
end
class Chess_Search
attr_reader :best_move
#--------------------------------------------------------------------------
# * Search
#--------------------------------------------------------------------------
def search(pos)
@move_gen = Chess_MoveGeneration.new
@best_move = [Chess::NO_SQUARE, Chess::NO_SQUARE]
negamax(pos, 4, -Chess::INFINITY, Chess::INFINITY)
end
#--------------------------------------------------------------------------
# * NegaMax
#--------------------------------------------------------------------------
def negamax(pos, depth, alpha, beta)
# Leaf Node
if(depth == 0)
if(pos.side_to_move == Chess::WHITE)
return pos.score
elsif(pos.side_to_move == Chess::BLACK)
return -pos.score
end
end
# Generate legal moves
moves = []
moves += @move_gen.generateCapture(pos)
moves += @move_gen.generateQuiet(pos)
if(moves.length == 0)
return Chess::DRAW
end
# Browse legal moves
moves.each_index do |i|
pos.make_move( moves[i] )
score = -negamax(pos, depth - 1, -beta, -alpha)
pos.unmake_move()
if(score >= beta)
return beta
end
if(score > alpha)
alpha = score
if(depth == 4)
@best_move = moves[i]
end
end
end
return alpha
end
end
class Chess_Position
#--------------------------------------------------------------------------
# * Public Variables
#--------------------------------------------------------------------------
attr_accessor :board
attr_reader :side_to_move
attr_reader :score
#--------------------------------------------------------------------------
# * Start
#--------------------------------------------------------------------------
def initialize
@side_to_move = Chess::WHITE
@board = []
@score = 0
@history = []
@history_capture = []
starting_position
end
#--------------------------------------------------------------------------
# * Start
#--------------------------------------------------------------------------
def clear
@score = 0
# 120
i = 0
while(i < 120)
@board[i] = Chess::OFF_BOARD
i += 1
end
# Real 64 board
i = 0
while(i < 64)
@board[sq120(i)] = Chess::NO_PIECE
i += 1
end
end
#--------------------------------------------------------------------------
# * Move
#--------------------------------------------------------------------------
def make_move(move)
# Update game score
@score -= Chess::PVALUE[@board[move[1]]]
# Record history
@history.push(move)
@history_capture.push(@board[move[1]])
# Move piece
@board[move[1]] = @board[move[0]]
@board[move[0]] = Chess::NO_PIECE
@side_to_move = !@side_to_move
end
#--------------------------------------------------------------------------
# * Undo Move
#--------------------------------------------------------------------------
def unmake_move()
move = @history.pop
captured = @history_capture.pop
# Refactor game score
@score += Chess::PVALUE[captured]
# Move back piece
@board[move[0]] = @board[move[1]]
@board[move[1]] = captured
@side_to_move = !@side_to_move
end
#--------------------------------------------------------------------------
# * Color
#--------------------------------------------------------------------------
def is_white(piece)
(piece >= Chess::W_PAWN && piece <= Chess::W_KING)
end
def is_black(piece)
(piece >= Chess::B_PAWN && piece <= Chess::B_KING)
end
#--------------------------------------------------------------------------
# * Square 64 => 120
#--------------------------------------------------------------------------
def sq120(s)
x = (s % 8)
y = (s / 8)
21 + y * 10 + x
end
#--------------------------------------------------------------------------
# * Square 120 => 64
#--------------------------------------------------------------------------
def sq64(s)
s -= 21;
x = (s % 10)
y = (s / 10)
y * 8 + x
end
#--------------------------------------------------------------------------
# * Starting position
#--------------------------------------------------------------------------
def starting_position
clear
# White
@board[Chess::A1] = Chess::W_ROOK
@board[Chess::B1] = Chess::W_KNIGHT
@board[Chess::C1] = Chess::W_BISHOP
@board[Chess::D1] = Chess::W_QUEEN
@board[Chess::E1] = Chess::W_KING
@board[Chess::F1] = Chess::W_BISHOP
@board[Chess::G1] = Chess::W_KNIGHT
@board[Chess::H1] = Chess::W_ROOK
@board[Chess::A2] = Chess::W_PAWN
@board[Chess::B2] = Chess::W_PAWN
@board[Chess::C2] = Chess::W_PAWN
@board[Chess::D2] = Chess::W_PAWN
@board[Chess::E2] = Chess::W_PAWN
@board[Chess::F2] = Chess::W_PAWN
@board[Chess::G2] = Chess::W_PAWN
@board[Chess::H2] = Chess::W_PAWN
# Black
@board[Chess::A8] = Chess::B_ROOK
@board[Chess::B8] = Chess::B_KNIGHT
@board[Chess::C8] = Chess::B_BISHOP
@board[Chess::D8] = Chess::B_QUEEN
@board[Chess::E8] = Chess::B_KING
@board[Chess::F8] = Chess::B_BISHOP
@board[Chess::G8] = Chess::B_KNIGHT
@board[Chess::H8] = Chess::B_ROOK
@board[Chess::A7] = Chess::B_PAWN
@board[Chess::B7] = Chess::B_PAWN
@board[Chess::C7] = Chess::B_PAWN
@board[Chess::D7] = Chess::B_PAWN
@board[Chess::E7] = Chess::B_PAWN
@board[Chess::F7] = Chess::B_PAWN
@board[Chess::G7] = Chess::B_PAWN
@board[Chess::H7] = Chess::B_PAWN
end
end
#==============================================================================
# ** Scene_Chess
#------------------------------------------------------------------------------
# This class performs chess game UI and AI
#==============================================================================
class Scene_Chess < Scene_Base
#--------------------------------------------------------------------------
# * Start Processing
#--------------------------------------------------------------------------
def start
super
@position = Chess_Position.new
@move_gen = Chess_MoveGeneration.new
@search = Chess_Search.new
@selected_square = @position.sq64(Chess::E2)
@from_square = Chess::NO_SQUARE
load_piece_sprite
create_chessboard_sprite
create_piece_sprite
redraw_pieces
end
#--------------------------------------------------------------------------
# * Make move
#--------------------------------------------------------------------------
def make_move(from, to)
from = @position.sq120(from)
to = @position.sq120(to)
move = [from, to]
move_legal = @move_gen.move_exists(@position, move)
if(move_legal)
# Make player move
@position.make_move(move)
redraw_pieces
# Pick computer move
@search.search(@position)
# Make move
@position.make_move(@search.best_move)
redraw_pieces
dx = (@position.sq64(@search.best_move[1]) % 8)
dy = (@position.sq64(@search.best_move[1]) / 8)
@last_move_sprite.x = dx * @square_size + @board_padding
@last_move_sprite.y = dy * @square_size
@last_move_sprite.visible = true
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Move cursor
if(Input.trigger?(:UP))
@selected_square -= 8
elsif(Input.trigger?(:RIGHT))
@selected_square += 1
elsif(Input.trigger?(:LEFT))
@selected_square -= 1
elsif(Input.trigger?(:DOWN))
@selected_square += 8
end
@selected_square = 0 if(@selected_square < 0)
@selected_square = 63 if(@selected_square > 63)
# Enter
if(Input.trigger?(:C))
if(@from_square != Chess::NO_SQUARE)
make_move(@from_square, @selected_square)
@from_square = Chess::NO_SQUARE
else
@from_square = @selected_square
end
end
# Position sprite
@cursor_sprite.x = @square_size * (@selected_square % 8) + @board_padding
@cursor_sprite.y = @square_size * (@selected_square / 8)
@from_sprite.x = @square_size * (@from_square % 8) + @board_padding
@from_sprite.y = @square_size * (@from_square / 8)
super
end
#--------------------------------------------------------------------------
# * create_piece_sprite
#--------------------------------------------------------------------------
def create_piece_sprite
@piece_sprite = Sprite.new
@piece_sprite.x = @board_padding
@piece_sprite.y = 0
@piece_sprite.z = 150
@piece_sprite.bitmap = Bitmap.new(@board_size, @board_size)
end
#--------------------------------------------------------------------------
# * Redraw piece
#--------------------------------------------------------------------------
def redraw_pieces
@piece_sprite.bitmap.clear
x = 0; y = 0;
while(y < 8)
while(x < 8)
square64 = y * 8 + x
square120 = @position.sq120(square64)
piece = @position.board[square120]
if(piece != Chess::NO_PIECE)
dx = @square_size * x
dy = @square_size * y
rect = Rect.new(0, 0, @board_size, @board_size)
@piece_sprite.bitmap.blt(dx, dy, @piece_bitmaps[piece], rect)
end
x += 1
end
x = 0
y += 1
end
end
#--------------------------------------------------------------------------
# * Load Piece Sprite
#--------------------------------------------------------------------------
def load_piece_sprite
@piece_bitmaps = []
@piece_bitmaps[Chess::W_PAWN] = Bitmap.new("ChessPieces/white_pawn.png")
@piece_bitmaps[Chess::W_ROOK] = Bitmap.new("ChessPieces/white_rook.png")
@piece_bitmaps[Chess::W_KNIGHT] = Bitmap.new("ChessPieces/white_knight.png")
@piece_bitmaps[Chess::W_BISHOP] = Bitmap.new("ChessPieces/white_bishop.png")
@piece_bitmaps[Chess::W_QUEEN] = Bitmap.new("ChessPieces/white_queen.png")
@piece_bitmaps[Chess::W_KING] = Bitmap.new("ChessPieces/white_king.png")
@piece_bitmaps[Chess::B_PAWN] = Bitmap.new("ChessPieces/black_pawn.png")
@piece_bitmaps[Chess::B_ROOK] = Bitmap.new("ChessPieces/black_rook.png")
@piece_bitmaps[Chess::B_KNIGHT] = Bitmap.new("ChessPieces/black_knight.png")
@piece_bitmaps[Chess::B_BISHOP] = Bitmap.new("ChessPieces/black_bishop.png")
@piece_bitmaps[Chess::B_QUEEN] = Bitmap.new("ChessPieces/black_queen.png")
@piece_bitmaps[Chess::B_KING] = Bitmap.new("ChessPieces/black_king.png")
end
#--------------------------------------------------------------------------
# * Create chessboard sprite
#--------------------------------------------------------------------------
def create_chessboard_sprite
Graphics.resize_screen(640, 480)
# Size constants
@board_size = 480
@board_padding = (640 - @board_size) / 2
@square_size = @board_size / 8
# Create board sprite
@board_gfx = Sprite.new
@board_gfx.z = 10
@board_gfx.x = @board_padding
@board_gfx.bitmap = Bitmap.new(@board_size, @board_size)
y = 0
while(y < 8)
x = 0
while(x < 8)
x2 = x * @square_size
y2 = y * @square_size
if((x + y) % 2 == 0)
col = Color.new(255, 255, 255)
else
col = Color.new(80, 30, 0)
end
@board_gfx.bitmap.fill_rect(x2, y2, @square_size, @square_size, col)
x += 1
end
y += 1
end
# Create square cursor sprite
@cursor_sprite = Sprite.new
@cursor_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@cursor_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(255, 255, 100))
@cursor_sprite.z = 50
# Create from_square sprite
@from_sprite = Sprite.new
@from_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@from_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(100, 255, 100))
@from_sprite.z = 51
# Create last_move_to sprite
@last_move_sprite = Sprite.new
@last_move_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@last_move_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(200, 200, 100))
@last_move_sprite.z = 51
@last_move_sprite.visible = false
end
#--------------------------------------------------------------------------
# * Termination Processing
#--------------------------------------------------------------------------
def terminate
super
end
end
#==============================================================================
# ** Scene_Chess
#------------------------------------------------------------------------------
# This class performs chess game UI and AI
#==============================================================================
class Scene_Chess < Scene_Base
#--------------------------------------------------------------------------
# * Start Processing
#--------------------------------------------------------------------------
def start
super
Graphics.resize_screen(640, 480)
@position = Chess_Position.new
@move_gen = Chess_MoveGeneration.new
@search = Chess_Search.new
@selected_square = @position.sq64(Chess::E2)
@from_square = Chess::NO_SQUARE
load_piece_sprite
create_chessboard_sprite
create_piece_sprite
redraw_pieces
end
#--------------------------------------------------------------------------
# * Make move
#--------------------------------------------------------------------------
def make_move(from, to)
from = @position.sq120(from)
to = @position.sq120(to)
move = [from, to]
move_legal = @move_gen.move_exists(@position, move)
if(move_legal)
# Make player move
@position.make_move(move)
redraw_pieces
# Pick computer move
@search.search(@position)
# Make move
@position.make_move(@search.best_move)
redraw_pieces
dx = (@position.sq64(@search.best_move[1]) % 8)
dy = (@position.sq64(@search.best_move[1]) / 8)
@last_move_sprite.x = dx * @square_size + @board_padding
@last_move_sprite.y = dy * @square_size
@last_move_sprite.visible = true
end
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Move cursor
if(Input.trigger?(Input::UP))
@selected_square -= 8
elsif(Input.trigger?(Input::RIGHT))
@selected_square += 1
elsif(Input.trigger?(Input::LEFT))
@selected_square -= 1
elsif(Input.trigger?(Input::DOWN))
@selected_square += 8
end
@selected_square = 0 if(@selected_square < 0)
@selected_square = 63 if(@selected_square > 63)
# Enter
if(Input.trigger?(Input::C))
if(@from_square != Chess::NO_SQUARE)
make_move(@from_square, @selected_square)
@from_square = Chess::NO_SQUARE
else
@from_square = @selected_square
end
end
# Position sprite
@cursor_sprite.x = @square_size * (@selected_square % 8) + @board_padding
@cursor_sprite.y = @square_size * (@selected_square / 8)
@from_sprite.x = @square_size * (@from_square % 8) + @board_padding
@from_sprite.y = @square_size * (@from_square / 8)
end
#--------------------------------------------------------------------------
# * create_piece_sprite
#--------------------------------------------------------------------------
def create_piece_sprite
@piece_sprite = Sprite.new
@piece_sprite.x = @board_padding
@piece_sprite.y = 0
@piece_sprite.z = 150
@piece_sprite.bitmap = Bitmap.new(@board_size, @board_size)
end
#--------------------------------------------------------------------------
# * Redraw piece
#--------------------------------------------------------------------------
def redraw_pieces
@piece_sprite.bitmap.clear
x = 0; y = 0;
while(y < 8)
while(x < 8)
square64 = y * 8 + x
square120 = @position.sq120(square64)
piece = @position.board[square120]
if(piece != Chess::NO_PIECE)
dx = @square_size * x
dy = @square_size * y
rect = Rect.new(0, 0, @board_size, @board_size)
@piece_sprite.bitmap.blt(dx, dy, @piece_bitmaps[piece], rect)
end
x += 1
end
x = 0
y += 1
end
end
#--------------------------------------------------------------------------
# * Load Piece Sprite
#--------------------------------------------------------------------------
def load_piece_sprite
@piece_bitmaps = []
@piece_bitmaps[Chess::W_PAWN] = Bitmap.new("ChessPieces/white_pawn.png")
@piece_bitmaps[Chess::W_ROOK] = Bitmap.new("ChessPieces/white_rook.png")
@piece_bitmaps[Chess::W_KNIGHT] = Bitmap.new("ChessPieces/white_knight.png")
@piece_bitmaps[Chess::W_BISHOP] = Bitmap.new("ChessPieces/white_bishop.png")
@piece_bitmaps[Chess::W_QUEEN] = Bitmap.new("ChessPieces/white_queen.png")
@piece_bitmaps[Chess::W_KING] = Bitmap.new("ChessPieces/white_king.png")
@piece_bitmaps[Chess::B_PAWN] = Bitmap.new("ChessPieces/black_pawn.png")
@piece_bitmaps[Chess::B_ROOK] = Bitmap.new("ChessPieces/black_rook.png")
@piece_bitmaps[Chess::B_KNIGHT] = Bitmap.new("ChessPieces/black_knight.png")
@piece_bitmaps[Chess::B_BISHOP] = Bitmap.new("ChessPieces/black_bishop.png")
@piece_bitmaps[Chess::B_QUEEN] = Bitmap.new("ChessPieces/black_queen.png")
@piece_bitmaps[Chess::B_KING] = Bitmap.new("ChessPieces/black_king.png")
end
#--------------------------------------------------------------------------
# * Create chessboard sprite
#--------------------------------------------------------------------------
def create_chessboard_sprite
# Size constants
@board_size = 480
@board_padding = (640 - @board_size) / 2
@square_size = @board_size / 8
# Create board sprite
@board_gfx = Sprite.new
@board_gfx.z = 10
@board_gfx.x = @board_padding
@board_gfx.bitmap = Bitmap.new(@board_size, @board_size)
y = 0
while(y < 8)
x = 0
while(x < 8)
x2 = x * @square_size
y2 = y * @square_size
if((x + y) % 2 == 0)
col = Color.new(255, 255, 255)
else
col = Color.new(80, 30, 0)
end
@board_gfx.bitmap.fill_rect(x2, y2, @square_size, @square_size, col)
x += 1
end
y += 1
end
# Create square cursor sprite
@cursor_sprite = Sprite.new
@cursor_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@cursor_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(255, 255, 100))
@cursor_sprite.z = 50
# Create from_square sprite
@from_sprite = Sprite.new
@from_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@from_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(100, 255, 100))
@from_sprite.z = 51
# Create last_move_to sprite
@last_move_sprite = Sprite.new
@last_move_sprite.bitmap = Bitmap.new(@square_size, @square_size)
@last_move_sprite.bitmap.fill_rect(0, 0, 640, 480, Color.new(200, 200, 100))
@last_move_sprite.z = 51
@last_move_sprite.visible = false
end
#--------------------------------------------------------------------------
# * Termination Processing
#--------------------------------------------------------------------------