public bool ExecuteMotion(ref EntityLogic.Actions actions, Entity currentState, int generation, EntityRandom random, float myYield, ref int spawn) { bool rs = false; switch (generation % 3) { case 0: //receive unicast, send broadcast if (animal == null) { foreach (var msg in currentState.EnumInboundEntityMessages(channel)) { if (!msg.IsBroadcast) //coming around { if (animal != null) { throw new ExecutionException(currentState.ID, "Trying to import multiple animals"); } animal = new Animal(msg.Payload); rs = true; } } } if (animal != null) { actions.Broadcast(channel, null); //can i go there? } break; case 1: //receive broadcast, send unicast if (animal == null) { LazyList <Actor> competitors = new LazyList <Actor>(); foreach (var msg in currentState.EnumInboundEntityMessages(channel)) { if (msg.IsBroadcast && msg.Payload == null) //can i go here? { competitors.Add(msg.Sender); } } if (competitors.IsNotEmpty) { actions.Send(competitors[random.Next(competitors.Count)], channel, BitConverter.GetBytes(myYield)); //you can go here } } break; case 2: //receive unicast, send unicast if (animal != null) { LazyList <Tuple <Actor, float> > options = new LazyList <Tuple <Actor, float> >(); foreach (var msg in currentState.EnumInboundEntityMessages(channel)) { if (!msg.IsBroadcast && Helper.Length(msg.Payload) == 4) //i can go there { options.Add(new Tuple <Actor, float>(msg.Sender, BitConverter.ToSingle(msg.Payload, 0))); } } options.Sort((a, b) => { return(a.Item2.CompareTo(b.Item2)); }); if (options.IsNotEmpty) { if (spawn > 0) { foreach (var o in options) { actions.Send(o.Item1, channel, new Animal(0).Export()); //coming around if (--spawn <= 0) { break; } } spawn = 0; } else { actions.Send(options.Last.Item1, channel, animal.Export()); //coming around } animal = null; //in transit } } break; } return(rs); }
public List <EntityError> Evolve(IReadOnlyList <Entity> entities, Dictionary <Guid, ClientMessage[]> clientMessages, InconsistencyCoverage ic, TimeSpan budget, EntityChange.ExecutionContext ctx) { if (ic.Size != InconsistencyCoverage.CommonResolution) { throw new IntegrityViolation("Trying to evolve with an IC of size " + ic.Size + ". Should be " + InconsistencyCoverage.CommonResolution); } int numErrors = 0; List <Task> tasks = new List <Task>(); List <Entity.TimeTrace> tables = new List <Entity.TimeTrace>(); ClientMessage[] clientBroadcasts = null; if (clientMessages != null) { clientMessages.TryGetValue(Guid.Empty, out clientBroadcasts); } Stopwatch watch0 = new Stopwatch(); object lazyLock = new object(); bool exceeded = false; var rs = new LazyList <EntityError>(); Parallel.For(0, entities.Count, i => { Entity e = entities[i]; ClientMessage[] messages = null; if (clientMessages != null) { clientMessages.TryGetValue(e.ID.Guid, out messages); } var t = new Entity.TimeTrace(watch0); //tables.Add(t); EntityLogic st = null; try { if (!exceeded) { st = e.Evolve(t, this, Helper.Concat(clientBroadcasts, messages), ctx, ic.IsInconsistentR(ctx.LocalSpace.Relativate(e.ID.Position))); if (e.transientDeserializedLogic != null) { throw new IntegrityViolation("Transient deserialized logic was not wiped"); } } if (exceeded || watch0.Elapsed > budget) { exceeded = true; throw new TimeBudgetException(budget, t); } } catch (AssertFailedException) { throw; } catch (Exception ex) { if (st == null) { st = (EntityLogic)Helper.Deserialize(e.SerialLogicState); } var error = new EntityError(e, st, ex); lock (lazyLock) rs.Add(error); ic.FlagInconsistentR(ctx.LocalSpace.Relativate(e.ID.Position)); Interlocked.Increment(ref numErrors); } }); /* * * watch0.Start(); * foreach (var e in entities) * { * EntityMessage[] messages = null; * if (clientMessages != null) * { * clientMessages.TryGetValue(e.ID.Guid, out messages); * } * var t = new Entity.TimeTrace(watch0); * tables.Add(t); * tasks.Add(e.EvolveAsync(t,this, roundNumber, maySendMessages,Helper.Concat(clientBroadcasts, messages))); * } * int at = 0; * * Stopwatch watch = new Stopwatch(); * watch.Start(); * * LazyList<EntityEvolutionException> rs = new LazyList<EntityEvolutionException>(); * * foreach (var e in entities) * { * try * { * var remaining = (budget - watch.Elapsed).NotNegative(); * if (!tasks[at].Wait( remaining)) * throw new ExecutionException(e.ID, "Failed to execute " + (EntityLogic)Helper.Deserialize(e.SerialLogicState)+" in "+remaining.TotalMilliseconds+" ms"); * } * catch (Exception ex) * { * rs.Add(new EntityEvolutionException(e, ex, tables[at])); * * ic.FlagInconsistentR(Simulation.MySpace.Relativate(e.ID.Position)); * * Interlocked.Increment(ref numErrors); * } * at++; * }*/ return(rs.InternalList); }