Mundo Maker
¡Bienvenid@ a Mundo Maker!

¿Quieres aprender todo sobre el RPG Maker?



Regístrate y forma parte de Mundo Maker.

[RGSS2]Minijuego Othello

Ver el tema anterior Ver el tema siguiente Ir abajo

[RGSS2]Minijuego Othello

Mensaje por gantzer49 el 2015-03-23, 20:34

¡Hola a todos! les traigo un estupendo minijuego que me conseguí hace más o menos un año en una página japonesa, con el objetivo de implementarlo en mi juego actual, pero lamentablemente era para RPG Maker VX y nunca pude configurarlo para el RPG Maker VX ACE, de todos modos, el juego es muy entretenido y quiero compartirlo con ustedes, es un minijuego de mesa llamado Othello (también conocido como Yang o Reversi).

Un poco de información sobre el juego:
Éste juego fué creado en Inglaterra del sigo XIX llamado Reversi, luego un japonés llamado Goro Hasegawa cambió algunas reglas y el juego pasó a ser llamado Othello.

Reglas del juego:
El tablero del juego consta de 8 filas por 8 columnas y se usan 64 fichas redondas que son blancas por una cara y negra por la otra, cada jugador tiene un color asignado, y el que tiene el color negro comienza.

El movimiento consiste en colocar una ficha de forma que flanquee una o varias fichas del color contrario y voltear esas fichas para que pasen a mostrar el propio color, esas fichas, para que estén flanqueadas, deben formar una línea continua recta (diagonal u ortogonal) de fichas del mismo color entre dos fichas del color contrario (una de ellas la recién colocada y la otra ya presente)

Una partida puede durar unos 4 minutos, o extenderse incluso a una hora aproximadamente, todo dependiendo de cuanto te toma pensar en tu jugada.
para iniciar el juego, se tiene que poner en un evento la siguiente llamada de script:
Código:
$scene = Scene_Othello.new
El script tiene más funciones como crear alguna condición si el jugador gana o pierde, pero no logré saber como utilizar al completo este script, ya que lo guardé y no me puse a investigar más a fondo su funcionamiento ya que sabía que no lo iva a ocupar en mi juego porque sólo funciona para el VX, y con pantalla 544x416, aunque no sé si se podrá configuar eso también (advierto que esta todo el script en japonés XD).
El juego utiliza efectos de sonido y música del RTP del programa, por lo que es importante que los archivos de audio estén en la carpeta del juego (a menos que sepas meterle mano al script y puedas configurar los nombres de los archivos de audio )
Capturas:




Instalación:
Insertar Script sobre "Main" en el Editor de Scripts.
Código:
=begin
      ★ミニゲーム:オセロ★
      
      CPUとオセロで戦えます。
      思考ルーチンにminimax法とかを使ってないのでそこまで強くありません。
      あくまでミニゲームということで。
      
      ● 使い方 ●========================================================
      イベントコマンドのスクリプトで次の命令を実行
      $scene = Scene_Othello.new
      ====================================================================      
      
      ver1.02

      Last Update : 2011/02/09
      02/09 : 引き分け時のサウンドが定義されていなかった不具合を修正
      ----------------------2011--------------------------
      05/22 : CPUのPASS時にエラーが発生する場合がある不具合を修正?
            : 配置可能場所に石を置けない場合がある不具合を修正?
      05/17 : 新規
      ----------------------2010--------------------------
      
      ろかん   http://kaisouryouiki.web.fc2.com/
=end

#===================================
#  ●設定箇所
#===================================
module OTHELLO
  # 結果を格納する変数番号
  # 対戦後の石差が格納されます
  # 勝利時は正の値、敗北時は負の値が格納されます
  # ギブアップ時は-100が格納されます
  RESULT_O_V = 35
  
  # パズルゲーム中のBGM[ファイル名, 音量, ピッチ]
  OTHELLO_GAME_BGM = RPG::BGM.new("Field3", 100, 100)
  # CPUの思考停止時間をフレーム数で指定
  CPU_AITHI_TIME = 90
end
#===================================
#  ここまで
#===================================

$rsi = {} if $rsi == nil
$rsi["オセロ"] = true

