Forum: PogamutUT2004

Launching Multiple Bots of Different Types

The MultipleUT2004BotRunner only seems to allow for the launching of multiple bots of a single type. What if I want to launch multiple bots at the same time but of different types. If a way to do this does not exist yet, then can you help me write my own class to accomplish this? Furthermore, I'm not certain if there is a way to use the Class objects to create bots using a zero-parameter constructor. Is there a way to use constructors that take input parameters?

What I'm getting at is a way to evolve bots, but I want to evolve them against scripted bots. Therefore, as long as I'm asking about the BotRunner class, I might as well ask about how to run bot evaluations in sequence. The JavaDoc says that MultipleUT2004BotRunner and SingleUT2004BotRunner block, such that only one instance can run at a time. However, I would assume that if I terminate a running instance of either BotRunner it would be safe to start a new one. What is the appropriate way to terminate the startAgent() method of one method so that I can start a new one?
First off, I'm not part of the staff, just thought I'd drop my thoughts :-)
Secondly, I can't guarantee you that this will work for you.

I implemented this static class in my parent class for all bots I've made. I've had no problem starting multiple bots of the same type from each type's respective static main method. I don't see why you shouldn't be able to adapt this to an "experiment" class which calls the respective type's main method. Might be worth a try :-)

I couldn't get the code field to work (maybe it's Chrome?) so I've extracted the method body and removed all generics fields, so you'll get warnings if you compile with -xlint:unchecked.
botClass is any class that derives from UT2004BotModuleController(UT2004Bot)

UT2004BotFactory factory = new UT2004BotFactory(new UT2004BotModule(botClass));
UT2004BotRunner botRunner;
if(host == null) {
botRunner = new UT2004BotRunner(factory, name);
}
else {
botRunner = new UT2004BotRunner(factory, name, host, port);
}
return botRunner.startAgent();
Hi!

By popular demand, I'm going to implement one more "bot runner" class that will accept the array of bot classes and start it :-)
Hopefully somewhere tomorrow! But it will be available through SVN only (for now).

Cheers,
Jakub
I'm glad to hear that, though there is still one part of my original question that is unanswered. Re-reading it, I should probably have asked it more clearly:

How do I send input parameters to a constructor when launching a bot? The factory method seems to launch the zero-parameter constructor only. If I'm going to evolve things, then I'm going to need to pass in a genome of some sort in the constructor for the bot.

I can think of a way to fill in this information after the bots are constructed, but this seems like messy code to me. I'm just hoping I can give the bot this info via a constructor instead of by assigning it after construction.
Hi! That would be more tricky.

There is no consensus among Pogamut team members how this should be done, but here is one way that is achievable already:

I'm going to describe the code, you're probably aware of (as you write):

SingleUT2004BotRunner as well as MultipleUT2004BotRunner has method


/**
* Custom hook called after the agent is instantiated by the {@link RemoteAgentRunner#factory} and before
* the {@link IAgent#start()} is called.
* @param agent
*/
protected void preStartHook(T agent) throws PogamutException {
}

/**
* Custom hook called after the agent is instantiated by the {@link RemoteAgentRunner#factory} and
* started with {@link IAgent#start()}.
* @param agent
* @throws PogamutException
*/
protected void postStartHook(T agent) throws PogamutException {
}


This method (postStartHook) is going to be called everytime a new agent is created (preStartHook) and started (postStartHook). This way, you may inject whatever you want into the agent's instance. Note that you will do something like:


new MultipleUT2004BotRunner(3, NavigationBot.class, "NavigationBot") {
protected void preStartHook(UT2004Bot agent) throws PogamutException {
((NavigationBot)agent.getController()).setSomething(myconfig++index);
};
}.startAgent();


This way you may pass configs into newly created agents.


Another way would be through Guice which I'm going to implement as well. Basicly, I will create an
IAgentParameters interface that you may put into the constructor of the IUT2004BotController implementor and specify the bindings for this via Guice letting Guice to inject these parameters into the constructor for you.

Best,
Jakub

>By popular demand, I'm going to implement one more "bot runner" class that will accept the array of bot >classes and start it
>Hopefully somewhere tomorrow! But it will be available through SVN only (for now).

Thanks for the help. When this class becomes available in the SVN, can you post a message here directing us to its exact location? I've gotten lost in the SVN repository a couple of times.
Ok, it is committed,
I'm going to work on "parametrization" of the agents now.

