Forum: General

Threads

Hii!

Is there any option to control from one bot(thread) the other bots(threads)?

I need to do some stuff with the bot_1 (operations) and the other threads need those operations to act, but i don't know how to do it because i don't know enough how works pogamut with threads.

i tried to get the threads and call wait() until i finish the operations and after that, i resume them with notify() but it seems that there are some errors with all these stuff.

Any suggestion? :-)
How it works:

Each bot in PogamutUT2004 has two threads.
1) GB2004 consumer
-- constantly reads messages from the GB2004 connection
2) Logic
-- thread that is running logic() method of the UT2004BotModuleController

However, these two threads may never collide, their work is controlled by the WorldView as the data flow looks like this
GB2004 consumer | WorldView | Logic

Once the Logic thread wants to execute logic(), it locks the WorldView, which prevents any modifications to the data while the Logic thread is running, that is any new messages from GB2004 consumer is buffered and their processing is postponed, till the Logic thread finishes and unlocks the WorldView again. From the bot-programmer, it seems like there is only a single thread in there.

But, if you are going to run 2+ bots in the same JVM and wants to access each others data structure, surely concurrency issues might pop out. If that is the case, I would suggest to create public static Object mutex = new Object() somewhere and synchronize( mutex ) { ... all critical operations ... }.

However, it might not be enough depending on what components you would like to use. For instance, WorldView is written the way that it should be thread-safe, but modules like AgentInfo, Players, etc. might not. You will have to experiment.

May be, if you can describe your scenario, I can provide you with more insights.

Cheers!
Jimmy
Hi Jimmy!

First of all, thanks for your help
^

I just need to use the logic module. I'm working with the bots to create a better bot after a certain time, so in the logic module, every 20 seconds, each bot writes in a personal file it's own information (health, deads,...). After 2-3min one bot should stop the other bots and read all the files, create a new file with all the data from the bots and generate a new file for each bot. All these stuff is done in the logic module without pausing the threads. In this case the execution is quite good but almost always the execution fails because some bot is trying to read a file that doesn't exist yet.

I know there's always one thread which id is "10", so i decided that this thread will manage all the others.

if(thread_id == 10)
{
Thread[] threads = new ThreadThread.activeCount();
int numThreads = Thread.enumerate(threads);
int index = 0;
for (int i = 0; i < numThreads; i++)
{
if(((int)(threadsi.getId())) != 10)
{
synchronized(threadsi)
{
try{
threadsi.wait()
}
catch(Inter...)
{
System.err...
}
}
}
}
}

This is the code that i use to try to manage the bots. would you still using the same that you said before with the mutex?

Thanks for everything
^
Notice, that there is a possibility to pause/resume the agent from outside.

UT2004BotModuleController.bot.pause() / .resume() should work for you.

Cheers!
Jimmy
Seems to be the best way for me but.. in this case, how could i manage all the bots from one bot?
I can get the bot id from it's own thread but i don't see anything that lets me access to other bots.

(sorry if i ask dumb questions ^^').

Cheers!
Joan Marc.
No, Pogamut does not track "list of executed agents", its not multi-agent platform in broad sense of the term.

I would do it through some workaround, e.g., create static List of slave bots you want to control from master bot
and let master bot to work with that list.

Would that work for you?

Cheers!
Jimmy
It would work perfectly!
I just need one bot or whatever to manage the other bots, i don't mind if that bot/thread doesn't do anything else.

Could you tell me more or less how can i get that list? Maybe i need to create that list in the main or something like that?

Thanks :-)

Joan Marc.
Exactly in the main() method.

1) start ALL SLAVES
2) save their instances into public static List
3) start MASTER
-> have the MASTER access that static list of UT2004Bot instances

It has some drawbacks in case of failures of single bot (e.g., the JVM won't terminate if one of your bots fails),
but I guess you should start with that.

Cheers!
Jimmy
i tried this but its not working:

1) new UT2004BotRunner(SmartBot.class, "SmartBot").setMain(true).StartAgents(4);
2) ????
3) new UT2004BotRunner(SmartBot.class, "MasterBot").setMain(true).StartAgents();

I don't know how to ghet the 4 instances ^^'. Also i have a doubt/problem. In this case, if i launch 4 bots + the master separately, the master does not run. It is because they are using the same class?

Thanks!

