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.
|
||||
/// </summary>
|
||||
/// <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>
|
||||
public List<IBehaviour> Behaviours { get; private set; }
|
||||
public Dictionary<string, IBehaviour> Behaviours { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Objects that the bot has discovered.
|
||||
|
@ -165,8 +166,6 @@ namespace pCampBot
|
|||
{
|
||||
ConnectionState = ConnectionState.Disconnected;
|
||||
|
||||
behaviours.ForEach(b => b.Initialize(this));
|
||||
|
||||
Random = new Random(Environment.TickCount);// We do stuff randomly here
|
||||
FirstName = firstName;
|
||||
LastName = lastName;
|
||||
|
@ -176,12 +175,31 @@ namespace pCampBot
|
|||
StartLocation = startLocation;
|
||||
|
||||
Manager = bm;
|
||||
Behaviours = behaviours;
|
||||
|
||||
Behaviours = new Dictionary<string, IBehaviour>();
|
||||
foreach (IBehaviour behaviour in behaviours)
|
||||
AddBehaviour(behaviour);
|
||||
|
||||
// Only calling for use as a template.
|
||||
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()
|
||||
{
|
||||
GridClient newClient = new GridClient();
|
||||
|
@ -237,16 +255,21 @@ namespace pCampBot
|
|||
private void Action()
|
||||
{
|
||||
while (ConnectionState != ConnectionState.Disconnecting)
|
||||
{
|
||||
lock (Behaviours)
|
||||
Behaviours.ForEach(
|
||||
b =>
|
||||
{
|
||||
foreach (IBehaviour behaviour in Behaviours.Values)
|
||||
{
|
||||
Thread.Sleep(Random.Next(3000, 10000));
|
||||
|
||||
// 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>
|
||||
|
|
|
@ -140,7 +140,7 @@ namespace pCampBot
|
|||
/// <summary>
|
||||
/// Behaviour switches for bots.
|
||||
/// </summary>
|
||||
private HashSet<string> m_behaviourSwitches = new HashSet<string>();
|
||||
private HashSet<string> m_defaultBehaviourSwitches = new HashSet<string>();
|
||||
|
||||
/// <summary>
|
||||
/// 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.",
|
||||
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(
|
||||
"bot", false, "sit", "sit", "Sit all bots on the ground.",
|
||||
HandleSit);
|
||||
|
@ -235,7 +247,7 @@ namespace pCampBot
|
|||
m_startUri = ParseInputStartLocationToUri(startupConfig.GetString("start", "last"));
|
||||
|
||||
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++)
|
||||
{
|
||||
|
@ -243,28 +255,50 @@ namespace pCampBot
|
|||
{
|
||||
string lastName = string.Format("{0}_{1}", m_lastNameStem, i + m_fromBotNumber);
|
||||
|
||||
CreateBot(
|
||||
this,
|
||||
CreateBehavioursFromAbbreviatedNames(m_defaultBehaviourSwitches),
|
||||
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
|
||||
if (m_behaviourSwitches.Contains("c"))
|
||||
behaviours.Add(new CrossBehaviour());
|
||||
foreach (string abName in abbreviatedNames)
|
||||
{
|
||||
IBehaviour newBehaviour = null;
|
||||
|
||||
if (m_behaviourSwitches.Contains("g"))
|
||||
behaviours.Add(new GrabbingBehaviour());
|
||||
if (abName == "c")
|
||||
newBehaviour = new CrossBehaviour();
|
||||
|
||||
if (m_behaviourSwitches.Contains("n"))
|
||||
behaviours.Add(new NoneBehaviour());
|
||||
if (abName == "g")
|
||||
newBehaviour = new GrabbingBehaviour();
|
||||
|
||||
if (m_behaviourSwitches.Contains("p"))
|
||||
behaviours.Add(new PhysicsBehaviour());
|
||||
if (abName == "n")
|
||||
newBehaviour = new NoneBehaviour();
|
||||
|
||||
if (m_behaviourSwitches.Contains("t"))
|
||||
behaviours.Add(new TeleportBehaviour());
|
||||
if (abName == "p")
|
||||
newBehaviour = new PhysicsBehaviour();
|
||||
|
||||
CreateBot(this, behaviours, m_firstName, lastName, m_password, m_loginUri, m_startUri, m_wearSetting);
|
||||
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)
|
||||
|
@ -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)
|
||||
{
|
||||
lock (m_bots)
|
||||
|
@ -594,7 +666,7 @@ namespace pCampBot
|
|||
currentSim != null ? currentSim.Name : "(none)",
|
||||
bot.ConnectionState,
|
||||
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))
|
||||
return;
|
||||
|
||||
string name = string.Format("{0} {1}_{2}", m_firstName, m_lastNameStem, botNumber);
|
||||
|
||||
Bot bot;
|
||||
|
||||
lock (m_bots)
|
||||
bot = m_bots.Find(b => b.Name == name);
|
||||
Bot bot = GetBotFromNumber(botNumber);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -650,13 +717,39 @@ namespace pCampBot
|
|||
MainConsole.Instance.Output("Settings");
|
||||
|
||||
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;
|
||||
statusCdl.AddRow("SEND_AGENT_UPDATES", botClient.Settings.SEND_AGENT_UPDATES);
|
||||
|
||||
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)
|
||||
{
|
||||
lock (RegionsKnown)
|
||||
|
|
Loading…
Reference in New Issue