The conrete class in svn is at:
http://artemis.ms.mff.cuni.cz/websvn/filedetails.php?repname=Pogamut&path=%2Ftrunk%2Fproject%2FPogamutUT2004%2Fsrc%2Fcz%2Fcuni%2Famis%2Fpogamut%2Fut2004%2Futils%2FMultipleUT2004BotRunner.java

Note that the MultipleUT2004BotRunner has "pausing" feature. By default, it will pause all newly started bots and have them paused until it spawns all bots into UT2004. MultipleUT2004BotRunner will resume them all at once then. This behaviour may be disabled by calling .setPausing(false)

Cheers!

P.S.: hopefully, IAgentParameters interface + support in factories / guice / runner will be available today at night.
Well, as I'm looking into repo, I've already started some implementation regarding agent parameters.

The API for creating / starting agents must be changed (not too much but new interfaces are going to be incompatible).

But it will work well (hopefully ;-)).

Best,
Jakub
I've tried out the new constructor in MultipleUT2004BotRunner, and am running to a problem. The bots seem to be confused about the presence of enemy bots in the world, and crash as a result of a NullPointerException when getNearestEnemy is called. This happened with my own bot, but I also verified the the problem occurs with the provided Hunter bot. All I did was change the line in the main method to be:

MultipleUT2004BotRunner.BotDescriptor hunters = new MultipleUT2004BotRunner.BotDescriptor(4,Hunter.class, "Hunter");
new MultipleUT2004BotRunner(hunters).startAgent();

What's wrong?
Nevermind. The problem seems to be fixed by setting pausing to false. This seems a bit odd though. Could the bots be running their logic methods even though they are paused? I would imagine that player senses would be strangely affected by the presence of paused bots.
The problem lies in DistanceUtils.java - I've fixed that with that commit as well :-) ... I think that the problem lies in GB2004 that exports PLR informations in the handshake (info about Players) with 'visible' set to TRUE which confuses the bots. We will investigate it more thoroughly as DistanceUtils fix is a bit "hot" one.

Cheers!
Jakub

P.S.: Have you tried to run different types of bots using MutlipleXXX ? I admin I haven't tested that (shame on me...).
I'm able to run bots of up to two types when I set pausing to false. I haven't tried the fixed DistanceUtils yet though.
Could someone kindly guide me where to find setPausing(boolean). I checked inside MultipleUT2004BotRunner, however I cannot find the method.

Juts for your info, I have EmptyJavaBot and ResponsiveBot packages.

Thanks
Hi dirkmalta and welcome to the forum!

Which version of Pogamut 3 are you using?

In current trunk (more of in devel stage right now) the MultipleUT2004BotRunner is extending MultipleAgentRunner which have method setPausing(boolean) defined.

Cheers!
Jimmy
Thanks Jimmy.
The Pogamut 3 version I installed is 'Pogamut-3-install-all-v3.0.11'.

The following is a full copy&paste of MultipleUT2004BotRunner:

package cz.cuni.amis.pogamut.ut2004.utils;

import java.util.concurrent.CountDownLatch;

import cz.cuni.amis.pogamut.base.agent.IAgent;
import cz.cuni.amis.pogamut.base.agent.impl.AgentId;
import cz.cuni.amis.pogamut.base.agent.state.level0.IAgentState;
import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateDown;
import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateGoingDown;
import cz.cuni.amis.pogamut.base.agent.state.level2.IAgentStateFailed;
import cz.cuni.amis.pogamut.base.agent.utils.runner.impl.RemoteAgentRunner;
import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnectionAddress;
import cz.cuni.amis.pogamut.base.utils.Pogamut;
import cz.cuni.amis.pogamut.base.utils.PogamutPlatform;
import cz.cuni.amis.pogamut.base.utils.PogamutProperty;
import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004BotFactory;
import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004BotModule;
import cz.cuni.amis.utils.exception.PogamutException;
import cz.cuni.amis.utils.exception.PogamutInterruptedException;
import cz.cuni.amis.utils.flag.FlagListener;