module OTHELLO
  WALL = -3      # 盤外:処理の都合上定義
  BLACK = -2     # 黒が置かれている
  WHITE = -1     # 白が置かれている
  AVOID_NONE = 0 # 何も無い(避けるべき場所)
  NOMAL_NONE = 1 # 何も無い(通常の場所)
  SIDE = 2       # 何も無い(優先すべき場所)
  CORNER = 3     # 何も無い(最優先すべき場所)
end

class Othello_Board
  #--------------------------------------------------------------------------
  # ● インクルード OTHELLO
  #--------------------------------------------------------------------------
  include OTHELLO
  #--------------------------------------------------------------------------
  # ● 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_reader       :board              # オセロ盤の状況
  attr_accessor     :set_stone_flag     # 石を新たに配置したフラグ
  attr_accessor     :condition_change   # オセロ盤の状況の全体的な変化フラグ
  attr_accessor     :notice_list        # 配置可能通知インデックスリスト
  attr_accessor     :set_position_data  # セットする石のリスト・位置データ
  attr_accessor     :set_color          # セットする石の色
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(color)
    board_clear
    @color = color
    @set_color = 0
    @set_position_data = []
    @set_stone_flag = false
    @condition_change = false
    @notice_list = [nil]
    @othello_sprite = Spriteset_Othello.new(self, @color)
  end
  #--------------------------------------------------------------------------
  # ● シーンの開始後処理で石を配置する
  #--------------------------------------------------------------------------
  def set_initialize_stone
    @othello_sprite.create_stones
  end
  #--------------------------------------------------------------------------
  # ● 開放
  #--------------------------------------------------------------------------
  def dispose
    @othello_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    return @othello_sprite.update
  end
  #--------------------------------------------------------------------------
  # ● オセロ盤の初期化
  #--------------------------------------------------------------------------
  def board_clear
    @board = Table.new(10,10)
    for i in 0...10
      for j in 0...10
        if i.zero? || j.zero? || i == 9 || j == 9
          @board[i, j] = WALL
        elsif (i == 5 && j == 4) || (i == 4 && j == 5)
          @board[i, j] = BLACK
        elsif (i == 4 && j == 4) || (i == 5 && j == 5)
          @board[i, j] = WHITE
        elsif (i == 2 && j == 1) || (i == 2 && j == 2) || (i == 1 && j == 2) ||
              (i == 7 && j == 1) || (i == 7 && j == 2) || (i == 8 && j == 2) ||
              (i == 2 && j == 8) || (i == 2 && j == 7) || (i == 1 && j == 7) ||
              (i == 7 && j == 7) || (i == 7 && j == 8) || (i == 8 && j == 7)
          @board[i, j] = AVOID_NONE
        elsif (i == 1 && j == 1) || (i == 8 && j == 1) ||
              (i == 1 && j == 8) || (i == 8 && j == 8)
          @board[i, j] = CORNER
        elsif (i == 1 && j == 3) || (i == 3 && j == 3) || (i == 3 && j == 1) ||
              (i == 1 && j == 6) || (i == 3 && j == 6) || (i == 3 && j == 8) ||
              (i == 6 && j == 1) || (i == 6 && j == 3) || (i == 8 && j == 3) ||
              (i == 6 && j == 6) || (i == 8 && j == 6) || (i == 6 && j == 8)
          @board[i, j] = SIDE
        else
          @board[i, j] = NOMAL_NONE
        end
      end
    end  
  end
  #--------------------------------------------------------------------------
  # ● 石数をそれぞれ返す
  #--------------------------------------------------------------------------
  def get_stones_size
    result = [0, 0]
    for i in 0...10
      for j in 0...10
        case @board[i, j]
        when BLACK
          result[@color[0] == BLACK ? 0 : 1] += 1
        when WHITE
          result[@color[0] == BLACK ? 1 : 0] += 1
        end
      end
    end  
    return result
  end
  #--------------------------------------------------------------------------
  # ● 石が置かれていないインデックスを返す
  #--------------------------------------------------------------------------
  def check1_no_index
    result = []
    for i in 0...10
      for j in 0...10
        result << [i, j] if @board[i, j] >= AVOID_NONE
      end
    end  
    return result.uniq
  end
  #--------------------------------------------------------------------------
  # ● 石を置くことができるインデックスを返す
  #--------------------------------------------------------------------------
  def check2_can_put_index(mycolor)
    symmetry_color = (mycolor == BLACK) ? WHITE : BLACK # 対称色
    result = []
    for i in check1_no_index
      old_result = result
      for j in [[-1, 1], [0, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [0, -1], [1, -1]]
        next if @board[i[0] + j[0], i[1] + j[1]] != symmetry_color # 対称色でない
        check_length = 1             # 拡張する検査範囲
        loop do
          cc = @board[i[0] + (j[0] * check_length), i[1] + (j[1] * check_length)]
          if cc == mycolor           # 拡張先で自分と同色に遭遇
            result << i              # 配置可能
            break
          elsif cc != symmetry_color # 拡張先で奪えない配置に遭遇
            break                    # 配置不可
          elsif cc == symmetry_color # 拡張先で対称色に遭遇
            check_length += 1        # 検査範囲をさらに拡張
          end
        end
        break if result != old_result# 配置可能と判断された場合は次へ移行
      end
    end
    return result.uniq
  end
  #--------------------------------------------------------------------------
  # ● 評価値が最も高いインデックスを返す
  #--------------------------------------------------------------------------
  def check3_can_put_value(mycolor, phase)
    symmetry_color = (mycolor == BLACK) ? WHITE : BLACK # 対称色
    max_result = [[0, 0], 0]         # 最も高い総合評価値とそれを持つインデックス
    for i in check2_can_put_index(mycolor)
      point_result = 0 # その検査場所の総合評価値
      get_size     = 0 # 奪える石数
      open_point   = 0 # 開放度
      position     = 0 # 場所による評価値
      error_point = phase.zero? ? rand(4) : 0 # 序盤のみ発生する誤差
      for j in [[-1, 1], [0, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [0, -1], [1, -1]]
        next if @board[i[0] + j[0], i[1] + j[1]] != symmetry_color # 対称色でない
        check_length = 1             # 拡張する検査範囲
        direction_getsize   = 0      # その方向から奪える石数
        direction_openpoint = 0      # その方向の開放度
        loop do
          cc = @board[i[0] + (j[0] * check_length), i[1] + (j[1] * check_length)]
          if cc == mycolor           # 拡張先で自分と同色に遭遇
            get_size += direction_getsize     # 奪える石数の決定
            open_point += direction_openpoint # 開放度の決定
            break
          elsif cc != symmetry_color # 拡張先で奪えない配置に遭遇
            break                    # 配置不可
          elsif cc == symmetry_color # 拡張先で対称色に遭遇
            if phase.zero?           # 遭遇地点の開放度を計算 序盤のみ適用
              for k in [[-1, 1], [0, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [0, -1], [1, -1]]
                kxi = i[0] + (j[0] * check_length) + k[0]
                kyi = i[1] + (j[1] * check_length) + k[1]
                direction_openpoint += 1 if @board[kxi, kyi] >= AVOID_NONE
              end
            end
            direction_getsize += 1   # 奪える石数候補を増やす
            check_length += 1        # 検査範囲をさらに拡張
          end
        end
      end
      position = @board[i[0], i[1]] * 15
      point_result = get_size - open_point + position + error_point
      if max_result[1] <  point_result # 最大評価値の更新
        max_result[0] = i
        max_result[1] = point_result
      end
    end
    return max_result
  end
  #--------------------------------------------------------------------------
  # ● 反転するインデックスを返す
  #--------------------------------------------------------------------------
  def check4_change_index(set_position, mycolor)
    symmetry_color = (mycolor == BLACK) ? WHITE : BLACK # 対称色
    result = []
    for i in [[-1, 1], [0, 1], [1, 1], [-1, 0], [1, 0], [-1, -1], [0, -1], [1, -1]]
      next if @board[set_position[0] + i[0], set_position[1] + i[1]] != symmetry_color # 対称色でない
      direction_getlist = []       # その方向にある反転させるべきインデックス
      check_length = 1             # 拡張する検査範囲
      loop do
        cc = @board[set_position[0] + (i[0] * check_length), set_position[1] + (i[1] * check_length)]
        if cc == mycolor           # 拡張先で自分と同色に遭遇
          result += direction_getlist
          break
        elsif cc != symmetry_color # 拡張先で奪えない配置に遭遇
          break                    # 配置不可
        elsif cc == symmetry_color # 拡張先で対称色に遭遇
          direction_getlist << [set_position[0] + (i[0] * check_length), set_position[1] + (i[1] * check_length)]
          check_length += 1        # 検査範囲をさらに拡張
        end
      end
    end
    return result.uniq
  end
  #--------------------------------------------------------------------------
  # ● 石を置けない判定
  #--------------------------------------------------------------------------
  def can_not_set?(turn)
    return check2_can_put_index(@color[turn ? 0 : 1]).length.zero?
  end
  #--------------------------------------------------------------------------
  # ● 石を置く場所を決定する:CPU用
  #--------------------------------------------------------------------------
  def decision_set_position(phase)
    set_position_data = check3_can_put_value(@color[1], phase)
    set_stone(set_position_data[0], @color[1])
  end
  #--------------------------------------------------------------------------
  # ● 指定位置に石をセットする
  #--------------------------------------------------------------------------
  def set_stone(data, color)
    # 配置する処理
    @set_stone_flag = true
    @set_position_data, @set_color = data, color
    @board[@set_position_data[0], @set_position_data[1]] = @set_color
    # 配置により反転する処理
    @condition_change = true
    for i in check4_change_index(@set_position_data, @set_color)
      @board[i[0], i[1]] = @set_color
    end
  end
end

class Sprite_Storn < Sprite
  #--------------------------------------------------------------------------
  # ● インクルード OTHELLO
  #--------------------------------------------------------------------------
  include OTHELLO
  #--------------------------------------------------------------------------
  # ● 定数
  #--------------------------------------------------------------------------
  INVERSION_SE = RPG::SE.new("Book", 90, 70)
  SET_SE       = RPG::SE.new("Cursor", 90, 80)
  #--------------------------------------------------------------------------
  # ● 公開インスタンス変数
  #--------------------------------------------------------------------------
  attr_reader       :xi              # 横軸のインデックス
  attr_reader       :yi              # 縦軸のインデックス
  attr_accessor     :notice          # 配置可能通知フラグ
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(xi, yi, condition)
    super(nil)
    @xi, @yi = xi, yi
    @condition = nil
    @notice = false
    self.x = (35 * xi) + (10 * xi) - 22
    self.y = (35 * yi) + (10 * yi) - 11
    self.bitmap = Cache.picture("OthelloStones") if condition != WALL
    update_bitmap_change(condition, true)
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    self.bitmap.dispose if self.bitmap != nil
    super
  end
  #--------------------------------------------------------------------------
  # ● 転送元ビットマップの更新
  #--------------------------------------------------------------------------
  def update_bitmap_change(new_condition, set = false)
    if self.bitmap != nil && @condition != new_condition
      @condition = new_condition
      return if @condition == WALL
      case @condition
      when BLACK
        self.src_rect.set(35, 0, 35, 35)
      when WHITE
        self.src_rect.set(70, 0, 35, 35)
      else
        self.src_rect.set(105, 0, 35, 35)
        return
      end
      set ? SET_SE.play : INVERSION_SE.play
      if (@condition == BLACK || @condition == WHITE)
        17.times{
          Graphics.update
          Input.update
        }
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 転送元ビットマップの更新:通知
  #--------------------------------------------------------------------------
  def update_bitmap_notice
    if @notice
      self.src_rect.set(0, 0, 35, 35)
    elsif @condition != BLACK && @condition != WHITE
      self.src_rect.set(105, 0, 35, 35)
    end
  end
end

class Sprite_StornCount < Sprite
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(count_target) # 0/ 1 => PLAYER/ CPU
    super(Viewport.new(0, 0, 544, 416))
    self.bitmap = Bitmap.new(140, 100)
    self.bitmap.font.size = 35
    self.x = 385
    self.y = count_target.zero? ? 340 : -15
    refresh(2)
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    self.bitmap.dispose
    super
  end
  #--------------------------------------------------------------------------
  # ● リフレッシュ
  #--------------------------------------------------------------------------
  def refresh(stone_size)
    self.bitmap.clear
    self.bitmap.font.color.set(255, 255, 255)
    self.bitmap.draw_text(0, 0, self.bitmap.width, self.bitmap.height, "#{stone_size}", 2)
  end
end

class Sprite_StornColor < Sprite
  #--------------------------------------------------------------------------
  # ● インクルード OTHELLO
  #--------------------------------------------------------------------------
  include OTHELLO
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(color, player)
    super(nil)
    self.x = 490
    self.y = player ? 320 : 56
    self.bitmap = Cache.picture("OthelloStones")
    case color
    when BLACK
      self.src_rect.set(35, 0, 35, 35)
    when WHITE
      self.src_rect.set(70, 0, 35, 35)
    end
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    self.bitmap.dispose
    super
  end
end

class Sprite_Result < Sprite
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize
    super(nil)
    @display_viewport = Viewport.new(0, 0, 544, 416)
    self.bitmap = Cache.picture("OthelloResult")
    self.src_rect.set(0, 195, 207, 65)
    self.x = 544
    self.y = (416 / 2) - (65 / 2)
    self.z = 300
    self.opacity = 0
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    self.bitmap.dispose
    @display_viewport.dispose
    super
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update(condition)
    case condition
    when 0 # 勝利
      self.src_rect.set(0, 0, 207, 65)
      @display_viewport.flash(Color.new(255, 255, 255, 200), 45)
    when 1 # 敗北
      self.src_rect.set(0, 65, 207, 65)
    when 2 # パス
      self.src_rect.set(0, 130, 207, 65)
    when 3 # 引き分け
      self.src_rect.set(0, 195, 207, 65)
    when 4 # スタート
      self.src_rect.set(0, 260, 207, 65)
    end
    animation_count = 0
    loop do
      case animation_count
      when 0..36
        self.x -= 10
        self.opacity += 10
      when 95..130
        if condition == 2 || condition == 4
          self.x -= 10
          self.opacity -= 10
        end
      end
      Graphics.update
      @display_viewport.update
      animation_count += 1
      break if animation_count == 131
    end
    if condition == 2 || condition == 4
      self.x = 544
      self.src_rect.set(0, 325, 207, 65)
    end
  end
end

class Spriteset_Othello
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(board, color)
    @board_condition = board
    create_back
    create_stone_count
    create_color(color)
  end
  #--------------------------------------------------------------------------
  # ● 背景スプライトの生成
  #--------------------------------------------------------------------------
  def create_back
    @back_sprite = Sprite.new
    @back_sprite.bitmap = Cache.picture("OthelloBoard")
  end
  #--------------------------------------------------------------------------
  # ● 石スプライトの生成
  #--------------------------------------------------------------------------
  def create_stones
    @stone_sprite = []
    for i in 0...10
      for j in 0..10
        @stone_sprite << Sprite_Storn.new(i, j, @board_condition.board[i, j])
      end
    end
  end
  #--------------------------------------------------------------------------
  # ● 石数カウントスプライトの生成
  #--------------------------------------------------------------------------
  def create_stone_count
    @count_sprite = []
    @count_sprite << Sprite_StornCount.new(0)
    @count_sprite << Sprite_StornCount.new(1)
  end
  #--------------------------------------------------------------------------
  # ● 対戦者の色を示すスプライトの生成
  #--------------------------------------------------------------------------
  def create_color(color)
    @color_sprite = []
    @color_sprite << Sprite_StornColor.new(color[0], true)
    @color_sprite << Sprite_StornColor.new(color[1], false)
  end
  #--------------------------------------------------------------------------
  # ● 解放
  #--------------------------------------------------------------------------
  def dispose
    for i in @stone_sprite do i.dispose end
    for j in @count_sprite do j.dispose end
    for k in @color_sprite do k.dispose end
    @back_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    if @board_condition.notice_list.length.zero?
      notice_update
      @board_condition.notice_list << nil
      return true
    elsif @board_condition.set_stone_flag
      set_stone_update
      @board_condition.set_stone_flag = false
      return true
    elsif @board_condition.condition_change
      for i in 0..1
        @count_sprite[i].refresh(@board_condition.get_stones_size[i])
      end
      change_stone_update
      @board_condition.condition_change = false
      return true
    elsif @board_condition.notice_list[0] != nil
      notice_update(@board_condition.notice_list)
      return false
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ● 石スプライトの更新:石の設置
  #--------------------------------------------------------------------------
  def set_stone_update
    xi = @board_condition.set_position_data[0]
    yi = @board_condition.set_position_data[1]
    for i in @stone_sprite
      next if i.bitmap == nil
      next unless i.xi == xi && i.yi == yi
      i.update_bitmap_change(@board_condition.board[xi, yi], true)
    end
  end
  #--------------------------------------------------------------------------
  # ● 石スプライトの更新:石の反転
  #--------------------------------------------------------------------------
  def change_stone_update
    for i in @stone_sprite
      next if i.bitmap == nil
      i.update_bitmap_change(@board_condition.board[i.xi, i.yi])
    end
  end
  #--------------------------------------------------------------------------
  # ● 配置可能通知の更新
  #--------------------------------------------------------------------------
  def notice_update(list = [])
    for i in @stone_sprite
      next if i.bitmap == nil
      i.notice = list.include?([i.xi, i.yi])
      i.update_bitmap_notice
    end
  end
end

class Window_StornCursor < Window
  #--------------------------------------------------------------------------
  # ● インクルード OTHELLO
  #--------------------------------------------------------------------------
  include OTHELLO
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize(color)
    super()
    self.windowskin = Cache.system("Window")
    self.width  = 68
    self.height = 68
    self.opacity = 0
    self.contents_opacity = 180
    self.visible = false
    @bstf = false
    create_contents
    refresh(color)
  end
  #--------------------------------------------------------------------------
  # ● ウィンドウ内容の作成
  #--------------------------------------------------------------------------
  def create_contents
    self.contents.dispose
    self.contents = Bitmap.new(width - 32, height - 32)
  end
  #--------------------------------------------------------------------------
  # ● リフレッシュ
  #--------------------------------------------------------------------------
  def refresh(color)
    bitmap = Cache.picture("OthelloStones")
    rect = Rect.new((color == BLACK) ? 35 : 70, 0, 35, 35)
    self.contents.blt(0, 0, bitmap, rect)
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    # 点滅処理
    if self.contents_opacity < 180 && @bstf
      self.contents_opacity += 5
    elsif self.contents_opacity > 40 && ! @bstf
      self.contents_opacity -= 5
    else
      @bstf ^= true
    end
  end
end

class Window_OthelloGuidance < Window_Base
  TEXT1_1 = "Comenzar"
  TEXT1_2 = "Botón A"
  TEXT2_1 = "Rendirse"
  TEXT2_2 = "Botón S"
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize
    super(385, 110, 150, 300)
    self.opacity = 0
    refresh
  end
  #--------------------------------------------------------------------------
  # ● リフレッシュ
  #--------------------------------------------------------------------------
  def refresh
    text_width = self.width - 30
    self.contents.clear
    self.contents.font.color = system_color
    self.contents.draw_text(0, WLH * 0, text_width, WLH, TEXT1_1, 0)
    self.contents.draw_text(0, WLH * 2, text_width, WLH, TEXT2_1, 0)
    self.contents.font.color = normal_color
    self.contents.draw_text(-3, WLH * 1, text_width, WLH, TEXT1_2, 2)
    self.contents.draw_text(-3, WLH * 3, text_width, WLH, TEXT2_2, 2)
  end
end

class Scene_Othello < Scene_Base
  START_SE = RPG::SE.new("Saint7", 100, 100)
  WIN_SE = RPG::SE.new("Applause", 100, 100)
  WIN_ME = RPG::ME.new("Fanfare1", 100, 100)
  LOSE_SE = RPG::SE.new("Chest", 100, 60)
  LOSE_ME = RPG::ME.new("Shock", 100, 100)
  LOSE_SE = RPG::SE.new("Chest", 100, 70)
  DRAW_ME = RPG::ME.new("Mystery", 100, 100)
  PASS_SE = RPG::SE.new("Saint6", 100, 100)
  #--------------------------------------------------------------------------
  # ● インクルード OTHELLO
  #--------------------------------------------------------------------------
  include OTHELLO
  #--------------------------------------------------------------------------
  # ● オブジェクト初期化
  #--------------------------------------------------------------------------
  def initialize
    @map_bgm = RPG::BGM.last
    @map_bgs = RPG::BGS.last
    RPG::BGM.stop
    RPG::BGS.stop
    OTHELLO_GAME_BGM.play
  end
  #--------------------------------------------------------------------------
  # ● 開始処理
  #--------------------------------------------------------------------------
  def start
    reset_game
    create_class
    create_giveup_command_window
    create_result
  end
  #--------------------------------------------------------------------------
  # ● 開始後処理
  #--------------------------------------------------------------------------
  def post_start
    @othello_board.set_initialize_stone
  end
  #--------------------------------------------------------------------------
  # ● 各クラスのインスタンス化
  #--------------------------------------------------------------------------
  def create_class
    @othello_board = Othello_Board.new(@color)
    @stone_cursor  = Window_StornCursor.new(@color[0])
    @guide_window  = Window_OthelloGuidance.new
  end
  #--------------------------------------------------------------------------
  # ● オセロのリセット
  #--------------------------------------------------------------------------
  def reset_game
    @game_condition = 0 # ゲームの進行状況
    @turn_count = 0     # 手数
    @phase_line = 0     # 局面
    @turn_end = true    # ターンエンドフラグ
    @select_index = 0   # 選択インデックス
    @color = [[-2, -1], [-1, -2]][rand(2)] # 色
    @player_turn = (@color[0] == BLACK)    # ターンフラグ
  end
  #--------------------------------------------------------------------------
  # ● ギブアップ確認コマンドウィンドウの作成
  #--------------------------------------------------------------------------
  def create_giveup_command_window
    @giveup_command_window = Window_Command.new(160, ["Rendirse", "Continuar"])
    @giveup_command_window.x = 544 / 2 - @giveup_command_window.width  / 2
    @giveup_command_window.y = 416 / 2 - @giveup_command_window.height / 2
    @giveup_command_window.index = 1
    @giveup_command_window.active  = false
    @giveup_command_window.visible = false
  end
  #--------------------------------------------------------------------------
  # ● 結果を示すスプライトの生成
  #--------------------------------------------------------------------------
  def create_result
    @result_sprite = Sprite_Result.new
  end
  #--------------------------------------------------------------------------
  # ● 終了処理
  #--------------------------------------------------------------------------
  def terminate
    @map_bgm.play
    @map_bgs.play
    @othello_board.dispose
    @stone_cursor.dispose
    @guide_window.dispose
    @giveup_command_window.dispose
    @result_sprite.dispose
  end
  #--------------------------------------------------------------------------
  # ● 局面の監視 および 進行
  #--------------------------------------------------------------------------
  def phase_check
    @turn_count += 1
    case @turn_count
    when 0..20    # 序盤
      @phase_line = 0
    when 21..44   # 中盤
      @phase_line = 1
    when 44..64   # 終盤
      @phase_line = 2
    end
  end
  #--------------------------------------------------------------------------
  # ● パス処理
  #--------------------------------------------------------------------------
  def pass?
    if @othello_board.can_not_set?(@player_turn)
      if @othello_board.can_not_set?(@player_turn ^ true)
        # 対称色も置けない場合はゲーム終了
        @game_condition = 2
        return true
      else
        # パスアニメーション
        PASS_SE.play
        @result_sprite.update(2)
      end
      action_end
      return true
    end
    return false
  end
  #--------------------------------------------------------------------------
  # ● プレイヤー行動前処理
  #--------------------------------------------------------------------------
  def action_start_player
    return if pass?
    # 配置可能箇所のリスト化
    @othello_board.notice_list = @othello_board.check2_can_put_index(@color[0])
    move_cursor
    @turn_end = false
  end
  #--------------------------------------------------------------------------
  # ● CPU行動前処理
  #--------------------------------------------------------------------------
  def action_start_cpu
    return if pass?
    @turn_end = false
  end
  #--------------------------------------------------------------------------
  # ● プレイヤーに行動させる
  #--------------------------------------------------------------------------
  def action_player
    @othello_board.set_stone(@othello_board.notice_list[@select_index], @color[0])
    phase_check
    action_end
  end
  #--------------------------------------------------------------------------
  # ● CPUに行動させる
  #--------------------------------------------------------------------------
  def action_cpu
    CPU_AITHI_TIME.times{ Graphics.update } unless @turn_count.zero?
    @othello_board.decision_set_position(@phase_line)
    phase_check
    action_end
  end
  #--------------------------------------------------------------------------
  # ● 行動後処理
  #--------------------------------------------------------------------------
  def action_end
    @select_index = 0
    @othello_board.notice_list = []
    @turn_end = true
    @player_turn ^= true
    @stone_cursor.visible = @player_turn
  end
  #--------------------------------------------------------------------------
  # ● カーソルの移動
  #--------------------------------------------------------------------------
  def move_cursor
    return if @othello_board.notice_list.size.zero?
    xi = @othello_board.notice_list[@select_index][0]
    yi = @othello_board.notice_list[@select_index][1]
    @stone_cursor.x = (35 * xi) + (10 * xi) - 38
    @stone_cursor.y = (35 * yi) + (10 * yi) - 27
  end
  #--------------------------------------------------------------------------
  # ● フレーム更新
  #--------------------------------------------------------------------------
  def update
    case @game_condition
    when 0 # 対戦前
      if Input.trigger?(Input::X)
        START_SE.play
        @result_sprite.update(4)
        @game_condition = 1
        @stone_cursor.visible = @player_turn
      end
    when 1 # 対戦中
      return if @othello_board.update # オセロ盤の更新中
      return if update_giveup         # ギブアップコマンドの更新中
      if @turn_end
        @player_turn ? action_start_player : action_start_cpu
      elsif @player_turn
        @stone_cursor.update
        update_select_position
      else
        action_cpu
      end
    when 2 # 対戦終了後
      clear_update
    end
  end
  #--------------------------------------------------------------------------
  # ● 投了確認コマンド更新
  #--------------------------------------------------------------------------
  def update_giveup
    if @giveup_command_window.active
      giveup_command_update
      return true
    else
      if Input.trigger?(Input::Y)
        @giveup_command_window.active  = true
        @giveup_command_window.visible = true
        @giveup_command_window.index = 1
        return true
      end
      return false
    end
  end
  #--------------------------------------------------------------------------
  # ● 配置場所の移動・選択・決定更新
  #--------------------------------------------------------------------------
  def update_select_position
    last_index = @select_index
    if Input.trigger?(Input::DOWN) || Input.trigger?(Input::RIGHT)
      @select_index = (@select_index == @othello_board.notice_list.length - 1) ?
                      0 : @select_index + 1
    elsif Input.trigger?(Input::UP) || Input.trigger?(Input::LEFT)
      @select_index = @select_index.zero? ?
                      @othello_board.notice_list.length - 1 : @select_index - 1
    end
    move_cursor   if last_index != @select_index
    action_player if Input.trigger?(Input::C)
  end
  #--------------------------------------------------------------------------
  # ● 投了確認コマンド更新
  #--------------------------------------------------------------------------
  def giveup_command_update
    @giveup_command_window.update
    if Input.trigger?(Input::C)
      case @giveup_command_window.index
      when 0
        Sound.play_decision
        @giveup_command_window.active = @giveup_command_window.visible = false
        clear_update(true)
      when 1
        Sound.play_cancel
      end
      @giveup_command_window.active = @giveup_command_window.visible = false
    elsif Input.trigger?(Input::B)
      Sound.play_cancel
      @giveup_command_window.active = @giveup_command_window.visible = false
    end
  end
  #--------------------------------------------------------------------------
  # ● 対戦後の更新
  #--------------------------------------------------------------------------
  def clear_update(giveup = false)
    # 石状況を取得
    result = @othello_board.get_stones_size
    $game_variables[RESULT_O_V] = giveup ? -100 : result[0] - result[1]
    # リザルトアニメーション
    if giveup || result[0] < result[1]
      LOSE_ME.play
      LOSE_SE.play
      @result_sprite.update(1)
    elsif result[0] > result[1]
      WIN_ME.play
      WIN_SE.play
      @result_sprite.update(0)
    elsif result[0] == result[1]
      DRAW_ME.play
      DRAW_SE.play
      @result_sprite.update(3)
    end
    loop do
      Graphics.update
      Input.update
      if Input.trigger?(Input::C)
        $scene = Scene_Map.new
        break
      end
    end
  end
end

Importante: deben agregar éstas imágenes en la carpeta Graphics/Pictures y colocarles los siguientes nombres:
Spoiler:
OthelloBoard:


OthelloResult


OthelloStones

Además agregaré una demo, que incluye el script para que vean como es, o para lo que quieran simplemente jugarlo (es muy entretenido)

¡DEMO PARA LLEGAR Y JUGAR!

https://mega.co.nz/#!gAJEDIAA!x0Z4xIFaZ0JizVkF5J0PC7A3vTePYjZYxFYkNRR9tGE

Créditos: Rokan (el blog la página de descarga original ya no existe)

Bugs conocidos:
Cuando ocurre un empate (rara vez sucede pero a veces pasa), produce un crash el juego, pero a veces, es lo único que me he encontrado mal en el script, pero es raro que se produzca además.
No estoy seguro si tiene incompatibilidades con otros scripts, pero si encuentran algún error de compatibilidad pueden decirme para irlos agregando.

gantzer49
Novato
Novato

0/3

Créditos 82

Gracias : 20

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba


Permisos de este foro:
No puedes responder a temas en este foro.