Add ability to adjust pCampbot bot behaviours whilst running with "add behaviour <behaviour-name> <bot-number>" console commad
parent
01cb8033a4
commit
9bd6271570
|
@ -72,9 +72,10 @@ namespace pCampBot
|
||||||
/// Behaviours implemented by this bot.
|
/// Behaviours implemented by this bot.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Lock this list before manipulating it.
|
/// Indexed by abbreviated name. There can only be one instance of a particular behaviour.
|
||||||
|
/// Lock this structure before manipulating it.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public List<IBehaviour> Behaviours { get; private set; }
|
public Dictionary<string, IBehaviour> Behaviours { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Objects that the bot has discovered.
|
/// Objects that the bot has discovered.
|
||||||
|
@ -165,8 +166,6 @@ namespace pCampBot
|
||||||
{
|
{
|
||||||
ConnectionState = ConnectionState.Disconnected;
|
ConnectionState = ConnectionState.Disconnected;
|
||||||
|
|
||||||
behaviours.ForEach(b => b.Initialize(this));
|
|
||||||
|
|
||||||
Random = new Random(Environment.TickCount);// We do stuff randomly here
|
Random = new Random(Environment.TickCount);// We do stuff randomly here
|
||||||
FirstName = firstName;
|
FirstName = firstName;
|
||||||
LastName = lastName;
|
LastName = lastName;
|
||||||
|
@ -176,12 +175,31 @@ namespace pCampBot
|
||||||
StartLocation = startLocation;
|
StartLocation = startLocation;
|
||||||
|
|
||||||
Manager = bm;
|
Manager = bm;
|
||||||
Behaviours = behaviours;
|
|
||||||
|
Behaviours = new Dictionary<string, IBehaviour>();
|
||||||
|
foreach (IBehaviour behaviour in behaviours)
|
||||||
|
AddBehaviour(behaviour);
|
||||||
|
|
||||||
// Only calling for use as a template.
|
// Only calling for use as a template.
|
||||||
CreateLibOmvClient();
|
CreateLibOmvClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool AddBehaviour(IBehaviour behaviour)
|
||||||
|
{
|
||||||
|
lock (Behaviours)
|
||||||
|
{
|
||||||
|
if (!Behaviours.ContainsKey(behaviour.AbbreviatedName))
|
||||||
|
{
|
||||||
|
behaviour.Initialize(this);
|
||||||
|
Behaviours.Add(behaviour.AbbreviatedName, behaviour);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateLibOmvClient()
|
private void CreateLibOmvClient()
|
||||||
{
|
{
|
||||||
GridClient newClient = new GridClient();
|
GridClient newClient = new GridClient();
|
||||||
|
@ -237,16 +255,21 @@ namespace pCampBot
|
||||||
private void Action()
|
private void Action()
|
||||||
{
|
{
|
||||||
while (ConnectionState != ConnectionState.Disconnecting)
|
while (ConnectionState != ConnectionState.Disconnecting)
|
||||||
|
{
|
||||||
lock (Behaviours)
|
lock (Behaviours)
|
||||||
Behaviours.ForEach(
|
{
|
||||||
b =>
|
foreach (IBehaviour behaviour in Behaviours.Values)
|
||||||
{
|
{
|
||||||
Thread.Sleep(Random.Next(3000, 10000));
|
Thread.Sleep(Random.Next(3000, 10000));
|
||||||
|
|
||||||
// m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
|
// m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType());
|
||||||
b.Action();
|
behaviour.Action();
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
|
// XXX: This is a really shitty way of yielding so that behaviours can be added/removed
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace pCampBot
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Behaviour switches for bots.
|
/// Behaviour switches for bots.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private HashSet<string> m_behaviourSwitches = new HashSet<string>();
|
private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
|
/// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
|
||||||
|
@ -194,6 +194,18 @@ namespace pCampBot
|
||||||
+ "If no <n> is given, then all currently connected bots are disconnected.",
|
+ "If no <n> is given, then all currently connected bots are disconnected.",
|
||||||
HandleDisconnect);
|
HandleDisconnect);
|
||||||
|
|
||||||
|
m_console.Commands.AddCommand(
|
||||||
|
"bot", false, "add behaviour", "add behaviour <abbreviated-name> <bot-number>",
|
||||||
|
"Add a behaviour to a bot",
|
||||||
|
"Can be performed on connected or disconnected bots.",
|
||||||
|
HandleAddBehaviour);
|
||||||
|
|
||||||
|
// m_console.Commands.AddCommand(
|
||||||
|
// "bot", false, "remove behaviour", "remove behaviour <abbreviated-name> <bot-number>",
|
||||||
|
// "Remove a behaviour from a bot",
|
||||||
|
// "Can be performed on connected or disconnected bots.",
|
||||||
|
// HandleRemoveBehaviour);
|
||||||
|
|
||||||
m_console.Commands.AddCommand(
|
m_console.Commands.AddCommand(
|
||||||
"bot", false, "sit", "sit", "Sit all bots on the ground.",
|
"bot", false, "sit", "sit", "Sit all bots on the ground.",
|
||||||
HandleSit);
|
HandleSit);
|
||||||
|
@ -235,7 +247,7 @@ namespace pCampBot
|
||||||
m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
|
m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
|
||||||
|
|
||||||
Array.ForEach<string>(
|
Array.ForEach<string>(
|
||||||
startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_behaviourSwitches.Add(b));
|
startupConfig.GetString("behaviours", "p").Split(new char[] { ',' }), b => m_defaultBehaviourSwitches.Add(b));
|
||||||
|
|
||||||
for (int i = 0; i < botcount; i++)
|
for (int i = 0; i < botcount; i++)
|
||||||
{
|
{
|
||||||
|
@ -243,30 +255,52 @@ namespace pCampBot
|
||||||
{
|
{
|
||||||
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
|
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
|
||||||
|
|
||||||
// We must give each bot its own list of instantiated behaviours since they store state.
|
CreateBot(
|
||||||
List<IBehaviour> behaviours = new List<IBehaviour>();
|
this,
|
||||||
|
CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
|
||||||
// Hard-coded for now
|
m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
|
||||||
if (m_behaviourSwitches.Contains("c"))
|
|
||||||
behaviours.Add(new CrossBehaviour());
|
|
||||||
|
|
||||||
if (m_behaviourSwitches.Contains("g"))
|
|
||||||
behaviours.Add(new GrabbingBehaviour());
|
|
||||||
|
|
||||||
if (m_behaviourSwitches.Contains("n"))
|
|
||||||
behaviours.Add(new NoneBehaviour());
|
|
||||||
|
|
||||||
if (m_behaviourSwitches.Contains("p"))
|
|
||||||
behaviours.Add(new PhysicsBehaviour());
|
|
||||||
|
|
||||||
if (m_behaviourSwitches.Contains("t"))
|
|
||||||
behaviours.Add(new TeleportBehaviour());
|
|
||||||
|
|
||||||
CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<IBehaviour> CreateBehavioursFromAbbreviatedNames(HashSet<string> abbreviatedNames)
|
||||||
|
{
|
||||||
|
// We must give each bot its own list of instantiated behaviours since they store state.
|
||||||
|
List<IBehaviour> behaviours = new List<IBehaviour>();
|
||||||
|
|
||||||
|
// Hard-coded for now
|
||||||
|
foreach (string abName in abbreviatedNames)
|
||||||
|
{
|
||||||
|
IBehaviour newBehaviour = null;
|
||||||
|
|
||||||
|
if (abName == "c")
|
||||||
|
newBehaviour = new CrossBehaviour();
|
||||||
|
|
||||||
|
if (abName == "g")
|
||||||
|
newBehaviour = new GrabbingBehaviour();
|
||||||
|
|
||||||
|
if (abName == "n")
|
||||||
|
newBehaviour = new NoneBehaviour();
|
||||||
|
|
||||||
|
if (abName == "p")
|
||||||
|
newBehaviour = new PhysicsBehaviour();
|
||||||
|
|
||||||
|
if (abName == "t")
|
||||||
|
newBehaviour = new TeleportBehaviour();
|
||||||
|
|
||||||
|
if (newBehaviour != null)
|
||||||
|
{
|
||||||
|
behaviours.Add(newBehaviour);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("No behaviour with abbreviated name {0} found", abName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return behaviours;
|
||||||
|
}
|
||||||
|
|
||||||
public void ConnectBots(int botcount)
|
public void ConnectBots(int botcount)
|
||||||
{
|
{
|
||||||
ConnectingBots = true;
|
ConnectingBots = true;
|
||||||
|
@ -453,6 +487,44 @@ namespace pCampBot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleAddBehaviour(string module, string[] cmd)
|
||||||
|
{
|
||||||
|
if (cmd.Length != 4)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Usage: add behaviour <abbreviated-behaviour> <bot-number>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string rawBehaviours = cmd[2];
|
||||||
|
int botNumber;
|
||||||
|
|
||||||
|
if (!ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, cmd[3], out botNumber))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Bot bot = GetBotFromNumber(botNumber);
|
||||||
|
|
||||||
|
if (bot == null)
|
||||||
|
{
|
||||||
|
MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HashSet<string> rawAbbreviatedSwitchesToAdd = new HashSet<string>();
|
||||||
|
Array.ForEach<string>(rawBehaviours.Split(new char[] { ',' }), b => rawAbbreviatedSwitchesToAdd.Add(b));
|
||||||
|
|
||||||
|
List<IBehaviour> behavioursAdded = new List<IBehaviour>();
|
||||||
|
|
||||||
|
foreach (IBehaviour behaviour in CreateBehavioursFromAbbreviatedNames(rawAbbreviatedSwitchesToAdd))
|
||||||
|
{
|
||||||
|
if (bot.AddBehaviour(behaviour))
|
||||||
|
behavioursAdded.Add(behaviour);
|
||||||
|
}
|
||||||
|
|
||||||
|
MainConsole.Instance.OutputFormat(
|
||||||
|
"Added behaviours {0} to bot {1}",
|
||||||
|
string.Join(", ", behavioursAdded.ConvertAll<string>(b => b.Name).ToArray()), bot.Name);
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleDisconnect(string module, string[] cmd)
|
private void HandleDisconnect(string module, string[] cmd)
|
||||||
{
|
{
|
||||||
lock (m_bots)
|
lock (m_bots)
|
||||||
|
@ -594,7 +666,7 @@ namespace pCampBot
|
||||||
currentSim != null ? currentSim.Name : "(none)",
|
currentSim != null ? currentSim.Name : "(none)",
|
||||||
bot.ConnectionState,
|
bot.ConnectionState,
|
||||||
bot.SimulatorsCount,
|
bot.SimulatorsCount,
|
||||||
string.Join(",", bot.Behaviours.ConvertAll<string>(behaviour => behaviour.AbbreviatedName).ToArray()));
|
string.Join(",", bot.Behaviours.Keys.ToArray()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,16 +693,11 @@ namespace pCampBot
|
||||||
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
|
if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, cmd[2], out botNumber))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
|
Bot bot = GetBotFromNumber(botNumber);
|
||||||
|
|
||||||
Bot bot;
|
|
||||||
|
|
||||||
lock (m_bots)
|
|
||||||
bot = m_bots.Find(b => b.Name == name);
|
|
||||||
|
|
||||||
if (bot == null)
|
if (bot == null)
|
||||||
{
|
{
|
||||||
MainConsole.Instance.Output("No bot found with name {0}", name);
|
MainConsole.Instance.OutputFormat("Error: No bot found with number {0}", botNumber);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,13 +717,39 @@ namespace pCampBot
|
||||||
MainConsole.Instance.Output("Settings");
|
MainConsole.Instance.Output("Settings");
|
||||||
|
|
||||||
ConsoleDisplayList statusCdl = new ConsoleDisplayList();
|
ConsoleDisplayList statusCdl = new ConsoleDisplayList();
|
||||||
statusCdl.AddRow("Behaviours", string.Join(", ", bot.Behaviours.ConvertAll<string>(b => b.Name).ToArray()));
|
|
||||||
|
statusCdl.AddRow(
|
||||||
|
"Behaviours",
|
||||||
|
string.Join(", ", bot.Behaviours.Values.ToList().ConvertAll<string>(b => b.Name).ToArray()));
|
||||||
|
|
||||||
GridClient botClient = bot.Client;
|
GridClient botClient = bot.Client;
|
||||||
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
|
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
|
||||||
|
|
||||||
MainConsole.Instance.Output(statusCdl.ToString());
|
MainConsole.Instance.Output(statusCdl.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a specific bot from its number.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>null if no bot was found</returns>
|
||||||
|
/// <param name='botNumber'></param>
|
||||||
|
private Bot GetBotFromNumber(int botNumber)
|
||||||
|
{
|
||||||
|
string name = GenerateBotNameFromNumber(botNumber);
|
||||||
|
|
||||||
|
Bot bot;
|
||||||
|
|
||||||
|
lock (m_bots)
|
||||||
|
bot = m_bots.Find(b => b.Name == name);
|
||||||
|
|
||||||
|
return bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateBotNameFromNumber(int botNumber)
|
||||||
|
{
|
||||||
|
return string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
|
||||||
|
}
|
||||||
|
|
||||||
internal void Grid_GridRegion(object o, GridRegionEventArgs args)
|
internal void Grid_GridRegion(object o, GridRegionEventArgs args)
|
||||||
{
|
{
|
||||||
lock (RegionsKnown)
|
lock (RegionsKnown)
|
||||||
|
|
Loading…
Reference in New Issue