/**
  • This class has only one purpose - execute ONE OR MORE BOTS inside 'main' method. You can't use it for anything else!
  • It is THE SHORTCUT of all SHORTCUTS to execute multiple bots, wait till they finishe and close the whole Pogamut.
  • Designed especially for the usage inside NetBeans projects.
  • NOTE: It's not even meant to be instantiated twice for two different batch of bots and consequently executed in two different threads!
  • Single-purpose class only ;-)
  • NOTE: It might be very interesting for you to check out the source of method {@link MultipleUT2004BotRunner#startAgent()} to
  • see how the agent should be instantiated via {@link UT2004BotFactory} using {@link UT2004BotModule}.
  • @author Jimmy
  • /
public class MultipleUT2004BotRunner {

protected String host;
protected int port;
protected int number;
protected UT2004BotFactory factory;
protected String name;

private Object agentCounterMutex = new Object();
private int agentCounter;

/**
* Constructs the runner so the newly created bots will be controlled by 'controllerClass' has name 'name' and will connect to 'host:port'.
* @param number how many bot instances with 'controllerClass' should be created
* @param controllerClass class that controls the bot's behavior
* @param name name of the bot
* @param host where it should connect (host of GB2004 bot connection)
* @param port to which port it should connect (port of the GB2004 bot connection)
*/
public MultipleUT2004BotRunner(int number, Class
My fault... it's been a long time since 3.0.11 version.

Unfortunately you won't find setPausing probably there,
please wait a few days if possible, Pogamut 3.1 will be out very soon.

Or you might want to use SVN version directly? Even though that is much less comfortable :-(

Best,
Jimmy
Well, Pogamut 3.1 can be already downloaded at Download page. As far as I know the installer works and PogamutUT2004 should be ok too. So you can try it already.

best,
michal
Apologies for the delay in my response, however I came up a solution! ;)

First and foremost I would like to thanks Jimmy & michal for their replies!
I downloaded and installed Pogamut 3.1, however I was having issues with the following imports:

import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Initialize;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BotKilled;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.InitedMessage;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Item;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
import cz.cuni.amis.pogamut.ut2004.utils.SingleUT2004BotRunner;

The only package I had available inside ut2004 was:
cz.cuni.amis.pogamut.ut2004.example

So I re-installed ‘Pogamut-v3.0.999’, and then both my Tutor and I got together and modified some code and managed to get 2 different bots with different behavior to be loaded in the same level. Here are the steps:

(1) Create two separate packages. In our case one Hunter Bot and one Navigation Bot
(2) Cut all java files from either of the Bots Source Packages, and Pasted them into the other Bot Source Packages.
(3) Create a new Java Class inside Source Package where all other files are located. Name it as you please, in our case we named the file “MultipleBots”;
(4) Next is to open ‘MultipleUT2004BotRunner’;
(5) Copy all code inside ‘MultipleUT2004BotRunner’;
(6) Paste it inside file you created in Step (3);
(7) Next is to adjust the code pasted inside “MultipleBots”, as follows:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package cz.cuni.amis.pogamut.ut2004.examples;

import java.util.concurrent.CountDownLatch;

import cz.cuni.amis.pogamut.base.agent.IAgent;
import cz.cuni.amis.pogamut.base.agent.impl.AgentId;
import cz.cuni.amis.pogamut.base.agent.state.level0.IAgentState;
import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateDown;
import cz.cuni.amis.pogamut.base.agent.state.level1.IAgentStateGoingDown;
import cz.cuni.amis.pogamut.base.agent.state.level2.IAgentStateFailed;
import cz.cuni.amis.pogamut.base.agent.utils.runner.impl.RemoteAgentRunner;
import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnectionAddress;
import cz.cuni.amis.pogamut.base.utils.Pogamut;
import cz.cuni.amis.pogamut.base.utils.PogamutPlatform;
import cz.cuni.amis.pogamut.base.utils.PogamutProperty;
import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004BotFactory;
import cz.cuni.amis.pogamut.ut2004.factory.guice.remoteagent.UT2004BotModule;
import cz.cuni.amis.utils.exception.PogamutException;
import cz.cuni.amis.utils.exception.PogamutInterruptedException;
import cz.cuni.amis.utils.flag.FlagListener;

/**
* This class has only one purpose - execute ONE OR MORE BOTS inside 'main' method. You can't use it for anything else!
* It is THE SHORTCUT of all SHORTCUTS to execute multiple bots, wait till they finishe and close the whole Pogamut.
*
* Designed especially for the usage inside NetBeans projects.
*
* NOTE: It's not even meant to be instantiated twice for two different batch of bots and consequently executed in two different threads!
* Single-purpose class only ;-)
*
* NOTE: It might be very interesting for you to check out the source of method {@link MultipleUT2004BotRunner#startAgent()} to
* see how the agent should be instantiated via {@link UT2004BotFactory} using {@link UT2004BotModule}.
*
* @author Jimmy
*/
public class MultipleBots {

protected String host;
protected int port;
//protected int number;
//protected UT2004BotFactory factory;
protected String name;

private Object agentCounterMutex = new Object();
private int agentCounter;

/**
* Constructs the runner so the newly created bots will be controlled by 'controllerClass' has name 'name' and will connect to 'host:port'.
* @param number how many bot instances with 'controllerClass' should be created
* @param controllerClass class that controls the bot's behavior
* @param name name of the bot
* @param host where it should connect (host of GB2004 bot connection)
* @param port to which port it should connect (port of the GB2004 bot connection)
*/
public MultipleBots(String name, String host, int port) {
//this.factory = new UT2004BotFactory(new UT2004BotModule(controllerClass));
this.name = name;
this.port = port;
this.host = host;
//this.number = number;
//if (number < 0) throw new IllegalArgumentException("Can't have < 0 bot instances.");
}

/**
* Returns agent id for a new agent.
*
* Set {@link RemoteAgentRunner#name} in {@link RemoteAgentRunner#preInitHook()} to change the name of the agent.
* @return
*/
public AgentId getAgentId() {
synchronized(agentCounterMutex ) {
return new AgentId(name + ++agentCounter);
}
}

/**
* Constructs the runner so the bot will be controlled by 'controllerClass' has name 'name' and will connect to
* host and port according to the property file.
* @param number how many bot instances with 'controllerClass' should be created
* @param controllerClass
* @param name
*/
public MultipleBots(String name) {
this( name,
Pogamut.getPlatform().getProperty(PogamutProperty.POGAMUT_UT2004_BOT_HOST.getKey()),
Pogamut.getPlatform().getIntProperty(PogamutProperty.POGAMUT_UT2004_BOT_PORT.getKey()));
}

/**
* Where the bot is going to connect.
*/
public SocketConnectionAddress getAddress() {
return new SocketConnectionAddress(host, port);
}

// fields used by startAgent()
private boolean agentsKilled = false;
//Variable "agents" is used to keep all bots which are to be loaded
private UT2004Bot[] agents;
private CountDownLatch latch;

/**
* Kills are instances inside {@link MultipleUT2004BotRunner#agents} but only if {@link MultipleUT2004BotRunner#agentsKilled} flag
* is down (raises this flag in the end to prevent future misusing).
*/
private void killAgents() {
if (agentsKilled)
return;
synchronized(agents) {
if (!agentsKilled) {
agentsKilled = true;
for (int i = 0; i < agents.length; ++i) {
if (agentsi == null)
continue;
if (agentsi.notInState(IAgentStateDown.class, IAgentStateGoingDown.class)) {
agentsi.kill();
}
}
while (latch.getCount() > 0)
latch.countDown();
}
}
}

/**
* Starts all the bots and waits till they finishes. Whenever one of them fail (exception is caught), all bots are tore down.
*
* It closes the Pogamut platform in the end via {@link PogamutPlatform#close()} to ensure that the JVM will exit.
*
* WARNING: use this only inside 'main' method to start MULTIPLE bots of the SAME controller!
*/
public synchronized void startAgent() throws PogamutException {

preAllInitHook();
final int number = 2;//Determines the number of bots
agents = new UT2004Botnumber;
for (int i = 0; i < number; ++i) {
agentsi = null;
}
agentsKilled = false;

FlagListener[] agentStateListener = new FlagListenernumber;

latch = new CountDownLatch(number);

try {
for (int i = 0; i < number; ++i) {
synchronized(agents) {
if (agentsKilled)
break;

//QUICK HACK
/*Following hack in going to create EXACTLY 2 bots by using the switch statement
IMP that this is an early hack so we understant this might be a cheap hack, but it works!
Next on TODO is to build a GUI which will allows total freedom on the amount of bots*/
UT2004Bot agent;

preInitHook();
UT2004BotFactory factory;
switch (i)
{
case 0:
factory = new UT2004BotFactory(new UT2004BotModule(Hunter.class));
break;
case 1:
factory = new UT2004BotFactory(new UT2004BotModule(NavigationBot.class));
break;
default: throw new IllegalArgumentException("You need to specify another case for the type of bot you want to create");
}
agent = (UT2004Bot) factory.newAgent(getAgentId(), getAddress());
agentsi = agent;

agent.getLogger().addDefaultConsoleHandler();
// DO NOT ALTER LOGGING LEVEL HERE!
// Default logging level is taken from the property file.
// Additionally if the user wants to set logging level, he/she should use 'preStartHook'.

FlagListener listener = new FlagListener() {
@Override
public void flagChanged(IAgentState changedValue) {
if (changedValue instanceof IAgentStateFailed) {
killAgents();
} else
if (changedValue instanceof IAgentStateDown) {
latch.countDown();
}
}
};

agent.getState().addListener(listener);
agentStateListeneri = listener;
preStartHook(agent);
agent.start();
postStartHook(agent);
}
}

postAllStartHook(agents);

try {
latch.await();
} catch (InterruptedException e) {
throw new PogamutInterruptedException("Interrupted while waiting for all agents to finishes.", e, this);
}
} catch (Exception e) {
killAgents();
if (e instanceof PogamutException)
throw (PogamutException)e;
throw new PogamutException(e, this);
} finally {
try {
for (int i = 0; i < agents.length; ++i) {
agentsi = null;
}
} finally {
Pogamut.getPlatform().close();
}
}
}

/**
* Custom hook that is called before any agent is initialized.
*/
protected void preAllInitHook() {
}

/**
* Custom hook that is called after all agents have been started.
* @param agents2
*/
protected void postAllStartHook(UT2004Bot[] startedAgents) {
}

/**
* Custom hook called before the agent is instantiated by the {@link RemoteAgentRunner#factory}.
* @throws PogamutException
*/
protected void preInitHook() throws PogamutException {
}

/**
* Custom hook called after the agent is instantiated by the {@link RemoteAgentRunner#factory} and before
* the {@link IAgent#start()} is called.
* @param agent
*/
protected void preStartHook(UT2004Bot agent) throws PogamutException {
}

/**
* Custom hook called after the agent is instantiated by the {@link RemoteAgentRunner#factory} and
* started with {@link IAgent#start()}.
* @param agent
* @throws PogamutException
*/
protected void postStartHook(UT2004Bot agent) throws PogamutException {
}

//IMP is to remove main methods from original Bot classes
public static void main(String args[]) throws PogamutException {
new MultipleBots("MultipleBotsAgent").startAgent();
}
}




If anyone requires further assistance just post a reply and I’ll try my best to reply as soon as possible.
Thanks
Hi!

Congrat on finguring this out!

Nevertheless, I'm ashamed we've forced you to go through this dark... honestly, we're currently having troubles with NetBeans (as usual they are messing up their own NetBeans module files failing to copy correct jars into correct places). But! We've just release the final Pogamut 3.1 installer - get it from the download page.

I suggest you to:
1) uninstall NetBeans
2) delete dir c:\program files\NetBeans 6.9.1
3) delete dir c:\users\your account\.nbi / .netbeans / .netbeans-registration
4) install fresh NetBeans 6.9.1
5) install Pogamut 3.1 from our download page

