gregor42 has asked for the wisdom of the Perl Monks concerning the following question:

As a follow-up to a previous posting where I learned a LOT...

It has brought me to this logical point in my project. I'm working with very simple RPG games. What I'm looking to do is to use the 2D-array as the Gameboard. Within each array element is either going to be a Data Structure defined to store all the game data on that "square" or simply a Grid object. Frankly I haven't decided which is the best way to approach this & why.

The problem I have depends on the type of gameboard you aspire to. If I wanted a 'globe', with fixed dimensions & complete wraparound behavior then I would use a single 2D array. Since negative values are allowed this statement is legal:

print "$grid[-5][-1]";

However, if I want instead to create a gameboard that is an infinite plane, that is another matter entirely. You would never want to call any array element by a negative value. Instead, I think, you will need 4 2Darrays, one each to accomidate all of the neg/pos quadrants on a typical geometric graph:

(x,y) -1,1 | 1,1 ----------+---------- <-- origin (0,0) -1,-1 | 1,-1

Also, it gets tricky when you ask for element 0,0. Which array should it exist in?

Now, when I did this in Java, I created a Gameboard object & a Column object & a series of Row objects & a series of Grid objects. Each one contained 2 vectors (scalable arrays) one for negative & one for positive. The Gameboard contained the Column object. The Column Object contained the Row instances, and the Rows contained Grid objects. At each step going down I had to make a conditional based on pos/neg value & then use the absolute value to perform the operations on the vector.

Now, that was a lot of work. I have reduced it to about 1% of the source code size by using PERL & asking for help from the Bretheren. What I want to know is: Is there a "Mo' Better" way to approach this:

I have taken out the ambiguity that was in the last version of the code I posted, hopefully this will hone down what I'm aiming at.
use strict; my (@pp_grid, @pn_grid, @nn_grid, @np_grid, @input); #INPUT push @pp_grid, [ @input ] for @input; push @pn_grid, [ @input ] for @input; push @nn_grid, [ @input ] for @input; push @np_grid, [ @input ] for @input; @pp_grid = ( [ qw( a b c d ) ], [ qw( e f g h ) ], [ qw( i j k l ) ], [ qw( m n o p ) ], ); @pn_grid = ( [ qw( q r s t ) ], [ qw( u v w x ) ], [ qw( y z 1 2 ) ], [ qw( 3 4 5 6 ) ], ); @nn_grid = ( [ qw( A B C D ) ], [ qw( E F G H ) ], [ qw( I J K L ) ], [ qw( M N O P ) ], ); @np_grid = ( [ qw( Q S T U ) ], [ qw( V W X Y ) ], [ qw( Z 7 8 9 ) ], [ qw( 0 ? ! & ) ], ); #OUTPUT print "pp_grid:\n"; print "@$_\n" for @pp_grid; print "\n"; print "np_grid:\n"; print "@$_\n" for @np_grid; print "\n"; print "nn_grid:\n"; print "@$_\n" for @nn_grid; print "\n"; print "pn_grid:\n"; print "@$_\n" for @pn_grid; print " and here is 1,-1: $pn_grid[1][1]\n"; print " and here is 1,1: $pp_grid[1][1]\n"; print " and here is -1,1: $np_grid[1][1]\n"; print " and here is -1,-1: $nn_grid[1][1]\n";


Wait! This isn't a Parachute, this is a Backpack!

Replies are listed 'Best First'.
Re: 2D Arrays as a Gameboard
by tachyon (Chancellor) on Jun 06, 2001 at 22:25 UTC

    A hash of hashes will do the trick nicely and is infinitely extensible. Here I populate a game board that extends from x = -5 to x = +5 with the same range for y then pluck a value from one square (I store the co-ordinates there for simplicity). Probably the simplest, if not the most memory efficient way to do it.

    Hope this helps.

    Cheers

    tachyon

    # declare $grid to hold ref to anon hashes (thanks tye) my $grid; for my $x(-5..5) { for my $y(-5..5) { $grid->{$x}{$y} = "co-ords x:$x, y:$y"; } } print "Here is -2,3 : ", $grid->{-2}{3}; print "\nHere is 0,0 : ", $grid->{0}{0};

    If you want to store a range of attributes for each square a super grid made of a hash of hashes will work.

    Note this has been modified for efficiency based on tye's post:

    my %grid1; for my $x(-5..5) { for my $y(-5..5) { $grid1{$x,$y} = { name => "$x,$y", power => int rand(10), allow => "all" }; } } print "\nHere is name 0,0 : ", $grid1{0,0}{'name'}; print "\nHere is power -2,3 : ", $grid1{-2,3}{'power'}; print "\nHere is allow 5,4 : ", $grid1{0,0}{'allow'};

    A hash of hash of arrays is more space efficient but you must index the contents of each square numerically

    my %grid2; for my $x(-5..5) { for my $y(-5..5) { $grid2{$x,$y} = ["$x,$y",int rand(10),"all"]; } } print "\nHere is name 0,0 : ", $grid2{0,0}[0]; print "\nHere is power -2,3 : ", $grid2{-2,3}[1]; print "\nHere is allow 5,4 : ", $grid2{0,0}[2];

      I'd actually use a single hash here to save space:

      my %grid; keys %grid= 11*11; # preallocate our hash size for my $x(-5..5) { for my $y(-5..5) { $grid{$x,$y} = "co-ords x:$x, y:$y"; } }
      Also note that you either need to remove the "->"s from your code or change "my %grid" to "my $grid".

              - tye (but my friends call me "Tye")

        Good point, in my examples $grid, $grid1 and $grid2 store refs to the data structure not %grid....Damn sloppy. I will take the liberty of fixing the code if that's OK

        I love the economy of $grid{$x,$y} to give keys like "0.-1"- very neat. Q: How much space does it save over and above the 11 unnecessary keys (121 hash keys - all in one hash in your case and in 132 in 12 hashes in mine). Or to put it another way how big is the memory penalty in setting up each extra anon hash?

        Also can you explain the purpose of the preallocation? No doubt it is an efficiency measure but does it commit to a set board size? If not why do we need it as we are about to allocate values to all the keys.

        cheers

        tachyon

Re: 2D Arrays as a Gameboard
by MeowChow (Vicar) on Jun 06, 2001 at 23:27 UTC
    You are tieing your data structures too closely to your functionality. There are no practical infinities in software design, so you don't really need negative coordinates; you can just relocate your origin to a point inside the array.

    If however, you don't want to create arbitrary limits, and you plan on designing a non-static gameboard, which expands to theoretical infinities in all directions as the game progresses and objects are moved, then you should use an object to encapsulate the functionality of your gameboard, and as part of that object's state, store an offset or any other data required to translate between the coordinates you use in gameplay, and the indexes necessary to reference your data structures.

    If you plan on having a very large gameboard, and you are concerned with performance and efficiency, consider using a bit vector or even PDL to internally represent your gameboard. Native lists and hashes are not the way to go. Then again, if you really were concerned about those things, you wouldn't choose Perl to write your game in :)

       MeowChow                                   
                   s aamecha.s a..a\u$&owag.print