RGSS2を知る(21)

次はTableクラス。
Cで書いた拡張ライブラリからアクセスするぶんには、Arrayの内部構造でも別に遅くはないが、Rubyから3次元配列にアクセスしようとすると、1アクセスごとにメソッド呼び出しが3回となって、さすがにちょっとしょんぼりだ。
Arrayの[]を再定義するわけにもいかないから、このようなクラスがあるのは悪くない。

t = Table.new(2,2,2)

open("c:\\test.txt","w") do |fh|
  for z in 0...t.zsize
    for y in 0...t.ysize
      for x in 0...t.xsize
        fh.write "[#{x},#{y},#{z}] = #{t[x,y,z]}\n"
      end
    end
  end
end
[0,0,0] = 0
[1,0,0] = 0
[0,1,0] = 0
[1,1,0] = 0
[0,0,1] = 0
[1,0,1] = 0
[0,1,1] = 0
[1,1,1] = 0

とりあえず初期値は0。マニュアルに書いてないんだもの。
んでもって省略した次元は1。

p Table.new(1).zsize #=> 1


さて、このような普通のクラスをなぜここで取り上げるのかというと、マニュアルにこのような記述があるからだ。

要素数が 0 の配列を生成することも可能です。

えーっと・・・??????
意味がわからん。
3次元の箱を想像して、そのうちの1辺の長さが0になるようなものだろう。それはもう3次元の物体として存在できないものになっていて、つまり3次元のうちどれか1つが要素数0になった時点で、Tableオブジェクトの中身は空っぽになるのではなかろうか。

t = Table.new(2,0,2)
p t[0,0,0] #=> nil

そりゃそうだ。
この仕様の存在意義がわからないが、このように実装しないといけないのだろうか。
こんなんエラーでいいやん?それともなんか有意義な使い道が?


最後にちょっと長いがresizeの結果を。

def output(t, type)
  open("c:\\test.txt",type) do |fh|
    for z in 0...t.zsize
      for y in 0...t.ysize
        for x in 0...t.xsize
          fh.write "[#{x},#{y},#{z}] = #{t[x,y,z]}\n"
        end
      end
    end
    fh.write "\n"
  end
end
t = Table.new(2,2,2)
t[1,1,1] = 1
output(t, "w")
t.resize(3,2,2)
output(t, "a")
t.resize(1,2,2)
output(t, "a")
t.resize(2,2,2)
output(t, "a")
[0,0,0] = 0
[1,0,0] = 0
[0,1,0] = 0
[1,1,0] = 0
[0,0,1] = 0
[1,0,1] = 0
[0,1,1] = 0
[1,1,1] = 1

[0,0,0] = 0
[1,0,0] = 0
[2,0,0] = 0
[0,1,0] = 0
[1,1,0] = 0
[2,1,0] = 0
[0,0,1] = 0
[1,0,1] = 0
[2,0,1] = 0
[0,1,1] = 0
[1,1,1] = 1
[2,1,1] = 0

[0,0,0] = 0
[0,1,0] = 0
[0,0,1] = 0
[0,1,1] = 0

[0,0,0] = 0
[1,0,0] = 0
[0,1,0] = 0
[1,1,0] = 0
[0,0,1] = 0
[1,0,1] = 0
[0,1,1] = 0
[1,1,1] = 0

大きくすると中身は保存されるが、小さくしてから戻すと消える。
これはまあ、普通だ。
Cの多次元short配列だと仮定すると単純にreallocするわけにはいかないから、mallocしてそのようにコピーしているのだろう。
あ、これほんとに最後。

t = Table.new(1,1,1)
t[0,0,0] = 60000
p t[0,0,0] # => -5536

飽和はしないらしい。