The problem with imports from ...ut2004... packages should go away.

-------------

Regarding start of multiple bots - it should be possible to create new Pogamut Java Bot project, set the project to reference your projects with bots you want to try out,
correctly configure MultipleUT2004BotRunner with classes of bots you want to run.

Would you try it? If so, I will explain how to setup correct NetBeans project to reference other projects in details.

Best,
Jimmy
Hey Jimmy. The installation worked after I followed your instructions. So that's Great! So now I have my 32-bit system running Pogamut3.1 and my 64-bit system running version 3.0.11.

Could you kindly explain the procedure for in NetBeans to correctly configure MultipleUT2004BotRunner with classes of bots I want to run.

Regards,
dirkmalta
Hi! Excellent!

So I'm going to explain how to work with MultipleUT2004BotRunner inside Pogamut 3.1 (I'm

afraid you're on your own with 3.0.11 which I would suggest not to use).

To be able to talk about MultipleUT2004BotRunner I will need to explain how objects of

UT2004Bot class are constructed and initialized and what roles objects implementing

IUT2004BotController (namely UT2004BotModuleController which you are extending) plays.

First of all you have to notice that what we call JAVA BOT PROJECT in the NetBeans plugin

is in fact UT2004 BOT CONTROLLER PROJECT, i.e., you're just creating something that control

