trebor777, just a few comments from my end...trebor777":zfmnf2xj said:Actually if we know how works the table we should be able to write directly
t = Table.new(nx, ny, nz)
for all the cases... as ny and nz, should be set to 0 by the unpack if the loaded tabled only used one or two dimensions.
Secondly you have a small bug that may happen if you try to dump a table which has just been created with only 1 or 2 dim
I think it's related to this; @data.pack('S#{size}') crashes "too few arguments".
I'll later tonight try to fix and improve that anyway.
EDIT^^
Al right Here is the fixed version:
Not Having a 2nd dimension is the same as having a 2nd dimension which only contains 1 item. (can be applied for a 3rd Dimension)
Therefore instead of increasing the dim size if the y or z are greater than 0, we do it if those are greater than 1
The default value for y and z also becomes 1.
Code: class Table def initialize(x, y = 1, z = 1) y = [y.abs,1].max # Just in case the user types 0, or a negative value z = [z.abs,1].max @dim = 1 + (y <=> 1) + (z <=> 1) # <=> returns 1 if greater, 0 if the same, -1 if smaller @xsize, @ysize, @zsize = x, y, z # We don't need to set the 1 to 1 ;) @data = Array.new(@xsize * @ysize * @zsize, 0) end def [](x, y = 0, z = 0) @data[x + y * @xsize + z * @xsize * @ysize] end def []=(*args) x = args[0] y = args.size > 2 ? args[1] : 0 z = args.size > 3 ? args[2] : 0 v = args.pop @data[x + y * @xsize + z * @xsize * @ysize] = v end def _dump(d = 0) [@dim, @xsize, @ysize, @zsize, @xsize * @ysize * @zsize].pack('LLLLL') << @data.pack("S#{@xsize * @ysize * @zsize}") end def self._load(s) size, nx, ny, nz, items = *s[0, 20].unpack('LLLLL') t = Table.new(nx, ny, nz) t.data = s[20, items * 2].unpack("S#{items}") t end attr_accessor(:xsize, :ysize, :zsize, :data) end
1) I did some "field research" on how the RMXP version of Table behaves for various inputs. Here are the results. The comments show what is packed into the dumped string:
Ruby:
               # =>  [dim, x, y, z, size, data (# of bytes)]
t = Table.new(2,4,2).dump   # =>  [  3, 2, 4, 2,  16,         32]
t = Table.new(1,1,1).dump   # =>  [  3, 1, 1, 1,   1,         2]
t = Table.new(1,1,-1).dump  # =>  [  3, 1, 1, 0,   0,         0]
t = Table.new(1,1).dump    # =>  [  2, 1, 1, 1,   1,         2]
t = Table.new(1).dump     # =>  [  1, 1, 1, 1,   1,         2]
t = Table.new(2,3,-4).dump  # =>  [  3, 2, 3, 0,   0,         0]
t = Table.new(2,-4,2).dump  # =>  [  3, 2, 0, 2,   0,         0]
It seems like RMXP doesn't crash when negative arguments are passed, but it also dumps a zero-sized array (which seems to be a bug). I recommend we copy RMXP's behavior, but NOT its bugs.
2) I agree with your point that we should handle 0 and negative values in the initialize method, but should it really assume a dimension -x is x? I think 0 is more intuitive to the user. For example, a Table.new(1,-4,3) would create a 1 x 1 x 3 table instead of a 1 x 4 x 3 table. I think this is intuitive because usually when users give a negative array value, it is because some variable has accidentally gone negative, not because the dimension sign was reversed. What do you think?
If we want to replicate the dump behavior of RMXP exactly, here's what I propose, using a little from everyone. This one:
Ruby:
class Table
 def initialize(x, y = 0, z = 0)
  @dim = 1 + (y > 0 ? 1 : 0) + (z > 0 ? 1 : 0)
  @xsize, @ysize, @zsize = x, [y, 1].max, [z, 1].max
  @data = Array.new(x * y * z, 0)
 end
 def [](x, y = 0, z = 0)
  @data[x + y * @xsize + z * @xsize * @ysize]
 end
 def []=(*args)
  x = args[0]
  y = args.size > 2 ? args[1] : 0
  z = args.size > 3 ? args[2] : 0
  v = args.pop
  @data[x + y * @xsize + z * @xsize * @ysize] = v
 end
 def _dump(d = 0)
  [@dim, @xsize, @ysize, @zsize, @xsize * @ysize * @zsize].pack('LLLLL') <<
  @data.pack("S#{@xsize * @ysize * @zsize}")
 end
 def self._load(s)
  size, nx, ny, nz, items = *s[0, 20].unpack('LLLLL')
  t = Table.new(*[nx, ny, nz][0,size])      # The * breaks apart an array into an argument list
  t.data = s[20, items * 2].unpack("S#{items}")
  t
 end
 attr_accessor(:xsize, :ysize, :zsize, :data)
end
I've tested it and I believe the dumped string matches the RMXP version 100% (except it doesn't have the negative dimension bug). Also, I settled on hanmac's the Table.new(*[...][...]) because, during some test over dumping many tables I didn't see a notable difference in speed. It's more succinct and with a comment it should be apparent what the syntax does.