Joan Marc.
setMain(true) is wrong name ... more suitable name is "setBlocking" ... you should definitely use setMain(false)
That's why your master bot is not starter.

Cheers!
Jimmy
This way it seems to work
1) new UT2004BotRunner(SmartBot.class, "SmartBot").setMain(false).StartAgents(4);
2) ????
3) new UT2004BotRunner(SmartBot.class, "MasterBot").setMain(true).StartAgents();

But now how can i get the instances of the smartbots? :-S

Thanks for everything jimmy!
Joan Marc.
Check .StartAgents(4) return type ;-)

List startAgents(int count)

it will return List of UT2004Bot instances.

Check out UT2004Bot.getController() method.

Cast its result to SmartBot class.

Cheers!
Jimmy
i think i got it!

i've created a list for the instances:

Private static List botInstances;

and i've initialized it in the main menu:

public.. main...
{
botInstances = new UT2004BotRunner(SmartBot.class, "SmartBot").setMain(false).StartAgents(4);
new UT2004BotRunner(SmartBot.class, "MasterBot").setMain(true).StartAgents();
//question: should i create another list only for the masterBot instance?
}

After all this, in the MasterBot logic part i would do something like this:
for(i = 0:num_bots)
((SmartBot)botInstances.get(i).getController()).getBot().pause();
  • operations*
for(i = 0:num_bots)
((SmartBot)botInstances.get(i).getController()).getBot().resume();

is this what you meant before? :-)
Yes,
please note that "pause()" operation is not blocking.

You should use WaitForAgentStateChange class after you call pause() and wait till the agent get into
the IAgentStatePaused.class state.

new WaitForAgentStateChange(agent.getState(), IAganeStatePaused.class).await()

same for resuming and IAgentStateRunning.class

Cheers!
Jimmy
so i have to do a new list var to save this:

new WaitForAgentStateChange(((SmartBot)botInstances.get(i).getController()).getBot().pause(), IAgentStatePaused.class).await();

but when i do it appears an error saying " 'void' type not allowed here" so i understand that botInstances is void?

another question. when the thread is blocked it reaches the new state "paused" right? but when it reaches this state, i guess that the bot has finished the logic block iteration right? or it could get into the paused state when it's in the middle of the logic block?

Thanks for everything!
I'ld but you a pata negra ham!!

Joan Marc.
Hi!!

Any idea?
Good night!

I'm still trying to stop the bots but i don't get it ^^'

I tried with new WaitForAgentStateChange(((SmartBot)botInstances.get(i).getController()).pause(), AgentStatePaused.class).await();

but (SmartBot)botInstances.get..... returns void insted of void (WaitForAgentStateChange arg #1 has to be null).

So i decided to try this other way, which first argument is null but then the bots doesn't stop. (i understand that bots should stop moving while im inside the game)

new WaitForAgentStateChange(((SmartBot)botInstances.get(i).getController()).getState(), AgentStatePaused.class).await();
I also realized that when the masterbot tries thi method (...getState()). he gets stuck here forever, it's like he's waiting for the ther bots to get paused.

Coul you help me?

Thanks.

Joan Marc.
Can you post here complete (relevant part) of the code that should stop (or pause?) your bot?

Best,
Jakub
Of course!

//i get the bot instantces in main
public static void main(String args[]) throws PogamutException {
botInstances = new UT2004BotRunner(SmartBot.class, "SmartBot").setMain(false).startAgents(num_bots);
new UT2004BotRunner(SmartBot.class, "MasterBot").setMain(true).startAgent();
}

//in the logic module
if((bot.getName()).contains("MasterBot"))
{
for(int i = 0; i < num_bots; i++)
await = new WaitForAgentStateChange(((SmartBot)botInstances.get(i).getController()).getBot().getState(), IAgentStatePaused.class).await();
}

Thanks,
Joan Marc.
Hi, thanks!

However, I don't see any "pausing slave bots" code here

for(int i = 0; i < num_bots; i++)
await = new WaitForAgentStateChange(((SmartBot)botInstances.get(i).getController()).getBot().getState(), IAgentStatePaused.class).await();
}

This just "waits" for bots to get into the PAUSED state. Are you using slaveBot.pause() anywhere?
See: http://pogamut.cuni.cz/pogamut_files/latest/doc/javadoc/
Find class AbstractAgent and method pause()

Cheers!
Jimmy