Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
Abigail

[VX/VX Ace] Chess Engine

Recommended Posts

Chess Engine
For RPG Maker VX
by Abigaila

Download Chess.dll




What is this?

This is a chess engine for RPG Maker.






How to use? IMPORTANT


1. Download the attached Chess.dll and place it in your game directory. Make sure the name of the file doesn't change. This is the actual engine that does the thinking.

2a. Install the interface script like you would any other script, invoke it by calling Scene_Chess

-- Or --

2b. You can use the chess engine for some other functionality, or make your own interface. Here is a list of commands. (You must have an understanding of Win32API.)




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")

 







Script (graphical interface)

Put this image in your game folder, name it pieces.png:
J49tjR8.png

 

#==============================================================================
# ** 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

 







DLL-free version (V1):
This version is made entirely with RPG Maker scripts and doesn't rely on a dll. It is much weaker as a player though.


Chess_Constants:

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

Chess_MoveGeneration:

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

Chess_Search:

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

Chess_Position:

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: (VXA Version)

#==============================================================================
# ** 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 (VX Version)

#==============================================================================
# ** 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
  #--------------------------------------------------------------------------&

 

 

Edited by Abigail

Share this post


Link to post
Share on other sites

such an awesome set of script's :) it look's so simple but elegant when you read through the line's of code :p  fancy a job Abigaila :p

 

possible updates:-

option's to change board design

option's to change board pieces

option's to change music in game

changeable AI (change difficulty of the AI at

Share this post


Link to post
Share on other sites

This is absolutely beautiful :p you read through the line's of code in each of the script's and it just seem's so simple but very elegant as well :p very nicely laid out and very neat :)

 

I wanna hire you for my team lol :p

 

Possible Upgrades:-

 

Allow board design to be selected before a game

Allow piece design to be chosen before a game

Allow music to be set before a game

Allow AI to be changed before game to change difficulty level

Add in the option for special move'stobe performed by the AI if certain move's aremade by player

Add an option in for castle king side :)

Share this post


Link to post
Share on other sites

This is absolutely beautiful :P you read through the line's of code in each of the script's and it just seem's so simple but very elegant as well :P very nicely laid out and very neat :)

 

I wanna hire you for my team lol :P

 

Possible Upgrades:-

 

Allow board design to be selected before a game

Allow piece design to be chosen before a game

Allow music to be set before a game

Allow AI to be changed before game to change difficulty level

Add in the option for special move'stobe performed by the AI if certain move's aremade by player

Add an option in for castle king side :)

Thanks for your feedback :D

 

PM me the details about your team, can't promise anything though, but it does sound fun.

Share this post


Link to post
Share on other sites

I tried it and I quite like it. The only thing that would make me like it more is if I had a .png of the pieces. lol

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...