/// <summary> /// Returns footballers overlapped by agent. /// </summary> public List <Footballer> PotentialFootballerToFootballerCollision(Footballer critter, Coords potentialPosition) { List <Footballer> returnVal = new List <Footballer>(); UInt16 critterRadiusX = critter.RadiusX; UInt16 critterRadiusY = critter.RadiusY; LinkedList <Coords> checkList = this.TilesCoveredByEllipse(potentialPosition, critterRadiusX, critterRadiusY); foreach (Coords checkme in checkList) { foreach (Footballer obstacle in _clippingBoxes[checkme.X, checkme.Y]) { // ignore self if (obstacle == critter) { continue; } if (CollisionCheckEllipses(potentialPosition, critterRadiusX, critterRadiusY, new Coords(obstacle.PositionDouble), obstacle.RadiusX, obstacle.RadiusY)) { returnVal.Add(obstacle); } } } return(returnVal); }
/// <summary> /// The scheduler updates its map's actors for the current tick. /// </summary> public void Update() { _gameMap.MatchOnMap.Update(); foreach (KeyValuePair <UInt32, Footballer> kvp in _gameMap.Roster) { Footballer someGuy = kvp.Value; Brain currentBrain = someGuy.FootballerBrain; if (currentBrain != null) { currentBrain.Update(); } // update inf map if necessary. // should ignore the GKs... if (_timeCounter % Constants.InfMapUpdatePeriod == someGuy.UniqueID) { Coords newInfMapPosition = new Coords((Int32)(someGuy.PositionDouble.X / Constants.InfMapDefaultBoxSizeX), (Int32)(someGuy.PositionDouble.Y / Constants.InfMapDefaultBoxSizeY)); _gameMap.InfMapGenerator.UpdateMapViaSourceMap(someGuy.Team.TeamInfluenceMap, _gameMap.DefaultInfSourceMap, someGuy.PositionAtLastInfMapUpdate, newInfMapPosition); someGuy.PositionAtLastInfMapUpdate = newInfMapPosition; } this._timeCounter++; } _gameMap.BallReference.UpdateMotion3D(); }
private DoubleFootballerPair GetBestLobPass() { List <Footballer> roster = _owner.Team.TeamRoster; Footballer best = null; double bestVal = 0; for (int i = 0; i < roster.Count; ++i) { Footballer current = roster[i]; if (current == _owner) { continue; } double currentVal = EvaluatorPassLob(current); if (currentVal > bestVal) { bestVal = currentVal; best = current; } } return(new DoubleFootballerPair(bestVal, best)); }
/// <summary> /// Returns a double that measures the usefulness of a lob pass to passTarget /// </summary> private double EvaluatorPassLob(Footballer passTarget) { double evaluation = 0; Vector2d passVector = passTarget.PositionDouble - _owner.PositionDouble; // add bonus for long passes (0,1) evaluation += passVector.Length() / Constants.ActualXMax; // add bonus for going in the direction of enemy goal (0,1) Vector2d goalPosition = Constants.Uprights[0]; //upper-left post if (!_owner.Team.AttackingLeft) { goalPosition = Constants.Uprights[2]; //upper-right post } double angle = passVector.AngleBetween(goalPosition - _owner.PositionDouble); angle = Math.Abs(angle - Math.PI); evaluation += (angle / Math.PI); // add large bonus if target is alone. InfluenceMap enemyMap = _owner.EnemyTeam.TeamInfluenceMap; double interdiction = enemyMap.SumInArea(passTarget.PositionOnInfMap(), (UInt16)(passVector.Length() / (0.1 * Constants.ActualXMax) + 1)); if (interdiction < 1) { evaluation += 3; } return(evaluation); }
public ActionPassToSpot(Footballer owner, Vector2d target, PassType typeOfPass) : base(owner) { _target = target; _typeOfPass = typeOfPass; // begin to turn to target. _owner.TurnToFace(target - _owner.PositionDouble); }
public Int32 CompareTo(object obj) { if (!(obj is Footballer)) { throw new Exception("Bad Footballer comparison."); } Footballer compared = (Footballer)obj; return((Int32)(this._uniqueID - compared._uniqueID)); }
public void HandleCollisions(Footballer someGuy, Vector2d oldPosition) { this.UpdateFootballerBoxes(someGuy, oldPosition); List <Footballer> collisions = this.PotentialFootballerToFootballerCollision(someGuy, new Coords(someGuy.PositionDouble)); for (int i = 0; i < collisions.Count; ++i) { this.HandleCollisionBetweenTwoPlayers(someGuy, collisions[i]); } }
public void RegisterFootballer(Footballer someGuy) { LinkedList <Coords> steppedOn = TilesCoveredByEllipse(new Coords(someGuy.PositionDouble), someGuy.RadiusX, someGuy.RadiusY); foreach (Coords c in steppedOn) { this.ClippingBoxesAddTo(c, someGuy); } _occupiedBoxes.Add(someGuy, steppedOn); }
public bool ReadyForOtherTeamToTakeKickOff() { for (int i = 0; i < _teamRoster.Count; ++i) { Footballer current = _teamRoster[i]; if (!current.IsNear(current.DefaultPositionInHalf())) { return(false); } } return(true); }
/* * /// <summary> * /// Performs a terrain passability check betwee two points by doing pixel validity checks at interval delta. * /// </summary> * public CollisionType RayTracerPassabilityCheckRough(Footballer client, Vector v1, Vector v2, double delta) * { * Vector difference = v2-v1; * Vector deltaV = difference; * deltaV.ScaleToLength(delta); * * Vector currentPosition = v1; * * for (int i = 0; i < difference.Length() / deltaV.Length(); ++i) * { * Coords pixel = new Coords(currentPosition); * currentPosition += deltaV; * } * * return CollisionType.None; * } * * /// <summary> * /// Returns the Bresenham line between p0 and p1; Borrowed the code * /// from some dude whose name I don't have, who in turn borrowed from Wikipedia. * /// </summary> * private List<Coords> BresenhamLine(Coords p0, Coords p1) * { * List<Coords> returnList = new List<Coords>(); * * Boolean steep = Math.Abs(p1.Y - p0.Y) > Math.Abs(p1.X - p0.X); * * if (steep == true) * { * Coords tmpPoint = new Coords(CoordsType.Tile,p0.X, p0.Y); * p0 = new Coords(CoordsType.Tile,tmpPoint.Y, tmpPoint.X); * * tmpPoint = p1; * p1 = new Coords(CoordsType.Tile,tmpPoint.Y, tmpPoint.X); * } * * Int32 deltaX = Math.Abs(p1.X - p0.X); * Int32 deltaY = Math.Abs(p1.Y - p0.Y); * Int32 error = 0; * Int32 deltaError = deltaY; * Int32 yStep = 0; * Int32 xStep = 0; * Int32 y = p0.Y; * Int32 x = p0.X; * * if (p0.Y < p1.Y) * { * yStep = 1; * } * else * { * yStep = -1; * } * * if (p0.X < p1.X) * { * xStep = 1; * } * else * { * xStep = -1; * } * * Int32 tmpX = 0; * Int32 tmpY = 0; * * while (x != p1.X) * { * * x += xStep; * error += deltaError; * * //if the error exceeds the X delta then * //move one along on the Y axis * if ((2 * error) > deltaX) * { * y += yStep; * error -= deltaX; * } * * //flip the coords if they're steep * if (steep) * { * tmpX = y; * tmpY = x; * } * else * { * tmpX = x; * tmpY = y; * } * * //check the point generated is legal * //and if it is add it to the list * if (this.CheckInBounds(new Coords(CoordsType.Tile,tmpX, tmpY)) == true) * { * returnList.Add(new Coords(CoordsType.Tile,tmpX, tmpY)); * } * else * { //a bad point has been found, so return the list thus far * return returnList; * } * * } * * return returnList; * } */ #endregion #region Item / Footballer spawners /// <summary> /// Spawns the player on the 'ground' at 'startPoint' /// returns a reference to the Player so one can more easily take care of references. /// </summary> public Footballer SpawnFootballer(Vector2d startPoint, Vector2d defaultPlayingPosition, Team team) { Footballer newGuy = new Footballer(this, startPoint, defaultPlayingPosition, this.IssueFootballerID(), team); Coords infMapPosition = new Coords((Int32)(startPoint.X / Constants.InfMapDefaultBoxSizeX), (Int32)(startPoint.Y / Constants.InfMapDefaultBoxSizeY)); InfluenceSourceMap updater = _infMapGenerator.ShiftInfluenceSourceMap(_defaultInfSourceMap, infMapPosition); newGuy.Team.TeamInfluenceMap.Add(updater); //_teamInfluenceMaps[(sbyte)team].Add( updater); newGuy.PositionAtLastInfMapUpdate = infMapPosition; return(newGuy); }
/// <summary> /// Gives the ball a velocity vector and a spin vector. /// </summary> public virtual void Kick(Vector3d velocity, Vector3d spin, Footballer kicker) { if (kicker != null) { _lastTouch = kicker.Team; } this._velocity = velocity; this._spin3d = spin; if (spin.Length() > 0 && (spin.X != 0 || spin.Y != 0) && (velocity.X != 0 || velocity.Y != 0)) { this.RealignSpin(); } ConstructProjection(); }
/// <summary> /// Returns a double that measures the usefulness of a ground pass to passTarget /// </summary> private double EvaluatorPassGround(Footballer passTarget) { double evaluation = 0; Vector2d passVector = passTarget.PositionDouble - _owner.PositionDouble; // add bonus for short passes (1,e) evaluation += Math.Pow(Math.E, (1 - passVector.Length() / Constants.ActualXMax)); // add bonus for going in the direction of enemy goal (0,1) Vector2d goalPosition = Constants.Uprights[0]; //upper-left post if (!_owner.Team.AttackingLeft) { goalPosition = Constants.Uprights[2]; //upper-right post } double angle = passVector.AngleBetween(goalPosition - _owner.PositionDouble); angle = Math.Abs(angle - Math.PI); evaluation += (angle / Math.PI); // add large bonus if lane of passing is empty (0 or 3). List <Coords> lane = _owner.InhabitedMap.RayTracer(_owner.PositionOnInfMap(), passTarget.PositionOnInfMap()); InfluenceMap enemyMap = _owner.EnemyTeam.TeamInfluenceMap; double interdiction = 0; for (int i = 0; i < lane.Count; ++i) { // these should be weighted somehow double toAdd = enemyMap.GetMapValue(lane[i]); if (toAdd > 0.5) { evaluation += toAdd; } } if (interdiction == 0) { evaluation += 3; } // there should be a bonus for players making runs return(evaluation); }
public Footballer PlayerNearestToBall() { Footballer nearest = null; double smallestD = Constants.ActualXMax; for (int i = 0; i < _teamRoster.Count; ++i) { Footballer current = _teamRoster[i]; double currentD = current.DistanceToBall(); if (currentD < smallestD) { nearest = current; smallestD = currentD; } } return(nearest); }
private void HandleCollisionBetweenTwoPlayers(Footballer first, Footballer second) { double distance = first.PositionDouble.DistanceTo(second.PositionDouble); double preferredDistance = Math.Sqrt(Math.Pow(first.RadiusX + second.RadiusX, 2) + Math.Pow(first.RadiusY + second.RadiusY, 2)); double deltaOver2 = 0.5 * (preferredDistance - distance); if (deltaOver2 < 0) { return; } // push both actors in opposite direction, by a vector of length delta/2. Vector2d mover = first.PositionDouble - second.PositionDouble; mover.ScaleToLength(deltaOver2); first.PositionDouble += mover; second.PositionDouble -= mover; // this might have cause other collisions. the algo needs fixing. }
private Footballer LookForPass() { Footballer target = null; // pick random target List <Footballer> roster = _owner.Team.TeamRoster; UInt16 choices = (UInt16)roster.Count; RandomStuff randomator = _owner.InhabitedMap.Randomator; UInt32 choice = randomator.NSidedDice(choices, 1) - 1; while (choice == _owner.UniqueID && roster.Count > 1) { choice = randomator.NSidedDice(choices, 1) - 1; } target = roster[(Int32)choice]; return(target); }
public bool ReadyToTakeKickOff() { for (int i = 0; i < _teamRoster.Count - 2; ++i) { Footballer current = _teamRoster[i]; if (!current.IsNear(current.DefaultPositionInHalf())) { return(false); } } for (int i = _teamRoster.Count - 2; i < _teamRoster.Count; ++i) { Footballer current = _teamRoster[i]; if (!current.IsNear(Constants.CenterPoint)) { return(false); } } return(true); }
public Footballer NearestTeammate(Footballer guy) { Footballer nearest = null; double smallestD = Constants.ActualXMax; for (int i = 0; i < _teamRoster.Count; ++i) { Footballer current = _teamRoster[i]; if (current == guy) { continue; } double currentD = current.DistanceToPlayer(guy); if (currentD < smallestD) { nearest = current; smallestD = currentD; } } return(nearest); }
public void UpdateFootballerBoxes(Footballer someGuy, Vector2d oldPosition) { Coords oldCoords = new Coords((Int32)(oldPosition.X / _pixelsPerBoxX), (Int32)(oldPosition.Y / _pixelsPerBoxY)); Coords newCoords = new Coords((Int32)(someGuy.PositionDouble.X / _pixelsPerBoxX), (Int32)(someGuy.PositionDouble.Y / _pixelsPerBoxY)); if (oldCoords == newCoords) { // nothing to do return; } LinkedList <Coords> steppedOn = TilesCoveredByEllipse(new Coords(someGuy.PositionDouble), someGuy.RadiusX, someGuy.RadiusY); foreach (Coords c in _occupiedBoxes[someGuy]) { this.ClippingBoxesRemoveFrom(c, someGuy); } foreach (Coords c in steppedOn) { this.ClippingBoxesAddTo(c, someGuy); } _occupiedBoxes[someGuy] = steppedOn; }
public ActionTakeAShot(Footballer owner) : base(owner) { // turn to face goal //_owner.TurnToFace(new Vector2d(Constants.GoalLeft, Constants.GoalTop) - _owner.PositionDouble); }
/// <summary> /// Add Footballer to the menagerie. They 'key' is the Footballer ID. /// </summary> public void RosterAddFootballerTo(UInt32 key, Footballer newGuy) { this._roster[key] = newGuy; //this._teamRoster[(sbyte)newGuy.Team][key] = newGuy; }
public Action(Footballer owner) { _owner = owner; }
public double DistanceToPlayer(Footballer someGuy) { return((this._positionDouble - someGuy.PositionDouble).Length()); }
public void AddForPaintingFootballer(Footballer critter) { this._FootballersToDraw.Add(critter); }
public DoubleFootballerPair(double val, Footballer guy) { value = val; player = guy; }
public ActionWait(Footballer owner, UInt16 releaseTime) : base(owner) { _releaseTime = releaseTime; }
public ActionGoto(Footballer owner, Vector2d target) : base(owner) { _target = target; _owner.MoveTo(_target); }
public ActionStumble(Footballer owner) : base(owner) { }
public ActionChallenge(Footballer owner, Vector2d direction) : base(owner) { _direction = direction; }
public ActionAnticipate(Footballer owner) : base(owner) { _owner.Stop(); }
public ActionDribbleTo(Footballer owner, Vector2d target) : base(owner) { _target = target; }