LoginSignup
5
3

More than 5 years have passed since last update.

デレステのガシャ(ガチャ)不具合から見るガシャ(ガチャ)想像図

Posted at

2017/09/27 15:00:00 JSTにデレステのガシャが更新されたのですが、提供割合不具合が発生しました。
(余談ですが、バンダイナムコエンタテインメント社提供のアプリでは「ガチャ」ではなく「ガシャ」表記です。商標絡みだとか何とか。)

で、そこで発生した現象は

  1. 10連ガシャの最後、SR確定ガシャで本来0.4%のピックアップSSRの確率が0.04%になっていた
  2. それにより、通常SSRの提供割合が想定より上がっていた
  3. SSR以外のレアリティ及び全体の提供割合は想定どおりだった

と言うものです。
また、表記上ピックアップSSR 0.400%、通常SSR 0.029%、ピックアップSR 2.400%、通常SR 0.082%、R 0.825%となっていて、小数第4位での切り捨てが明言されています。(※SR以上確定でないガシャ)
これらの情報から、

  • 割合のうちマスタに明記されているのはレアリティ全体のものとピックアップの割合のみ
  • 通常の確率はレアリティ全体の割合・ピックアップの割合・ピックアップの枚数から計算される

と言う処理が想像出来ます。
ここから、以前作成したガチャの実装例を改変して動作する例を作成してみました。

gacha.rb
require 'csv'

module Gacha
  class Main
    def self.execute
      rarity_deck = RarityDeck.new('rarity.csv')
      lotter = rarity_deck.lot
      card_deck = CardDeck.new('card.csv', lotter.rarity_id, lotter.is_pickup)
      return card_deck.lot
    end
  end

  class RarityDeck
    def initialize(file_name)
      @file_name = file_name
    end

    def data
      base = CSV.read(@file_name)
      data = base.map{|b| Rarity.new(*b)}
      return data
    end

    def lot
      i = 0.0
      lots = data.product([1, 0]).map{|a|
        l = Gacha::Lotter.new(i, i + a[0].wait(a[1]), a[0].id, a[1])
        i +=  a[0].wait(a[1])
        l
      }
      r = rand * 100
      return lots.find{|a| r > a.from && r <= a.to}
    end
  end

  class Rarity
    attr_reader :id, :name, :base_wait, :pickup_wait, :pickup_count
    def initialize(id, name, base_wait, pickup_wait, pickup_count)
      @id = id.to_i
      @name = name
      @base_wait = base_wait.to_f
      @pickup_wait = pickup_wait.to_f
      @pickup_count = pickup_count.to_i
    end

    def wait(is_pickup)
      if is_pickup > 0
        return @pickup_wait * @pickup_count
      else
        return @base_wait - (@pickup_wait * @pickup_count)
      end
    end
  end

  class CardDeck
    def initialize(file_name, rarity_id, is_pickup)
      @file_name = file_name
      @rarity_id = rarity_id
      @is_pickup = is_pickup.to_i > 0
    end

    def data
      base = CSV.read(@file_name)
      data = base.map{|b| Card.new(*b)}
      data = data.select{|d| d.rarity_id == @rarity_id && d.is_pickup == @is_pickup}
      return data
    end

    def lot
      return data.sample
    end
  end

  class Card
    attr_reader :id, :rarity_id, :is_pickup, :name
    def initialize(id, rarity_id, is_pickup, name)
      @id = id.to_i
      @rarity_id = rarity_id.to_i
      @is_pickup = is_pickup.to_i > 0
      @name = name
    end
  end

  class Lotter
    attr_reader :from, :to, :rarity_id, :is_pickup
    def initialize(from, to, rarity_id, is_pickup)
      @from = from
      @to = to
      @rarity_id = rarity_id
      @is_pickup = is_pickup
    end
  end
end

汚い?
もう時間が無いんです!

…ごめんなさい、正直今回のこれは防備録程度のものでしかないですので、少し時間が取れたらもっときれいな実装を作成したいと思います。
そのときには取って付けたようなミリマスのネタではなくちゃんとデレマスのネタも仕込みたいと思います。
一応、以前のものとはブランチを変えてgithubに上げました

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3