/// <summary> /// if the 'ID' key is PathHome then it tells the bot how to get home. /// we need to turn the dictionary into a list, ordered by key ('0' ... 'n') /// at present other IDs are ignored /// </summary> /// <param name="valuesDict"></param> override internal void ReceivePathDetails(Dictionary <string, string> valuesDict) { if (!valuesDict.ContainsKey("Id")) { return; } if (valuesDict["Id"] == pathHomeId) { info.pathHome = NavPoint.ConvertToPath(valuesDict); } else if (valuesDict["Id"] == pathToEnemyBaseId) { info.pathToEnemyBase = NavPoint.ConvertToPath(valuesDict); } // if there's no 0 key we're being given an empty path, so set TooCloseForPath to the current time // so that we can check how old the information is later on if (!valuesDict.ContainsKey("0")) { info.TooCloseForPath = TimerBase.CurrentTimeStamp(); } else { info.TooCloseForPath = 0L; } }
/// <summary> /// Was the bot hit in the last lsec seconds /// </summary> /// <param name="lsec">how many secs look back</param> /// <param name="isec">number of seconds to inhibit WasHit</param> /// <returns></returns> internal bool WasHit(int lsec, int isec) { int lastEvents = 0; long now = TimerBase.CurrentTimeStamp(); foreach (Tuple <long, string> elem in this.events) { if (elem.First > now - lsec) { lastEvents++; } } if (this.hitTimestamp < now - isec) { // Update the last Hit timestamp this.hitTimestamp = now; if (lastEvents > 0) { return(true); } } return(false); }
public bool HasTooCloseForPathExpired(int lsecs) { if (TooCloseForPath < TimerBase.CurrentTimeStamp() - lsecs) { return(true); } return(false); }
/// <summary> /// Checks the timestamp against current time less lifetime of damagedetails FA /// If the details expired null is returned. /// </summary> /// <param name="lsec"></param> /// <returns>damage</returns> public Damage GetDamageDetails(int lsec) { if (DamageDetails != null && DamageDetails.TimeStamp < TimerBase.CurrentTimeStamp() - lsec) { return(DamageDetails); } DamageDetails = null; return(null); }
public Projectile GetProjectileDetails(int lsecs) { if (ProjectileDetails != null && ProjectileDetails.TimeStamp < TimerBase.CurrentTimeStamp() - lsecs) { return(ProjectileDetails); } ProjectileDetails = null; return(null); }
public bool HasOurFlagInfoExpired(int lsecs) { if (ourFlagInfo.Count > 0 && ourFlagInfo.ContainsKey("Reachable")) { if (long.Parse(ourFlagInfo["TimeStamp"]) < (TimerBase.CurrentTimeStamp() - lsecs)) { return(true); } } return(false); }
/// <summary> /// Checks the timestamp against current time less lifetime of focus_id FA /// If the focus location expired null is returned. /// </summary> /// <param name="lsec"></param> /// <returns></returns> public Tuple <Vector3, long> GetFocusLocation(int lsec) { if (KeepFocusOnLocation is Tuple <Vector3, long> && KeepFocusOnLocation.First is Vector3) { if (KeepFocusOnLocation.Second < TimerBase.CurrentTimeStamp() - lsec) { return(KeepFocusOnLocation); } } KeepFocusOnLocation = null; return(null); }
/// <summary> /// Checks the timestamp against current time less lifetime of focus_id FA /// If the focus ID expired null is returned. /// /// </summary> /// <param name="lsec"></param> /// <returns></returns> public Tuple <string, long> GetFocusId(int lsec) { if (KeepFocusOnID is Tuple <string, long> && KeepFocusOnID.First != string.Empty) { if (KeepFocusOnID.Second < TimerBase.CurrentTimeStamp() - lsec) { return(KeepFocusOnID); } } KeepFocusOnID = null; return(null); }
/* * * OTHER FUNCTIONS * */ private void FindEnemyInView() { // work through who we can see, looking for an enemy string ourTeam = GetBot().info["Team"]; Console.Out.WriteLine("Our Team: " + ourTeam); foreach (UTPlayer player in GetBot().viewPlayers.Values) { if (player.Team != ourTeam) { // Turned KeepFocusOnID in to a tuple with the current_time as a timestamp FA info.KeepFocusOnID = new Tuple <string, long>(player.Id, TimerBase.CurrentTimeStamp()); info.KeepFocusOnLocation = new Tuple <Vector3, long>(player.Location, TimerBase.CurrentTimeStamp()); return; } } }
public bool SetAttacker() { Console.Out.WriteLine(" in SetAttacker"); if (GetBot().viewPlayers.Count == 0 || GetBot().info.Count == 0) { return(false); } if (info.GetDamageDetails() is Damage && info.DamageDetails.AttackerID != "") { if (GetBot().viewPlayers.ContainsKey(info.DamageDetails.AttackerID)) { // set variables so that other commands will keep him in view // Turned KeepFocusOnID into a tuple with the current_time as a timestamp FA info.KeepFocusOnID = new Tuple <string, long>(info.DamageDetails.AttackerID, TimerBase.CurrentTimeStamp()); info.KeepFocusOnLocation = new Tuple <Vector3, long>(GetBot().viewPlayers[info.DamageDetails.AttackerID].Location, TimerBase.CurrentTimeStamp()); } else { FindEnemyInView(); } } else { FindEnemyInView(); } return(true); }
/// <summary> /// all info from within the game are converted here /// handles synchronisation messages /// </summary> /// <param name="message">Tuples[command,valuesDictionary]</param> internal void ProcessSync(Tuple <string, Dictionary <string, string> > message) { message.Second["TimeStamp"] = TimerBase.CurrentTimeStamp().ToString(); switch (message.First) { case "SLF": // info about bot's state this.sBotinfo = message.Second; // Keep track of orientation so we can tell when we are moving // Yeah, we only need to know the Yaw this.rotationHist.Add( int.Parse( middleIntMatcher.Match(message.Second["Rotation"]) .Groups[1].Value) ); // Trim list to 3 entries if (this.rotationHist.Count > 3) { this.rotationHist.RemoveRange(0, this.rotationHist.Count - 3); } // Keep track of velocity so we know when we are stuck this.velocityHist.Add( CalculateVelocity(message.Second["Velocity"]) ); // Trim it to 20 entries if (this.velocityHist.Count > 20) { this.velocityHist.RemoveRange(0, velocityHist.Count - 20); } break; case "GAM": this.sGameinfo = message.Second; break; case "PLR": // another character visible // TODO: Test that this python statement is still true: For some reason, this doesn't work in ut2003 this.sViewPlayers[message.Second["Id"]] = new UTPlayer(message.Second); break; case "NAV": // a path marker // TODO: Neither does this // print "We have details about a nav point at " + values["Location"] this.sNavPoints[message.Second["Id"]] = NavPoint.ConvertToNavPoint(message.Second); break; case "INV": // an object on the ground that can be picked up this.sViewItems.Add(new InvItem(message.Second)); break; case "FLG": // pass these details to the movement behaviour as that stores details of locations etc and may need them // TODO: This needs some clean up as we just spread information which does not belong in all Behaviours if (this._debug_) { foreach (KeyValuePair <string, string> elem in message.Second) { Console.WriteLine(string.Format("{0} = {1}", elem.Key, elem.Value)); } } ((Movement)agent.getBehaviour("Movement")).ReceiveFlagDetails(message.Second); // inform the combat behaviour as well GetCombat().ReceiveFlagDetails(message.Second); break; default: break; } }
/// <summary> /// This method runs inside a thread updating the agent state /// by reading from the network socket /// </summary> void ConnectThread() { NetworkStream stream = null; StreamReader reader = null; TcpClient client = null; writer = null; killConnection = false; try { client = new TcpClient(this.ip.ToString(), this.port); // client.Connect(ipe); if (client.Connected) { stream = client.GetStream(); } } catch (Exception) { log.Error("Connection to server failed"); // Skip the read loop killConnection = true; return; } try { reader = new StreamReader(stream); writer = new StreamWriter(stream); } catch (IOException) { log.Error("Could not establish Reader or Writer on Socket."); // Skip the read loop killConnection = true; } if (reader is StreamReader) { // TODO: why does it write to error? shouldnt it be Info log.Error("Connected to server"); killConnection = false; } // This loop waits for the initialisation messages while (!killConnection && !this.connectedToGame) { string dataIn = ReadDataInput(reader); if (dataIn == string.Empty) { log.Error("Connection Closed from Remote End"); killConnection = true; break; } // print dataIn Tuple <string, Dictionary <string, string> > result = ProcessItem(dataIn); switch (result.First) { case "HELLO_BOT": SendMessage("READY", new Dictionary <string, string>()); break; case "SNAV": sNavPoints = new Dictionary <string, NavPoint>(); sNavID = ""; break; case "NAV": sNavPoints[result.Second["Id"]] = NavPoint.ConvertToNavPoint(result.Second); sNavID = result.Second["Id"]; break; case "SNPG": sNavPoints[sNavID].SetNeighbors(); break; case "INGP": sNavPoints[sNavID].NGP.Add(new NavPoint.Neighbor(result.Second)); break; case "ENGP": sNavID = ""; break; case "ENAV": navPoints = sNavPoints; GetNavigator().SetNavPoints(navPoints); SendMessage("INIT", new Dictionary <string, string> { { "Name", this.botName }, { "Team", this.team.ToString() } }); this.connectedToGame = true; break; } } // Main Loop // Not everything is implemented. Just some basics while (!killConnection) { string dataIn = ReadDataInput(reader); if (dataIn == string.Empty) { log.Error("Connection Closed from Remote End"); killConnection = true; break; } //print "R>> " + str(self) + x Tuple <string, Dictionary <string, string> > result = ProcessItem(dataIn); string [] syncStates = { "SLF", "GAM", "PLR", "MOV", "DOM", "FLG", "INV" }; string [] pathStates = { "SPTH", "IPTH", "EPTH" }; string [] events = { "WAL", "BMP" }; this.msgLog.Add(result); if (result.First == "BEG") { // When a sync batch is arriving, make sure the shadow // states are cleared this.sGameinfo = new Dictionary <string, string>(); this.sViewPlayers = new Dictionary <string, UTPlayer>(); this.sViewItems = new List <InvItem>(); this.sNavPoints = new Dictionary <string, NavPoint>(); this.sBotinfo = new Dictionary <string, string>(); } else if (syncStates.Contains(result.First)) { // These are sync. messages, handle them with another method ProcessSync(result); } else if (result.First == "END") { SynShadowStates(); this.viewPlayers = this.sViewPlayers; } if (this.connectedToGame) { this.connReady = true; this.connectedToGame = false; } else if (events.Contains(result.First)) { // The bot hit a wall or an actor, make a note // of it in the events list with timestamp this.events.Add(new Tuple <long, string>(TimerBase.CurrentTimeStamp(), result.ToString())); } else if (result.First == "SEE") { // Update the player Position this.sViewPlayers[result.Second["Id"]] = new UTPlayer(result.Second); } else if (pathStates.Contains(result.First)) { foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceivePathDetails(result.Second); } } // pass the details to the movement behaviour // ((Movement)agent.getBehaviour("Movement")).ReceivePathDetails(result.Second); } else if (result.First == "RCH") { foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceiveCheckReachDetails(result.Second); } } //((Navigator)agent.getBehaviour("Navigator")).ReceiveCheckReachDetails(result.Second); } else if (result.First == "PRJ") { // incoming projectile foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceiveProjectileDetails(result.Second); } } //GetCombat().ReceiveProjectileDetails(result.Second); } else if (result.First == "DAM") { foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceiveDamageDetails(result.Second); } } // incoming projectile //GetCombat().ReceiveDamageDetails(result.Second); } else if (result.First == "KIL") { foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceiveKillDetails(result.Second); } } // incoming projectile // GetCombat().ReceiveKillDetails(result.Second); } else if (result.First == "DIE") { foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).ReceiveDeathDetails(result.Second); } } // incoming projectile // GetCombat().ReceiveDeathDetails(result.Second); } // allows each behaviour to execute some internal logic foreach (Behaviour behave in agent.getBehaviours()) { if (behave is UTBehaviour) { ((UTBehaviour)behave).Update(); } } } log.Info("Closing Connection and Cleaning Up..."); try { writer.Flush(); writer.Close(); reader.Close(); if (client is TcpClient && client.Connected) { client.GetStream().Close(); } client.Close(); } catch (IOException) { log.Error("Could not close Reader or Writer on Socket."); // Skip the read loop } catch (Exception) { log.Error("Closing Connection to server failed."); // Skip the read loop killConnection = true; } this.threadActive = false; this.connReady = false; this.connThread = null; log.Info("Connection Thread Terminating..."); }