/// <summary> /// Updates the next task to execute. Technites can memorize and execute only one task per round, thus the logic /// must redefine this task each round. If the last task result is TaskResult.MoreWorkNeeded, then the last task /// is not cleared automatically, but can be redefined if desired. /// Calling the method several times on the same technite before a new round is processed will overwrite the previously set task. /// Calling SetNextTask() at all is optional. The technite will sooner or later default to not doing anything in this case. /// </summary> /// <param name="t">Task to execute next</param> /// <param name="target">Location target of the task</param> /// <param name="parameter">Task parameter. What the parameter does depends on the task executed.</param> public void SetNextTask(Task t, Grid.RelativeCell target, byte parameter = 0) { //Out.Log(Significance.Low, this + "->" + t + " @" + target); Grid.CellID absoluteTarget = Location + target; if (!absoluteTarget.IsValid) { throw new TaskException(this, "Trying to set invalid relative target " + target + ". Task not set."); } if (t == Task.SelfTransformToType) { if (parameter > MatterYield.Length) { throw new TaskException(this, "Parameter for task " + t + " (" + parameter + ") is not a valid matter type."); } if (MatterYield[parameter] == 0) { throw new TaskException(this, "Parameter for task " + t + " (" + parameter + "/" + ((Grid.Content)parameter) + ") is not a suitable transformation output."); } } else if ((t == Task.TransferEnergyTo || t == Task.TransferMatterTo) && parameter == 0) { throw new TaskException(this, "Task " + t + " requires a non-zero parameter value"); } Grid.Content content = Grid.World.CellStacks[absoluteTarget.StackID].volumeCell[absoluteTarget.Layer].content; nextTask = t; taskParameter = parameter; taskTarget = target; }
public CompressedTarget(Grid.RelativeCell target) { Data = (byte)((byte)target.NeighborIndex | (byte)((target.HeightDelta + 1) << 4)); }
/// <summary> /// Central logic method. Invoked once per round to determine the next task for each technite. /// </summary> public static void ProcessTechnites() { Out.Log(Significance.Common, "ProcessTechnites()"); //let's do some simple processing // bool slightlyVerbose = Technite.All.Count() < 20; int at = 0; foreach (Technite t in Technite.All) { at++; if (at < 20) { Out.Log(Significance.Low, "Processing " + t); } else if (at == 20) { Out.Log(Significance.Low, "..."); } if (t.Status.TTL <= 1) { t.SetCustomColor(new Technite.Color(255, 0, 0)); } else { float r0 = Grid.CellStack.HeightPerLayer * 2f; float r1 = r0 + Grid.CellStack.HeightPerLayer * 2f; float r02 = r0 * r0, r12 = r1 * r1; int atRange = 2; foreach (var obj in Objects.AllGameObjects) { float d2 = Vec.QuadraticDistance(obj.ID.Location.WorldPosition, t.Location.WorldPosition); if (d2 < r12) { atRange = 1; if (d2 < r02) { atRange = 0; break; } } } //if (atRange == 0) // t.SetCustomColor(new Technite.Color(255,0,0)); //else if (atRange == 0) { t.SetCustomColor(new Technite.Color(32, 32, 32)); } else { t.UnsetCustomColor(); } } //this will color technites depending on their up-direction in the world: //t.SetCustomColor(new Technite.Color(t.Location.UpDirection*0.5f + 0.5f)); if (t.LastTaskResult == Technite.TaskResult.MoreWorkNeeded) { bool skip = false; switch (t.LastTask) { case Technite.Task.ConsumeSurroundingCell: skip = t.CanConsume; break; case Technite.Task.GrowTo: skip = t.CanSplit; break; } if (skip) { //Out.Log(Significance.Common, "Still busy doing last job ("+t.LastTask+"). Allowing technite to continue"); continue; } } if (t.CurrentResources.Energy > 9 && random.NextDouble() < 0.1) { t.SetNextTask(Technite.Task.Scan, Grid.RelativeCell.Self, t.CurrentResources.Energy); continue; } bool tryTransfer = false; if (t.CanSplit) { Grid.RelativeCell target = Helper.GetSplitTarget(t.Location); if (target != Grid.RelativeCell.Invalid) { t.SetNextTask(Technite.Task.GrowTo, target); } else { //Out.Log(Significance.Unusual, "Unable to find adequate splitting destination"); tryTransfer = true; } } else { bool waitForSplitEnergy = t.Status.Lit && t.CurrentResources.Matter >= Technite.SplitMatterCost; if (t.CanGnawAt && !waitForSplitEnergy) { Grid.RelativeCell target = Helper.GetFoodChoice(t.Location); if (target != Grid.RelativeCell.Invalid) { t.SetNextTask(Technite.Task.GnawAtSurroundingCell, target); } else { //Out.Log(Significance.Unusual, "Unable to find adequate eating destination"); tryTransfer = true; } } else { //Out.Log(Significance.Unusual, "Insufficient resources to do anything"); tryTransfer = !waitForSplitEnergy && t.CurrentResources != Technite.Resources.Zero; } } if (tryTransfer) { Grid.RelativeCell target = Grid.RelativeCell.Invalid; Technite.Task task; byte amount = 0; if (t.CurrentResources.Matter > t.CurrentResources.Energy) { //Out.Log(Significance.Low, "Trying to transfer matter"); task = Technite.Task.TransferMatterTo; target = Helper.GetLitOrUpperTechnite(t.Location); amount = t.CurrentResources.Matter; } else { //Out.Log(Significance.Low, "Trying to transfer energy"); task = Technite.Task.TransferEnergyTo; target = Helper.GetUnlitOrLowerTechnite(t.Location); amount = t.CurrentResources.Energy; } if (target != Grid.RelativeCell.Invalid) { t.SetNextTask(task, target, amount); } else { //Out.Log(Significance.Unusual, "Unable to find adequate transfer target"); tryTransfer = true; } } } }
/// <summary> /// Updates the next task to execute. Technites can memorize and execute only one task per round, thus the logic /// must redefine this task each round. If the last task result is TaskResult.MoreWorkNeeded, then the last task /// is not cleared automatically, but can be redefined if desired. /// Calling the method several times on the same technite before a new round is processed will overwrite the previously set task. /// Calling SetNextTask() at all is optional. The technite will sooner or later default to not doing anything in this case. /// </summary> /// <param name="t">Task to execute next</param> /// <param name="target">Location target of the task</param> /// <param name="parameter">Task parameter. What the parameter does depends on the task executed.</param> public void SetNextTask(Task t, Grid.RelativeCell target, byte parameter = 0) { //Out.Log(Significance.Low, this + "->" + t + " @" + target); Grid.CellID absoluteTarget = Location + target; if (!absoluteTarget.IsValid) throw new TaskException(this,"Trying to set invalid relative target "+target+". Task not set."); if (t == Task.SelfTransformToType) { if (parameter > MatterYield.Length) throw new TaskException(this,"Parameter for task "+t+" ("+parameter+") is not a valid matter type."); if (MatterYield[parameter] == 0) throw new TaskException(this,"Parameter for task " + t + " (" + parameter + "/"+((Grid.Content)parameter) + ") is not a suitable transformation output."); } else if ((t == Task.TransferEnergyTo || t == Task.TransferMatterTo) && parameter == 0) throw new TaskException(this, "Task "+t+" requires a non-zero parameter value"); Grid.Content content = Grid.World.CellStacks[absoluteTarget.StackID].volumeCell[absoluteTarget.Layer].content; nextTask = t; taskParameter = parameter; taskTarget = target; }
/// <summary> /// Central logic method. Invoked once per round to determine the next task for each technite. /// </summary> public static void ProcessTechnites() { Out.Log(Significance.Common, "ProcessTechnites()"); int spielphase = 0; foreach (Technite t in Technite.All) { switch (spielphase) { case 0: //Wenn spawn unter der Erde -> Hochfressen Grid.RelativeCell target = Helper.GetSplitTarget(t.Location.TopNeighbor); //Grid.RelativeCell target = new Grid.RelativeCell(t.Location.TopNeighbor.StackID, 1); //if (target != Grid.RelativeCell.Invalid) //{ //t.SetNextTask(Technite.Task.GrowTo, target); //} //else //{ // target = Helper.GetLitOrUpperTechnite(t.Location); // t.SetNextTask(Technite.Task.TransferEnergyTo, target); //} break; case 1: //an der Planetoberfläche Console.WriteLine("test"); if (Technite.All.Count() < 100) { if (t.CanConsume) { target = Helper.GetFoodChoice(t.Location); //Grid.RelativeCell target = Helper.GetSplitTarget(t.Location); t.SetNextTask(Technite.Task.ConsumeSurroundingCell, target); } else if (t.CanSplit) { target = Helper.GetSplitTarget(t.Location); t.SetNextTask(Technite.Task.ConsumeSurroundingCell, target); } } else { Console.WriteLine("mehr als 100"); } break; //case 2: } } ////let's do some simple processing //// bool slightlyVerbose = Technite.All.Count() < 20; //int at = 0; //foreach (Technite t in Technite.All) //{ // at++; // Console.WriteLine("Die höhe dieses Technites: " + t.Location.Layer); // if (at < 20) // Out.Log(Significance.Low, "Processing "+t); // else // if (at == 20) // Out.Log(Significance.Low, "..."); // if (t.Status.TTL <= 1) // t.SetCustomColor(new Technite.Color(255, 0, 0)); // else // { // float r0 = Grid.CellStack.HeightPerLayer * 2f; // float r1 = r0 + Grid.CellStack.HeightPerLayer * 2f; // float r02 = r0*r0, // r12 = r1*r1; // int atRange = 2; // foreach (var obj in Objects.AllGameObjects) // { // float d2 = Vec.QuadraticDistance(obj.ID.Location.WorldPosition,t.Location.WorldPosition); // if (d2 < r12) // { // atRange = 1; // if (d2 < r02) // { // atRange = 0; // break; // } // } // } // //if (atRange == 0) // // t.SetCustomColor(new Technite.Color(255,0,0)); // //else // if (atRange == 0) // t.SetCustomColor(new Technite.Color(32, 32, 32)); // else // t.UnsetCustomColor(); // } // //this will color technites depending on their up-direction in the world: // //t.SetCustomColor(new Technite.Color(t.Location.UpDirection*0.5f + 0.5f)); // if (t.LastTaskResult == Technite.TaskResult.MoreWorkNeeded) // { // bool skip = false; // switch (t.LastTask) // { // case Technite.Task.ConsumeSurroundingCell: // skip = t.CanConsume; // break; // case Technite.Task.GrowTo: // skip = t.CanSplit; // break; // } // if (skip) // { // //Out.Log(Significance.Common, "Still busy doing last job ("+t.LastTask+"). Allowing technite to continue"); // continue; // } // } // if (t.CurrentResources.Energy > 9 && random.NextDouble() < 0.1) // { // t.SetNextTask(Technite.Task.Scan, Grid.RelativeCell.Self, t.CurrentResources.Energy); // continue; // } // bool tryTransfer = false; // if (t.CanSplit) // { // Grid.RelativeCell target = Helper.GetSplitTarget(t.Location); // if (target != Grid.RelativeCell.Invalid) // { // t.SetNextTask(Technite.Task.GrowTo, target); // } // else // { // //Out.Log(Significance.Unusual, "Unable to find adequate splitting destination"); // tryTransfer = true; // } // } // else // { // bool waitForSplitEnergy = t.Status.Lit && t.CurrentResources.Matter >= Technite.SplitMatterCost; // if (t.CanGnawAt && !waitForSplitEnergy) // { // Grid.RelativeCell target = Helper.GetFoodChoice(t.Location); // if (target != Grid.RelativeCell.Invalid) // { // t.SetNextTask(Technite.Task.GnawAtSurroundingCell, target); // } // else // { // //Out.Log(Significance.Unusual, "Unable to find adequate eating destination"); // tryTransfer = true; // } // } // else // { // //Out.Log(Significance.Unusual, "Insufficient resources to do anything"); // tryTransfer = !waitForSplitEnergy && t.CurrentResources != Technite.Resources.Zero; // } // } // if (tryTransfer) // { // Grid.RelativeCell target = Grid.RelativeCell.Invalid; // Technite.Task task; // byte amount = 0; // if (t.CurrentResources.Matter > t.CurrentResources.Energy) // { // //Out.Log(Significance.Low, "Trying to transfer matter"); // task = Technite.Task.TransferMatterTo; // target = Helper.GetLitOrUpperTechnite(t.Location); // amount = t.CurrentResources.Matter; // } // else // { // //Out.Log(Significance.Low, "Trying to transfer energy"); // task = Technite.Task.TransferEnergyTo; // target = Helper.GetUnlitOrLowerTechnite(t.Location); // amount = t.CurrentResources.Energy; // } // if (target != Grid.RelativeCell.Invalid) // { // t.SetNextTask(task, target, amount); // } // else // { // //Out.Log(Significance.Unusual, "Unable to find adequate transfer target"); // tryTransfer = true; // } // } //} }