using System.Collections.Generic; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.Robocode { [StorableClass] [Item("Robocode Grammar", "The grammar for the Robocode GP problem.")] public class Grammar : SymbolicExpressionGrammar { [StorableConstructor] private Grammar(bool deserializing) : base(deserializing) { } private Grammar(Grammar original, Cloner cloner) : base(original, cloner) { } public Grammar() : base("Robocode Grammar", "The grammar for the Robocode GP problem.") { Initialize(); } public override IDeepCloneable Clone(Cloner cloner) { return new Grammar(this, cloner); } // initialize set of allowed symbols and define // the allowed combinations of symbols private void Initialize() { #region Symbols var block = new Block(); var ifStmt = new IfStatement(); var elseStmt = new ElseStatement(); var whileLoop = new WhileLoop(); var numExpr = new NumericalExpression(); var number = new Number(); var numOp = new NumericalOperation(); var add = new Addition(); var sub = new Subtraction(); var mult = new Multiplication(); var div = new Division(); var mod = new Modulus(); var logicExpr = new LogicalExpression(); var logicComp = new LogicalComparison(); var numComp = new NumericalComparison(); var logicVal = new LogicalValue(); var not = new Negation(); var and = new Conjunction(); var or = new Disjunction(); var eq = new Equal(); var lt = new LessThan(); var gt = new GreaterThan(); var lteq = new LessThanOrEqual(); var gteq = new GreaterThanOrEqual(); var ahead = new Ahead(); var back = new Back(); var constant = new Constant(); var doNothing = new DoNothing(); var fire = new Fire(); var shotPower = new ShotPower(); var getEnergy = new GetEnergy(); var getGunHeading = new GetGunHeading(); var getHeading = new GetHeading(); var getRadarHeading = new GetRadarHeading(); var getX = new GetX(); var getY = new GetY(); //var setAdjustGunForRobotTurn = new SetAdjustGunForRobotTurn(); //var setAdjustRadarForGunTurn = new SetAdjustRadarForGunTurn(); //var setAdjustRadarForRobotTurn = new SetAdjustRadarForRobotTurn(); //var independent = new Independent(); var turnLeft = new TurnLeft(); var turnRight = new TurnRight(); var turnGunLeft = new TurnGunLeft(); var turnGunRight = new TurnGunRight(); var turnRadarLeft = new TurnRadarLeft(); var turnRadarRight = new TurnRadarRight(); var onBulletHit = new OnBulletHit(); var onBulletMissed = new OnBulletMissed(); var onHitByBullet = new OnHitByBullet(); var onHitRobot = new OnHitRobot(); var onHitWall = new OnHitWall(); var onScannedRobot = new OnScannedRobot(); var emptyEvent = new EmptyEvent(); var run = new Run(); var tank = new Tank(); var program = new Program(); #endregion #region Symbol Collections var numericalExpressions = new List() { number, numOp, getEnergy, getGunHeading, getHeading, getRadarHeading, getX, getY }; var numericalOperators = new List() { add, sub, mult, div, mod }; var logicalExpressions = new List() { logicVal, logicComp, numComp, not }; var logicalComparators = new List() { and, or }; var numericalComparators = new List() { lt, gt, lteq, gteq, eq }; var terminalSymbols = new List() { doNothing, //getEnergy, getGunHeading, getHeading, getRadarHeading, getX, getY }; var functionSymbols = new List() { ahead, back, fire, //setAdjustGunForRobotTurn, setAdjustRadarForGunTurn, setAdjustRadarForRobotTurn, turnGunLeft, turnGunRight, turnLeft, turnRadarLeft, turnRadarRight, turnRight }; var constantSymbols = new List() { shotPower, /*independent,*/ constant }; var eventSymbols = new List() { run, onBulletHit, onBulletMissed, onHitByBullet, onHitRobot, onHitWall, onScannedRobot, block, emptyEvent }; #endregion #region Adding Symbols // add all symbols to the grammar AddSymbol(ifStmt); AddSymbol(elseStmt); AddSymbol(whileLoop); AddSymbol(numExpr); foreach (var s in numericalExpressions) AddSymbol(s); foreach (var s in numericalOperators) AddSymbol(s); AddSymbol(logicExpr); foreach (var s in logicalExpressions) AddSymbol(s); foreach (var s in logicalComparators) AddSymbol(s); foreach (var s in numericalComparators) AddSymbol(s); foreach (var s in terminalSymbols) AddSymbol(s); foreach (var s in functionSymbols) AddSymbol(s); foreach (var s in constantSymbols) AddSymbol(s); foreach (var s in eventSymbols) AddSymbol(s); AddSymbol(tank); #endregion #region Defining Grammar // define grammar rules // Branches AddAllowedChildSymbol(ifStmt, logicExpr, 0); AddAllowedChildSymbol(ifStmt, block, 1); AddAllowedChildSymbol(ifStmt, elseStmt, 2); AddAllowedChildSymbol(ifStmt, doNothing, 2); AddAllowedChildSymbol(elseStmt, block); AddAllowedChildSymbol(whileLoop, logicExpr, 0); AddAllowedChildSymbol(whileLoop, block, 1); // Numerical Expressions foreach (var s in numericalExpressions) { AddAllowedChildSymbol(numExpr, s); AddAllowedChildSymbol(numOp, s, 1); AddAllowedChildSymbol(numOp, s, 2); } foreach (var s in numericalOperators) AddAllowedChildSymbol(numOp, s, 0); // Logical Expressions foreach (var s in logicalExpressions) { AddAllowedChildSymbol(logicExpr, s); AddAllowedChildSymbol(not, s); AddAllowedChildSymbol(logicComp, s, 1); AddAllowedChildSymbol(logicComp, s, 2); } foreach (var s in logicalComparators) AddAllowedChildSymbol(logicComp, s, 0); foreach (var s in numericalExpressions) { AddAllowedChildSymbol(numComp, s, 1); AddAllowedChildSymbol(numComp, s, 2); } foreach (var s in numericalComparators) AddAllowedChildSymbol(numComp, s, 0); // All Void Statements can appear in run or in an event handler or inside a block foreach (var e in eventSymbols) { AddAllowedChildSymbol(e, ifStmt); AddAllowedChildSymbol(e, whileLoop); AddAllowedChildSymbol(e, doNothing); foreach (var f in functionSymbols) AddAllowedChildSymbol(e, f); } // Add the appropriate parameters as children of their respective functions foreach (var f in functionSymbols) { if (f is SetAdjustGunForRobotTurn || f is SetAdjustRadarForGunTurn || f is SetAdjustRadarForRobotTurn) AddAllowedChildSymbol(f, logicExpr); else if (f is Fire) AddAllowedChildSymbol(f, shotPower); else AddAllowedChildSymbol(f, numExpr); } // Add all Event Methods to Tank. Run and OnScannedEvent are not optional, // so EmptyEvent cannot take their places AddAllowedChildSymbol(tank, run, 0); AddAllowedChildSymbol(tank, onScannedRobot, 1); AddAllowedChildSymbol(tank, onBulletMissed, 2); AddAllowedChildSymbol(tank, onHitByBullet, 3); AddAllowedChildSymbol(tank, onHitRobot, 4); AddAllowedChildSymbol(tank, onHitWall, 5); AddAllowedChildSymbol(tank, onBulletHit, 6); for (int i = 2; i < tank.MaximumArity; i++) AddAllowedChildSymbol(tank, emptyEvent, i); AddAllowedChildSymbol(StartSymbol, tank, 0); #endregion } } }