the bot. That is because UT2004Bot is wrapping all the low-level communication stuff with

GameBots2004 (i.e., Unreal Tournament 2004) you do not want to care about. All you

(usually) want is to code a behavior for your bot.
(This is our stance when coding Pogamut).

In fact, we did not spot any place where a user might want to extends the UT2004 except the

IUT2004BotController methods. That is to instantiate 2 (or more) different bots means to

instantiate 2 (or more) UT2004Bot objects each having a different IUT2004BotController

implementation.

As I said before, UT2004Bot handles communication with GB2004 which involves great deal of

objects that interacts with each others having their own threads, states, behaviors, etc...

Thus to construct UT2004Bot means to instantiate a lot of (correct) objects in concrete

sequence embedding one into another until you finally instantiates an UT2004Bot. Pretty

hard to do if you are not one of the authors... but the whole thing is handled gracefully

with Google Guice IoC container. I recommand you to see UT2004BotModule class which is a

descendent of some other classes which are defining dependencies between interfaces and

their implementations providing Guice an information how you want to instantiate the

UT2004Bot (or IAgent which is a base interface for any Pogamut's agent).

Guice module, i.e., UT2004BotModule is a place where you:
1) saying which IUT2004BotController implementation you want to use (that's why it has a

constructor with Class&lt; extends IUT2004BotController&gt; as parameter)
2) providing a parametrization of the agent (check the UT2004AgentParameters) ... note that

