From Robowiki
Jump to navigation Jump to search

I'm new to java, and my lack of understanding Java has me hung up on this key peice of code:

buffer = statBuffers[distanceIndex][velocityIndex][lastVelocityIndex];

from my understanding; buffer is an array of 25 (ints), each bin being a counter of times visited. And statBuffers is a 4dimesional array of size: 5(int), 5(int), 5(int),and 25(int) :

private static int[][][][] statBuffers = new int[DISTANCE_INDEXES][VELOCITY_INDEXES][VELOCITY_INDEXES][BINS];

so back to the problem code :

buffer = statBuffers[distanceIndex][velocityIndex][lastVelocityIndex];

so the above "indexes" (0-4) should retrieve the values in thoses locations in the statBuffers arrays. Am I wrong so far? It seems to me were assigning apples to oranges here? How does it work ? --Justin

int single[] = new int[ 5 ];
single is "an array of integers".
int double[][] = new int[ 5 ][ 5 ];
double is "an array of 5 arrays of 5 integers".

This means that each element in double[ n ] is itself "an array of 5 integers".

Let's change int to apple. double is now "an array of 5 arrays of 5 apples."

This means that every double[ n ] is a container, and each container holds 5 apples. The container is not an apple. It is 'a container of one or more apples'. You can visualize it as a paper bag if you like.

apple triple[][][] = new apple[ 5 ][ 5 ][ 5 ];
triple is "an array of 5 arrays of 5 arrays of apples" or perhaps "5 containers of 'containers of apples'".

Going back to your original question, here is the situation: buffer is 'an array of integers'. (I deliberately did not state the size, because buffer can be assigned an array of any size of the same dimensions.) statBuffers is 'an array of arrays of arrays of arrays of integers'. Each element in statBuffers[][][] is itself an 'array of integers', and that is why the assignment works.

I hope that helped. If not, best thing is to just practice with arrays it until it sinks in.


Addendum: Above you mentioned "statBuffers is a 4 dimesional array of size: 5(int), 5(int), 5(int), and 25(int)", and therein lies the misconception. The "5(int)" sections are not arrays of integers. They are "arrays of arrays". The integers only exist in the final array. --Martin

Yes I wasn't thinking dimesionally :), in the case of GFTargengBot code: buffer ends up being the 4 dimension of statBuffer that corisponds to the first 3 dimensions.. Correct? --Justin

Correct. Also, buffer doesn't get its own copy of the data. It just refers to the same memory location for the data that that branch of statBuffer does. I doubt that's really relevant, but it may become relevant in some other application, and just saying "Correct." alone seemed silly. --Martin

thx Martin :) --Justin

Credits - GFTargetingBot
Old wiki page: GFTargetingBot
Original author(s): PEZ

Old Wiki

Comments, questions, feedback:

Way cool, PEZ! It might be cool to pair this with the BasicSurfer movement and post it to the rumble, just to get a sense of a "base line" for a functioning GuessFactor gun and WaveSurfing movement. (This seems a little more polished for what it is than BasicSurfer, though...) I'm curious to hear from some other people how clear this code seems to them, as I'm already very familiar with both GuessFactorTargeting, and the PEZ style of the GF code that is found here. This should certainly be linked from a few places, including the GuessFactorTargeting/Tutorial. (I'll do some of that myself sometime soon if nobody else does.) -- Voidious

Really nice! Just a quick question what is BIN_WIDTH? It seems to be


, because the 0.7 is not really self explanatory (to me at least). Other than that it seems fine to me. -- Florent

I think using .7 instead of a true calculation is a "MiniBot-ism", as Math.asin(8/bulletvelocity(1.9)) is about .6 in radians. -- Voidious

No, it's not really minibot-ism. It's more of an approximation of the max escape angle that works for most bullet powers. But yeah, in a micro it saves spaces. I've changed the code above to include a MAX_ESCAPE_ANGLE constant. I hope that makes the code clearer. -- PEZ

Hi. I see, that you don't store your Waves in an ArrayList or Vector. Instead your GFTWave class exdends Condition. Could someone explain this point to me in more detail? By the way; I'm an absolute Greenhorn (Robocode and Java) but for some days i like to read the conversation of the godnesses from Robocode-Olymp. Sir Drake

An AdvancedRobot lets you add CustomEvents like that - it probably uses an ArrayList or Vector internally. Every tick, Robocode automatically runs the test() method of each CustomEvent, so this setup is just making use of that capability of the RobocodeAPI to take care of the waves stuff. This setup is particularly useful in CodeSize-restricted bots, as well, as it saves you a little bit of code. -- Voidious

Hmm, it's late here, and re-reading my post, that might not have completely cleared things up for you =) It does give some links that might help clear things up, but certainly feel free to ask if it's still unclear. (This is a Tutorial type bot, after all!) Don't worry about being a Greenhorn, this site is the perfect place to be for a beginner to Robocode ;) -- Voidious

In this bot I do it for clarity. Instead of adding structural code to handle the waves I just use a built-in Robocode mechanism. As long as your somewhat familiar with Robocode and its custom events then it's less blur. Note however, that if you want complete control over the execution order you might want to manage the waves list yourself. That or figure out exactly when custom events are executed in respect to the rest of your code. In this bot though I opted for as little extra code as possible. -- PEZ

I have run a TargetingChallenge2K6 with GFTargetingBot 1.02, mainly to have a reflection of GresSuffurd against another simple GF-gun. The results are a bit less than I expected, although it is clearly stated that this bot is just a basic implementation without any advanced stuff. One thing is quite obvious, to hit a WaveSurfer you do need more than this. -- GrubbmGait

Name Author Gun BFly CC Chk Cig Cya DM FM Grb RMB Tig Total
GFTargetingBot 1.02 PEZ GF 88.57 31.62 41.16 72.73 28.45 92.84 77.53 85.38 84.18 51.91 65.44

Indeed. In fact this bot is almost designed to miss a wavesurfer. Or, rather, any non-trivial WaveSurfer is designed to avoid it. Run a regular TargetingChallenge and you might see better performance from this bot. Is that a full TC2K6 run? If so, please pubish it on the appropriate results page. Good to have references like that. Especially if people base their bots on this code. -- PEZ

Results are published. I started an old TargetingChallenge, the results will be present in an hour or three. -- GrubbmGait
It has already finished, this gun is very comparable with Tityus's gun.

Name Author Type DT Asp TAOW Spar Cig Tron Fhqw HTTC Yng Funk Score
GFTargetingBot 1.02* PEZ GF 77.58 89.67 99.55 96.57 70.94 86.40 91.03 88.77 95.09 85.15 88.07

Just for grins, I DID pair this with BasicSurfer and the results were surprisingly good. It is BasicGFSurfer and ranks 47th in the RoboRumble as of 10-25-06. --Bayen

Yah, I did a merger too, and i'm trying to get mine to beat it. -- Chase-san

Okay, I'm trying to understand this code and have a couple of questions. In the GFTWave, when does the information from buffer get returned to statBuffers? It seems to me like it only takes data from statBuffers and never puts data back in. --Bayen

The magic is in this line from setSegmentation:

buffer = statBuffers[distanceIndex][velocityIndex][lastVelocityIndex];

After this, they 1D array "buffer" is set to point to one of the final dimensions of "statBuffers", so their cells point to the exact same data. This will save you from typing "statBuffers[index1][index2][index3]" every time you are accessing that data in that tick.

-- Voidious

Yah I had the same question, if Voidious' excellent explination wasn't enough you get my extremely confusing one, but one that comes with a visual represnetation...

Pointers 101: with visual aids

Here we have two different statBuffers, each with what
data they contain displayed respecibly below them.

  Main Class                  GFTWave
+-------------+           +-------------+
| statBuffers |           | statBuffers |
+-------------+           +-------------+
| 0           |           |             |
+-------------+           +-------------+

Notice how the statBuffers in GFTWave contain nothing, thats
considered a null state, or just null for short.

Now when you assign the statBuffers from the main class to
the statBuffers of the GFTWave your not actually copying the
data, no for that you would need to clone() it.

Now you have made a pointer! Congradulations.

  Main Class                  GFTWave
+-------------+           +-------------+
| statBuffers |           | statBuffers |
+-------------+  same as  +-------------+
| 0           | <-------- | 0           |
+-------------+    this   +-------------+

Now any modification you make to the data in the GTFWave
class will also take place in the main class aswell.

So when you assign or add or multiply or do whatever else to
the data in the GTFWave it also takes place in the Main class.

GFTWave:statBuffers = 1;

  Main Class                   GFTWave
+-------------+            +-------------+
| statBuffers |  actually  | statBuffers |
+-------------+ happens to +-------------+
| 1           | <--------- | 1           |
+-------------+    this    +-------------+

It also works in reverse. So anything you assign to the main class
will also happen to the data in the other class.

I explained all that just so I could make the ascii graphics. -- Chase-san

There are no threads on this page yet.