Page 1 of 1

Radio - shuts off when think returns null

Posted: Sun Mar 16, 2008 5:51 am
by gorzak
I've had a heck of a time making the radio work the way I expect. What I understood from this thread and the SDK was that the radio variable would be read regardless of what was returned via think. The behavior I seem to be able to count on is different. Returning the instance of the bot (via this) has the expected behavior, but returning null turns the radio off.

I am kinda new to this, so this code may not be pretty. It was the best I could do to demonstrate this surprise.

Code: Select all

public class RadioTest {
	public int orderType=1; // move by default
	public double destX = 25;
	public double destY = 25; //middle of the board
	public int[] radio = new int[4]; // we'll use this to communicate with other bots
	
 	public Object think(final double dx, final double dy, final double x, final double y, final boolean moving, final int terrain, final int ourID, final int ourType, final double hp, final double maxHP, final double range, final double time, final double[] objX, final double[] objY, final int[] objID, final int[] objFaction, final int[] objType, final int[][] incomingRadio) {
		
		if (moving) return null;
		
/* the next condition will not be met when you expect. If "return null" is used 
as in this example, it will never be met. If only "return this" is used bots 
stutterstep due to new order delay. If you combine them, you get the worst of 
both, bots twitching around with thier radios off and on based on what you 
returned last. */
		if ( radio[0] == 1 && incomingRadio.length > 5) {//if you are a transmitter, and there are more than 5 radios on
			orderType = 1; //move to the center of the board when the condition is met.
			return this;
		}
/* Here is more proof of whats going on. the only bots eligable to move to the 
center are ones that set a transmitting flag. that can ONLY happen if they see
no one else transmitting. if you change the condition to "return this" where I 
suggest it below, you willsee some of the newly created bots moving toward the 
center. that means no radio transmissions were detected when they were finished
being built. */
		if ( incomingRadio.length == 0 || radio[0] == 1 ) {//if no one is transmtting, or if I am transmitting
				orderType = 2; //stop
				radio[0] = 1; //  transmitting flag
				radio[2] = (int) x; // transmit this bots location
				radio[3] = (int) y; // transmit this bots location
				return this;
				
		}else{//someone is transmitting
			
			radio[0] = 2; //listening flag set
			int lowestTransmitterID = 10000;
			int lowestTransmitterReference = 10000;
			for (int i = 0; i < incomingRadio.length; i++) {//check the transmitters
				int[] ir = incomingRadio[i];
				if (ir[1] == 1 && (ir[0] < lowestTransmitterID)) {
					lowestTransmitterID = ir[0];
					lowestTransmitterReference = i;
				}
			}// now we know the id and reference of the lowest transmitter
			
			if (radio[1] != lowestTransmitterID){// our second radio element doesnt match the lowest transmitters ID
				radio[1] = lowestTransmitterID; // remember and transmit the ID of this transmitter
				destX = incomingRadio[lowestTransmitterReference][3]; // set aim on the transmitted location
				destY = incomingRadio[lowestTransmitterReference][4]; // set aim on the transmitted location
				orderType = 1; //move
				return this;
			}else{//it does match, we are following the right transmitter
				
/* Here we have a problem. "return null;" shuts the radio off as long as 
the transmitter is in range. "return this;" turns it on, but reissues the move
 order. once it starts moving agin, it can't continue without returning null, 
shutting the radio off again ~3 time units later. (I think the radio is on 
during the order delay penalty. If it isn't, then its only .4 time later.)*/
				return null; // carry on
				
				
			}
		}
	}
	public int build(final double dx, final double dy, final double x, final double y, final int terrain, final int id, final int buildItem, final double hp, final double maxHP, final double time, final double[] objX, final double[] objY, final int[] objID, final int[] objFaction, final int[] objType, final int[][] incomingRadio) {
		radio[0] = 333; radio[2] = 25 ; radio[3] = 25;
		if (buildItem != 0) return 0;
		if (time < 30) return 2;
		return 1;
	}
}
If it is supposed to work like this, thats fine by me. I can work with it now that I understand whats going on.

Posted: Sun Mar 16, 2008 6:35 am
by adum
gorzak -- sorry for the confusion. i think you have described the behavior correctly -- if your think method returns null, the radio will not be updated. that's not the behavior i wanted originally and i may fix this at a later date, but for now, you can only change radio when returning an order, as you figured out.

thanks,
adum

Posted: Sun Mar 16, 2008 8:07 pm
by gorzak
I am sure it's my fault, but I feel like there is a misunderstanding.

When you say the radio will not be updated, it implies to me that the last update will continue to transmit. That is not the behavior my example demonstrates.

My example code always returns the bot after changing the radio, so if it continued to transmit, then incomingRadio.length would continue to increase until the initial condition was met. Every branch initially turns the radio on and returns the bot. No branch zeros out the radio vars. Even so, the bots stop transmitting.

When I say the bots stop transmitting, I don't mean they continue to transmit thier previous radio before an update, I mean they drop out of incomingRadio altogether.

After the first bot, who only continues to transmit because I return him with a stop order every time, the listening bots do this:
There are existing transmissions
I set a listening flag on my radio[0] and determine the ID and reference of the flagged transmitter
My radio[1] doesn't match the ID of the transmiter
I store thier ID there, and I move to their transmitted location
- at this point, the bot has done "return this" to issue the move order. The radio is updated, and incomingRadio.length will increase for other bots.

The very next think call, the same bot does this:
There are existing transmissions
I set a listening flag on my radio[0] and determine the ID and reference of the flagged transmitter
My radio[1] matches the ID of the transmitter
I don't change my orders
- now the bot has done "return null". There were no radio var changes, so no need to update any transmissions. Instead of continuing to transmit its previous radio however, it's radio goes OFF. incomingRadio.length will decrease for other bots. Last turn it was transmitting, it has not changed its radio vars, yet this turn it will not transmit.

If you compile my code and watch, you can visibly verify that every bot has its radio vars non zero. the first bot sits there, the 2nd and all following bots move to it. That they move to it and not the center of the board means they recieved the first bots transmission. That they moved at all means they set thier radio. Nevertheless, you can also visibly verify that the first bot never sees more than 5 radios on. The first bot never even sees 2 radios on (I am still figuring cities out, I don't think they think, but if they do, he may see 2 but not 3), because each bot shuts thiers off by returning null long before the next bot is built.

I hope this clears up any misunderstandings I may have caused.
Thanks,
Gorzak

P.S. I found a way to get around this limitation, but I am sure it goes against the intended function of the game. I have sent it to you via PM, you are welcome to do with it what you will.

Posted: Tue Mar 18, 2008 3:42 am
by Captain Segfault
I've noticed that if you return an object with a 0 command type it sets the radio without stopping the bot.

It also keeps the radio up.