UT2004Bot has a method getParams() which returns them, you are free to extend

UT2004AgentParameters and pass them into your bot in order to parametrize the behavior of

your bot (i.e., set a concrete skill level of the bot, sparing you of hard coding such

things into your IUT2004BotController implementation).

To utilize the UT2004BotModule you may use UT2004BotFactory but this is not needed because

it is internally wrapped by the MultipleUT2004BotRunner that provides an abstraction for

running a bunch of bots.

All you have to do is to utilize this method from MultipleUT2004BotRunner:

public List&lt;BOT&gt; startAgents(IAgentDescriptor&lt;PARAMS,MODULE&gt;... agentDescriptors)

It says you may provide arbitrary number of UT2004BotDescriptor objects which contains

information about which bots you want to start (i.e., which IUT2004BotController to

utilize) and which parameters you want to pass.

To put long story short, let's say you have three controllers ... Hunter, Prey, Defender

and you want to start one instance of UT2004Bot for every controller. You will code

something like this:


UT2004BotDescriptor hunterDesc = new UT2004BotDescriptor().setController

(Hunter.class).addParams(new UT2004AgentParameters());
UT2004BotDescriptor preyDesc = new UT2004BotDescriptor().setController

(Prey.class).addParams(new UT2004AgentParameters());
UT2004BotDescriptor defenderDesc = new UT2004BotDescriptor().setController

(Defebder.class).addParams(new UT2004AgentParameters());

new MultipleUT2004BotRunner("Multiple").setMain(true).startAgents(hunterDesc, preyDesc,

defenderDesc);


Note that you do not need to set any special parameters to UT2004AgentParameters class as

defaults are picked up via "assignDefaults()" method from inside the

MultipleUT2004BotRunner that gets them from the Pogamut.getPlatform().getProperty

(PogamutProperty.XXX.getKey()).

