[Pogamut-list] Launching Multiple Bots of Different Types

dirkmalta pogamut-forum at diana.ms.mff.cuni.cz
Wed Nov 24 23:02:42 CET 2010


Re: Launching Multiple Bots of Different Types

Author: dirkmalta

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 (agents[i] == null)
                                    continue;
				if (agents[i].notInState(IAgentStateDown.class, IAgentStateGoingDown.class)) {
					agents[i].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 UT2004Bot[number];
    	for (int i = 0; i < number; ++i) {
    		agents[i] = null;
    	}
    	agentsKilled = false;

    	FlagListener[] agentStateListener = new FlagListener[number];

    	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());
                        agents[i] = 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);
                            agentStateListener[i] = 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) {
        			agents[i] = 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

-- 
Reply Link: <http://diana.ms.mff.cuni.cz/main/tiki-view_forum_thread.php?forumId=4&comments_reply_threadId=4&comments_parentId=221&post_reply=1#form>





More information about the Pogamut-list mailing list