Show posts

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.

Topics - Abigail

1
Welcome! / Hi :)
May 23, 2014, 11:07:08 am
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.
2
RPG Maker Scripts / [VX/VX Ace] Chess Engine v2
May 18, 2014, 08:27:45 pm
Chess Engine
For RPG Maker VX
by Abigaila

Download Chess.dll




What is this?
Spoiler: ShowHide
This is a chess engine for RPG Maker.





How to use? IMPORTANT
Spoiler: ShowHide

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:

Spoiler: ShowHide

#==============================================================================
# ** 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.
Spoiler: ShowHide

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