[Home]PatternMatcherBot/Java13IncompatabilityBug

Robo Home | PatternMatcherBot | Changes | Preferences | AllPages

Difference (from prior major revision) (author diff)

Changed: 155c155

I have followed PEZ's suggestion to use a StringBuffer?, and only create a String from this buffer when matching. This time i changed this in Ender's codebase, which means that from now on all my bots should be 1.3 compatible (because all my bots are derived from Ender). -- Vic

I get the following when running version 1.2:
lv.PatternMatcherBot 1.2: Throwable: java.lang.NoSuchMethodError
java.lang.NoSuchMethodError
    at lv.patternanalyzer.PatternBuffer.FindMatch(PatternBuffer.java:154)
    at lv.patternanalyzer.PatternBuffer.CheckCurrentMatch(PatternBuffer.java:87)
    at lv.patternanalyzer.PatternBuffer.log(PatternBuffer.java:78)
    at lv.patternanalyzer.PatternAnalyzer.DataLogger(PatternAnalyzer.java:297)
    at lv.Enemy.set(Enemy.java:212)
    at lv.Radar.Event(Radar.java:72)
    at lv.Ender.onScannedRobot(Ender.java:225)
-- PEZ

Could that be a java 1.3 compatibility issue? I compiled with -target 1.3 and that compiled error free. But this sounds like i'm using a library class method that doesn't exist in your java version. I'll send you the source of the FindMatch?() method so you can scan it for non 1.3 methods....still don't understand why it compiles with -target 1.3 though...... -- Vic

Yes, that's probably it. Because I could run it with Java 1.4.1 (even if I can't watch the game. Post the relevant code here and we could all help finding the incompatible call. -- PEZ

ok, here it is:

	public void FindMatch()
	{
		MatchPoint = -1;														//reset
		TrackPoint = -1;														//reset
		
		int maxpattern 		= 1000;												//longest possible pattern to match against
		int i 				= LastPatternLength;								//start matching at the same length as last time
		int highestmatch 	= 3;												//at least a string of 3 characters needs to match
		int lowestfail 		= maxpattern + 1;											
		
		int index;
		boolean searching = true;
						
		if(lowestfail > patternbuffer.length())
		{
			lowestfail = patternbuffer.length();								//just in case the buffer is not yet full enough
		}
		
		do						//the outer loop will increase the pattern size each time a matching pattern was found
		{
			String testing = patternbuffer.substring(patternbuffer.length() - i);
			index = 0;
			while(patternbuffer.indexOf(testing, index) > -1)
			{			
				boolean OK = true;
				
				index = patternbuffer.indexOf(testing, index);								//seek the pattern
				if (index >= (patternbuffer.length() - i - LookAhead))
				{
					index += LookAhead;
					if(index < (patternbuffer.length() - i - LookAhead))
					{
						OK = false;
					}
					else
					{
						index = -1;
					}
				}
				else 
				{
					int EOP = checkEndOfPattern(index+i);
					if ( EOP > -1)
					{
						index += (EOP + i);									// shift forward by patternlength + position of # in lookahead
						
						if(index < (patternbuffer.length() - i - LookAhead))
						{
							OK = false;
						}
						else
						{
							index = -1;
						}
					}
				}
				
				if(OK)
				{
					break;
				}
			}
			
			if(index > -1)
			{
				highestmatch = i;											//mark the longest pattern found so far
				MatchPoint = index;											//mark start of pattern
				TrackPoint = index + i;										//mark end of pattern
				i *= 2;														//try double pattern length
				if(i >= lowestfail)											//except when this tops the lowest failing pattern length
				{
					i = lowestfail - 1;										// then try one less then the lowest failing
				}
			}
			else
			{
				lowestfail = i;												//mark the shorter pattern that failed to match
				i = (int)Math.round(((highestmatch + lowestfail) / 2.0));	//try a shorter pattern
			}
			
			if(highestmatch + 1 >= lowestfail)								//if failing pattern == succesfull pattern + 1 then we are ready
			{
				searching = false;											//break the loop
			}
			else if(i >= maxpattern)										//we have reached the maximum pattern length, so quit
			{
				searching = false;											//break the loop
			}
		}
		while (searching);

		if(MatchPoint >= 0)
		{
			LastPatternLength = highestmatch;									//remember this for the next time
		}
		else
		{
			//System.out.println(" NO MATCH :-(");
		}
			
		checkBestMatchOfTheRound();											// Check if our new match is a record breaker :-)
	}

-- Vic.

PEZ pointed me to the problem: a StringBuffer? has no indexOf() method in java 1.3 :-( I'll see if i can work around this -- Vic

PEZ, i made a new version of PatternMatcherBot exclusively for you ;-) Exclusively, because i'm not releasing a public version. That's because i've observed that the performance has degraded slightly, causing some more skipped turns and missed scans. It doesn't seem to effect the results, but i won't take any chances here. However this version might be useful to you for visual feedback. I do suggest that you use JVM 1.4.1 minimized with the public 1.2 version to do your 'official' runs :-)

Maybe you know why there is a degradation in performance? I'll tell you what i've done:

In the java api docs i've read that String concatenation is performed by a stringbuffer (probably the Stringbuffer is created from the string .... at size 15000 that's not a small deal!) and because this happens every scan it's quite expensive. If i were to use a StringBuffer? and only convert it to a String when i'm matching then i would have the same type of conversion and probably the same performance penalty.

Concerning your 1.4.1 MacOS? problem: are you sure there's nothing you can do about it? I've read some people have installed the latest revisions of the virtual machine to solve some other problems, so maybe that can be the solution for this problem as well. But...you probably already looked into that so never mind...

-- Vic.

Yeah, the String += 'c' does involve concatenation (creating a new String) and re-assignment, since Strings in Java are final (their internal value is not changed after they are created). -- Kawigi

There's no need to use the concatination operator. I think the only use for that operator is for using together with println() type of functions. Just use a StringBuffer? and pick out the substrings you need for the matching. As long as you do it only once per match it doesn't cost too much. As for my 1.4.1 problems; just take my word for it that I have tried. And I consider bots that don't run on Robocode supported platforms being defected. I haven't tried your patched version yet, but I fear it might be even slower than the non-patched one which runs really slow on my computer. LeachPMC runs about 5 times faster and it's 1.3.1 compatible. But it could be a 1.4.1 issue on MacOSX so I'll be back in a jiffy when I have tested the patched version. -- PEZ

OK, so now I have tested it. It's a bit faster than the unpatched version on my machine. Thanks! -- PEZ

It's true that Ender's gun is not very fast. I know of some improvements i could make, but i have some other priorities on my list :-) Thanx for your suggestions. -- Vic

I have followed PEZ's suggestion to use a StringBuffer?, and only create a String from this buffer when matching. This time i changed this in Ender's codebase, which means that from now on all my bots should be 1.3 compatible (because all my bots are derived from Ender). -- Vic


Robo Home | PatternMatcherBot | Changes | Preferences | AllPages
Edit text of this page | View other revisions
Last edited June 30, 2003 11:07 EST by Vic Stewart (diff)
Search: