• Main Page
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List

D:/Projekt/ECF_trunk/examples/GPSpaceFlight/SpaceFlight.Simulation/AiShipController.cs

00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 
00005 namespace SpaceFlight.Simulation
00006 {
00007   public class AiShipController : IShipController
00008   {
00009     private INode root;
00010 
00011     public AiShipController(string nodes)
00012     {
00013       root = Parse(nodes.Trim().Split(' ').AsEnumerable().GetEnumerator());
00014     }
00015 
00016     public void UpdateShip(TestCase testCase, Vector2D gravity)
00017     {
00018       var context = new Dictionary<string, double>();
00019       context["pi"] = Math.PI;
00020 
00021       Vector2D target = testCase.Waypoints[testCase.TargetWaypoint] - testCase.Ship.Position;
00022       context["td"] = target.Length;
00023       context["ta"] = Vector2D.Angle(testCase.Ship.Direction, target);
00024 
00025       context["vm"] = testCase.Ship.Velocity.Length;
00026       context["va"] = Vector2D.Angle(testCase.Ship.Direction, testCase.Ship.Velocity);
00027       context["gm"] = gravity.Length;
00028       context["ga"] = Vector2D.Angle(testCase.Ship.Direction, gravity);
00029 
00030       var nearest = testCase.Planets
00031         .DefaultIfEmpty(new Planet { Position = new Vector2D { X = -2000, Y = -2000 } })
00032         .Select(p => new { Distance = p.Position - testCase.Ship.Position, Raidus = p.Radius })
00033         .OrderBy(p => p.Distance.Length - p.Raidus)
00034         .First();
00035 
00036       context["npd"] = nearest.Distance.Length - nearest.Raidus;
00037       context["npa"] = Vector2D.Angle(testCase.Ship.Direction, nearest.Distance);
00038 
00039       testCase.Ship.Turn = root.Evaluate(context);
00040     }
00041 
00042     private INode Parse(IEnumerator<string> tokens)
00043     {
00044       tokens.MoveNext();
00045       string symbol = tokens.Current;
00046       if (new [] { "+", "-", "*", "/" }.Contains(symbol))
00047       {
00048         return new OperatorNode(symbol[0], Parse(tokens), Parse(tokens));
00049       }
00050       else if (symbol == "iflt")
00051       {
00052         return new BranchNode(Parse(tokens), Parse(tokens), Parse(tokens), Parse(tokens));
00053       }
00054       else if (new [] { "td", "ta", "vm", "va", "npd", "npa" }.Contains(symbol))
00055       {
00056         return new VariableNode(symbol);
00057       }
00058       else
00059       {
00060         if (symbol.StartsWith("D_") || symbol.StartsWith("I_"))
00061         {
00062           symbol = symbol.Substring(2);
00063         }
00064         return new ValueNode(double.Parse(symbol));
00065       }
00066     }
00067   }
00068 
00069   internal interface INode
00070   {
00071     double Evaluate(IDictionary<string, double> context);
00072   }
00073 
00074   internal class OperatorNode : INode
00075   {
00076     private char oper;
00077     private INode firstArg;
00078     private INode secondArg;
00079 
00080     public OperatorNode(char oper, INode firstArg, INode secondArg)
00081     {
00082       this.oper = oper;
00083       this.firstArg = firstArg;
00084       this.secondArg = secondArg;
00085     }
00086 
00087     public double Evaluate(IDictionary<string, double> context)
00088     {
00089       double first = firstArg.Evaluate(context);
00090       double second = secondArg.Evaluate(context);
00091       switch (oper)
00092       {
00093         case '+':
00094         {
00095           return first + second;
00096         }
00097         case '-':
00098         {
00099           return first - second;
00100         }
00101         case '*':
00102         {
00103           return first * second;
00104         }
00105         case '/':
00106         {
00107           return Math.Abs(second) > 1e-5 ? first / second : 1;
00108         }
00109         default:
00110         {
00111           throw new ArgumentException();
00112         }
00113       }
00114     }
00115   }
00116 
00117   internal class BranchNode : INode
00118   {
00119     private INode first, second;
00120     private INode less, greater;
00121 
00122     public BranchNode(INode first, INode second, INode lessEqual, INode greater)
00123     {
00124       this.first = first;
00125       this.second = second;
00126       this.less = lessEqual;
00127       this.greater = greater;
00128     }
00129 
00130     public double Evaluate(IDictionary<string, double> context)
00131     {
00132       if (first.Evaluate(context) < second.Evaluate(context))
00133       {
00134         return less.Evaluate(context);
00135       }
00136       else
00137       {
00138         return greater.Evaluate(context);
00139       }
00140     }
00141   }
00142 
00143   internal class ValueNode : INode
00144   {
00145     private double value;
00146 
00147     public ValueNode(double value)
00148     {
00149       this.value = value;
00150     }
00151 
00152     public double Evaluate(IDictionary<string, double> context)
00153     {
00154       return value;
00155     }
00156   }
00157 
00158   internal class VariableNode : INode
00159   {
00160     private string variable;
00161 
00162     public VariableNode(string variable)
00163     {
00164       this.variable = variable;
00165     }
00166 
00167     public double Evaluate(IDictionary<string, double> context)
00168     {
00169       return context[variable];
00170     }
00171   }
00172 }

Generated on Tue Oct 23 2012 11:14:22 for ECF by  doxygen 1.7.1