If you want to start for instance more prays (let's say 3), you would modify the code like

this:

UT2004BotDescriptor hunterDesc = new UT2004BotDescriptor().setController

(Hunter.class).addParams(new UT2004AgentParameters());
UT2004BotDescriptor preyDesc = new UT2004BotDescriptor().setController

(Prey.class).addParams(new UT2004AgentParameters()).addParams(new UT2004AgentParameters

()).addParams(new UT2004AgentParameters());
UT2004BotDescriptor defenderDesc = new UT2004BotDescriptor().setController

(Defebder.class).addParams(new UT2004AgentParameters());

new MultipleUT2004BotRunner("Multiple").setMain(true).startAgents(hunterDesc, preyDesc,

defenderDesc);


If you wish to use your own HunterParameters extends UT2004AgentParameters, which have a

constructor specifying the skill level of the hunter you will do something like:

UT2004BotDescriptor hunterDesc = new UT2004BotDescriptor().setController

(Hunter.class).addParams(new HunterParameters(5));
UT2004BotDescriptor preyDesc = new UT2004BotDescriptor().setController

(Prey.class).addParams(new UT2004AgentParameters()).addParams(new UT2004AgentParameters

()).addParams(new UT2004AgentParameters());
UT2004BotDescriptor defenderDesc = new UT2004BotDescriptor().setController

(Defebder.class).addParams(new UT2004AgentParameters());

new MultipleUT2004BotRunner("Multiple").setMain(true).startAgents(hunterDesc, preyDesc,

defenderDesc);


Note that "Multiple" will be used as a basis for all bot's ids. If you want to supply your

own ID (which is also a basis for a bot's name, but that may be changed later in the

controller in getInitialize() method) you will do something like:


UT2004BotDescriptor hunterDesc = new UT2004BotDescriptor().setController

(Hunter.class).addParams(new HunterParameters(5).setAgentId(new AgentId("Hunter"));
...
new MultipleUT2004BotRunner("Multiple").setMain(true).startAgents(hunterDesc, preyDesc,

defenderDesc);


Hope it helps :-)

Jimmy
Jimmy thank you so much for the assistance. Apologies for not replying earlier.

I have managed to create all instances of the examples you kindly shared.

Managed to set different radius parameters for individual bots.

My next task if to be able to give Bots items. These items I create myself, giving them specific functionalities. Such as a KEY to open specific paths.

Thank you once again.

Regards,
dirkmalta
I found the examples very helpful too, but there was one step that I didn't fully understand.
It regards this portion of the post:
----------------------------
If you wish to use your own HunterParameters extends UT2004AgentParameters, which have a constructor specifying the skill level of the hunter you will do something like:

UT2004BotDescriptor hunterDesc = new UT2004BotDescriptor().setController(Hunter.class).addParams(new HunterParameters(5));
UT2004BotDescriptor preyDesc = new UT2004BotDescriptor().setController(Prey.class).addParams(new UT2004AgentParameters()).addParams(new UT2004AgentParameters()).addParams(new UT2004AgentParameters());
UT2004BotDescriptor defenderDesc = new UT2004BotDescriptor().setController(Defebder.class).addParams(new UT2004AgentParameters());

new MultipleUT2004BotRunner("Multiple").setMain(true).startAgents(hunterDesc, preyDesc, defenderDesc);
----------------------------

The 5 sent to HunterParameters is presumably assigned to some variable inside HunterParameters. How does this value get assigned to a variable inside the bot? At what point does the Hunter bot have a chance to ask HunterParameters to give it the parameter value of 5?

-Jacob
Thanks for the question!

Actually the parameters are passed to the constructor of the UT2004Bot class itself (as well as is IUT2004BotController implementation).


public UT2004Bot(UT2004AgentParameters parameters, IComponentBus eventBus, IAgentLogger logger, IWorldView worldView, IAct act, IUT2004BotController init) {
super(parameters.getAgentId(), eventBus, logger, (WORLD_VIEW)worldView, (ACT)act);

this.params = parameters;
this.controller = (CONTROLLER) init;
NullCheck.check(this.controller, "init");
if (log.isLoggable(Level.FINER)) log.finer("Initializing the controller...");
this.controller.initializeController(this);
if (log.isLoggable(Level.FINER)) log.finer("Preparing the controller...");
this.controller.prepareBot(this);
....


As you can see parameters are saved into internal (private) field of the bot (thisrparams). This is done even before this.controller.prepareBot(this) is called. Which means early on, inside prepareBot() method of your controller (or the Hunter example), you may call bot.getParams() and get a hand on your passed parameters. The only sad thing is that you need to cast these params into the class you are expecting to receive, i.e., to the HunterParameters for instance (and it is expected you provide yourself with some getters to receive whatever params you want).

These params are present inside UT2004Bot during its whole "life", thus you may call bot.getParams() anytime you want.

Cheers!
Jimmy