public void OnPlaceClaimCmd(PlaceClaimMsg msg) { // Apian has said this message is authoritative BaseBike b = CoreData.GetBaseBike(msg.bikeId); if (CoreData.Ground.IndicesAreOnMap(msg.xIdx, msg.zIdx)) { if (b == null) { logger.Warn($"OnPlaceClaimCmd() Bike:{msg.bikeId} not found!"); // can happen if RemoveCmd and ClaimObs interleave return; } b.UpdatePosFromCommand(msg.TimeStamp, FrameApianTime, BeamPlace.PlacePos(msg.xIdx, msg.zIdx), msg.exitHead); // Claim it BeamPlace p = CoreData.ClaimPlace(b, msg.xIdx, msg.zIdx, msg.TimeStamp + BeamPlace.kLifeTimeMs); if (p != null) { ApplyScoreUpdate(msg.scoreUpdates); logger.Verbose($"OnPlaceClaimCmd() Bike: {b.bikeId} claimed {BeamPlace.PlacePos( msg.xIdx, msg.zIdx).ToString()} at {msg.TimeStamp}"); //logger.Verbose($" BikePos: {b.position.ToString()}, FrameApianTime: {FrameApianTime} "); //logger.Verbose($" at Timestamp: BikePos: {b.PosAtTime(msg.TimeStamp, FrameApianTime).ToString()}, Time: {msg.TimeStamp} "); PlaceClaimedEvt?.Invoke(this, p); } else { logger.Warn($"OnPlaceClaimCmd()) failed. Place already claimed."); } } }
public void OnPlaceRemovedCmd(PlaceRemovedMsg msg) { BeamPlace p = CoreData.GetPlace(msg.xIdx, msg.zIdx); logger.Verbose($"OnPlaceRemovedCmd({msg.xIdx},{msg.zIdx}) {(p==null?"MISSING":"")} Now: {FrameApianTime} Ts: {msg.TimeStamp}"); CoreData.PostPlaceRemoval(p); }
public static BeamPlace FromApianJson(string jsonData, List <string> bikeIdList, Dictionary <string, IBike> bikeDict) { object[] data = JsonConvert.DeserializeObject <object[]>(jsonData); BeamPlace p = new BeamPlace(); p.bike = bikeDict[bikeIdList[(int)(long)data[0]]]; p.xIdx = (int)(long)data[1]; p.zIdx = (int)(long)data[2]; p.expirationTimeMs = (long)data[3]; return(p); }
public void OnPlaceHitCmd(PlaceHitMsg msg) { // Apian has already checked the the place is claimed and the bike exists Vector2 pos = BeamPlace.PlacePos(msg.xIdx, msg.zIdx); BeamPlace p = CoreData.GetPlace(pos); BaseBike hittingBike = CoreData.GetBaseBike(msg.bikeId); if (p != null && hittingBike != null) { hittingBike.UpdatePosFromCommand(msg.TimeStamp, FrameApianTime, p.GetPos(), msg.exitHead); logger.Info($"OnPlaceHitCmd{p?.GetPos().ToString()} Now: {FrameApianTime} Ts: {msg.TimeStamp} Bike: {hittingBike?.bikeId} Pos: {p?.GetPos().ToString()}"); ApplyScoreUpdate(msg.scoreUpdates); PlaceHitEvt?.Invoke(this, new PlaceHitArgs(p, hittingBike)); } else { logger.Info($"OnPlaceHitCmd{p?.GetPos().ToString()} Now: {FrameApianTime} Ts: {msg.TimeStamp} Bike: {hittingBike?.bikeId} Pos: {p?.GetPos().ToString()}"); } }
public List <MoveNode> next; // length 3 public MoveNode(BeamCoreState gData, Vector2 p, Heading head, TurnDir d, int depth, List <Vector2> otherClaimedPos) { pos = p; dir = d; // for later lookup place = gData.GetPlace(p); score = ScoreForPoint(gData.Ground, pos, place); if (score == 0 && otherClaimedPos.Any(op => op.Equals(pos))) // TODO: make prettier { score = 1; // TODO: use named scoring constants } next = depth < 1 ? null : BikeUtils.PossiblePointsForPointAndHeading(pos, head) .Select((pt, childTurnDir) => new MoveNode(gData, pos + GameConstants.UnitOffset2ForHeading(GameConstants.NewHeadForTurn(head, (TurnDir)childTurnDir)) * Ground.gridSize, head, (TurnDir)childTurnDir, depth - 1, otherClaimedPos)) .ToList(); }
protected void xOnScoreEvent(BaseBike bike, ScoreEvent evt, BeamPlace place) { // Score events: // // TODO: as with above: This is coming from the backend (BaseBike, mostly) and should // be comming from the Net/event/whatever layer // NOTE: I'm not so sure about above comment. It;'s not clear that score changes constitute "events" int scoreDelta = GameConstants.eventScores[(int)evt]; bike.AddScore(scoreDelta); if (evt == ScoreEvent.kHitEnemyPlace || evt == ScoreEvent.kHitFriendPlace) { logger.Debug($"OnScoreEvent(). Bike: {bike.bikeId} Event: {evt}"); // half of the deduction goes to the owner of the place, the rest is divded // among the owner's team // UNLESS: the bike doing the hitting IS the owner - then the rest of the team just splits it if (bike != place.bike) { scoreDelta /= 2; place.bike.AddScore(-scoreDelta); // adds } IEnumerable <IBike> rewardedOtherBikes = CoreData.Bikes.Values.Where(b => b != bike && b.team == place.bike.team); // Bikes other the "bike" on affected team if (rewardedOtherBikes.Count() > 0) { foreach (BaseBike b in rewardedOtherBikes) { b.AddScore(-scoreDelta / rewardedOtherBikes.Count()); } } } if (evt == ScoreEvent.kOffMap || bike.score <= 0) { bike.score = 0; logger.Info($"OnScoreEvent(). Sending RemoveBikeObs: {bike.bikeId}"); apian.SendRemoveBikeObs(FrameApianTime, bike.bikeId); } }
protected Dictionary <string, int> ComputeScoreUpdate(IBike bike, ScoreEvent evt, BeamPlace place) { // BIG NOTE: total score is NOT conserved. Dictionary <string, int> update = new Dictionary <string, int>(); int scoreDelta = GameConstants.eventScores[(int)evt]; update[bike.bikeId] = scoreDelta; logger.Debug($"ComputeScoreUpdate(). Bike: {bike.bikeId} Event: {evt}"); if (evt == ScoreEvent.kHitEnemyPlace || evt == ScoreEvent.kHitFriendPlace) { // half of the deduction goes to the owner of the place, the rest is divded // among the owner's team // UNLESS: the bike doing the hitting IS the owner - then the rest of the team just splits it if (bike != place.bike) { scoreDelta /= 2; update[place.bike.bikeId] = -scoreDelta; // owner gets half } IEnumerable <IBike> rewardedOtherBikes = CoreData.Bikes.Values.Where(b => b != bike && b.team == place.bike.team); // Bikes other the "bike" on affected team if (rewardedOtherBikes.Count() > 0) { foreach (BaseBike b in rewardedOtherBikes) { update[b.bikeId] = -scoreDelta / rewardedOtherBikes.Count(); // all might not get exactly the same amount } } } if (evt == ScoreEvent.kOffMap) { update[bike.bikeId] = -bike.score * 2; // overdo it } return(update); }
public static int ScoreForPoint(Ground g, Vector2 point, BeamPlace place) { return(g.PointIsOnMap(point) ? (place == null ? 5 : 1) : 0); // 5 pts for a good place, 1 for a claimed one, zero for off-map }
public PlaceHitArgs(BeamPlace _p, IBike _ib) { p = _p; ib = _ib; }