diff --git a/OGP1718-Worms/src/worms/facade/Facade.java b/OGP1718-Worms/src/worms/facade/Facade.java index 2147ea0..13aae1a 100644 --- a/OGP1718-Worms/src/worms/facade/Facade.java +++ b/OGP1718-Worms/src/worms/facade/Facade.java @@ -37,7 +37,7 @@ public class Facade implements IFacade { worm.turn(angle); } catch (AssertionError e) { - throw new ModelException(""); + throw new ModelException(e); } } @@ -77,7 +77,7 @@ public class Facade implements IFacade { try { worm.move(); } catch(IllegalArgumentException e) { - throw new ModelException(""); + throw new ModelException(e); } } @@ -392,7 +392,11 @@ public class Facade implements IFacade { */ @Override public void eat(Worm worm) { - worm.checkEat(); + try { + worm.checkEat(); + } catch (IllegalStateException e){ + throw new ModelException(e); + } } /** @@ -1043,8 +1047,11 @@ public class Facade implements IFacade { */ @Override public void loadProgramOnWorm(Worm worm, Program program, IActionHandler actionHandler) throws ModelException { - actionHandler.toString(); - program.toString(); + try { + worm.loadProgram(program, actionHandler); + } catch (IllegalStateException e) { + throw new ModelException(e); + } } /** @@ -1060,7 +1067,11 @@ public class Facade implements IFacade { */ @Override public List executeProgram(Worm worm) throws ModelException { - return null; + try { + return worm.getProgram().debugExecute(worm); + } catch(IllegalArgumentException | IllegalStateException | ClassCastException e) { + throw new ModelException(e); + } } /** diff --git a/OGP1718-Worms/src/worms/model/Program.java b/OGP1718-Worms/src/worms/model/Program.java index 1a83014..f2d0623 100644 --- a/OGP1718-Worms/src/worms/model/Program.java +++ b/OGP1718-Worms/src/worms/model/Program.java @@ -1,33 +1,215 @@ package worms.model; import worms.internal.gui.game.IActionHandler; +import worms.programs.ArgumentExpression; +import worms.programs.Expression; import worms.programs.Procedure; import worms.programs.Statement; -import java.util.List; +import java.util.*; + +import static java.lang.Math.ceil; +import static java.lang.Math.toDegrees; public class Program { - private final List procedureList; + private final Map procMap; + private final Map varMap = new HashMap<>(); + private final List printList = new ArrayList<>(); + + private boolean enoughAP = true; + + private IActionHandler actionHandler; + private Worm worm; private final Statement main; public Program(List proc, Statement main) { - this.procedureList = proc; this.main = main; + procMap = new HashMap<>(); + proc.forEach(p -> procMap.put(p.getName(), p.getBody())); } + @SuppressWarnings("unchecked") protected void execute(Worm worm) { + // reset everything + enoughAP = true; + + if (iteratorStack.empty()) { + executeStatement(main); + } else { + executeStatement(lastStatement); + while (!iteratorStack.empty()) { + Iterator it = iteratorStack.pop(); + while (it.hasNext()) { + executeStatement(it.next()); + if (!enoughAP) { + iteratorStack.push(it); + break; + } + } + if (!enoughAP) break; + } + } + } + + public List debugExecute(Worm worm) { + + execute(worm); + + if (!enoughAP) return null; + iteratorStack.clear(); + return printList; + } + + private boolean breakLoop = false; + + @SuppressWarnings("unchecked") + private void executeStatement(Statement s) { + + if (!enoughAP) return; + + Statement.Type mainType = s.getType(); + + switch (mainType) { + case BLOCK: + executeStatementBlock((List) s.getData()); + break; + case ASSIGN: + Statement.Assign data = (Statement.Assign) s.getData(); + if (procMap.containsKey(data.getVariableName())) throw new IllegalArgumentException("Already a procedure with same name."); + varMap.put(data.getVariableName(), data.getValue()); + break; + case PRINT: + printList.add(processExpression((Expression) s.getData())); + break; + case ACTION: + Statement.Action action = (Statement.Action) s.getData(); + switch (action.getType()) { + case TURN: + Double val = (Double) processExpression(action.getValue()); + if (val == null) throw new IllegalArgumentException("Turn cannot be null"); + if (worm.getActionPoints() - (long) Math.abs(ceil(toDegrees(val) / 6)) < 0) { + enoughAP = false; + lastStatement = s; + return; + } + else if (!worm.canTurn(val)) throw new IllegalArgumentException("Invalid turn value"); + actionHandler.turn(worm, (double) processExpression(action.getValue())); + break; + case MOVE: + try { + actionHandler.move(worm); + } catch (IllegalArgumentException e) { + enoughAP = false; + lastStatement = s; + return; + } + break; + case JUMP: + if (worm.getActionPoints() < 0) { + enoughAP = false; + lastStatement = s; + return; + } + actionHandler.jump(worm); + break; + case EAT: + if (!worm.canEat()) { + enoughAP = false; + lastStatement = s; + return; + } + actionHandler.eat(worm); + break; + case FIRE: + if (!worm.canFire()) { + enoughAP = false; + lastStatement = s; + return; + } + actionHandler.fire(worm); + break; + } + break; + case WHILE: + + Boolean condition = (Boolean) processExpression(((Statement.While) s.getData()).getCondition()); + if (condition == null) throw new IllegalArgumentException("Condition has to be a boolean"); + while(condition) { + executeStatement(((Statement.While) s.getData()).getBody()); + if (breakLoop) { + breakLoop = false; + break; + } + condition = (Boolean) processExpression(((Statement.While) s.getData()).getCondition()); + if (condition == null) throw new IllegalArgumentException("Condition has to be a boolean"); + } + case IF: + if ((Boolean) processExpression(((Statement.If) s.getData()).getCondition())) { + executeStatement(((Statement.If) s.getData()).getIfBody()); + } else { + Statement elseBody = ((Statement.If) s.getData()).getElseBody(); + if (elseBody != null) { + executeStatement(elseBody); + } + } + break; + case INVOKE: + executeStatement(procMap.get((String) s.getData())); + break; + case BREAK: + breakLoop = true; + break; + } + } + + private Stack> iteratorStack = new Stack<>(); + private Statement lastStatement = null; + + private void executeStatementBlock(List list) { + + Iterator it = list.iterator(); + + iteratorStack.push(it); + + while(it.hasNext()) { + executeStatement(it.next()); + if (!enoughAP) { + break; + } + } + } + + @SuppressWarnings("unchecked") + private Object processExpression(Expression e) { + + if (e instanceof ArgumentExpression) { + switch (((ArgumentExpression) e).getType()) { + + case WORM: + return ((ArgumentExpression) e).execute(worm); + case VAR: + return ((ArgumentExpression) e).execute(varMap); + case GOBJECTS: + return ((ArgumentExpression) e).execute(worm.getWorld().getGameObjects()); + } + } else { + return e.execute(); + } + throw new UnsupportedOperationException(); + } + + public void setActionHandler(IActionHandler actionHandler) { + this.actionHandler = actionHandler; } public Worm getWorm() { - - return null; + return this.worm; } - protected Object findVar(String variableName) { - - return null; + public void setWorm(Worm worm) { + this.worm = worm; } } diff --git a/OGP1718-Worms/src/worms/model/World.java b/OGP1718-Worms/src/worms/model/World.java index c39e3fa..aa34549 100644 --- a/OGP1718-Worms/src/worms/model/World.java +++ b/OGP1718-Worms/src/worms/model/World.java @@ -278,12 +278,18 @@ public class World { double lenX = center[0] + radius * Math.cos(i); double lenY = center[1] + radius * Math.sin(i); - if (i < 1.58 && i > 1.57) { - lenY -= 0.0000000001; - } - else if (i < 0.79 && i > 0.78 ) { +// if (i < 1.58 && i > 1.57) { +// lenY -= 0.0000000001; +// } +// else if (i < 0.79 && i > 0.78 ) { +// lenX -= 0.0000000001; +// } + if (center[0] + radius == lenX) { lenX -= 0.0000000001; } + if (center[1] + radius == lenY) { + lenY -= 0.0000000001; + } if (!isPassable(lenX, lenY)) { return false; diff --git a/OGP1718-Worms/src/worms/model/Worm.java b/OGP1718-Worms/src/worms/model/Worm.java index dce98ad..a145caa 100644 --- a/OGP1718-Worms/src/worms/model/Worm.java +++ b/OGP1718-Worms/src/worms/model/Worm.java @@ -1,6 +1,7 @@ package worms.model; import be.kuleuven.cs.som.annotate.*; +import worms.internal.gui.game.IActionHandler; import worms.util.Coordinate; import worms.util.IllegalNameException; @@ -483,8 +484,6 @@ public class Worm extends GameObject { setLocation(newLocation); subtractActionPoints(cost); - - checkEat(); } /** @@ -646,7 +645,7 @@ public class Worm extends GameObject { * | (!Double.isNaN(angle)) && * | (getActionPoints() - (long) ceil(toDegrees(angle) / 6) >= 0) ) */ - private boolean canTurn(double angle) { + protected boolean canTurn(double angle) { double currentAngle = getOrientation(); return 0 <= angle + currentAngle && angle + currentAngle < (2 * PI) && !Double.isNaN(angle) && @@ -1114,6 +1113,8 @@ public class Worm extends GameObject { if (terminate) food.terminate(); + System.out.println(getWorld().isAdjacent(getLocation(), getRadius())); + double radius = getRadius(); double changeRadius = radius * 0.1; @@ -1172,7 +1173,6 @@ public class Worm extends GameObject { } } setLocation(location); - checkEat(); } /** @@ -1183,6 +1183,8 @@ public class Worm extends GameObject { */ public void checkEat() { + if (!canEat()) throw new IllegalStateException(); + World world = getWorld(); if (world != null) { List foodList = world.getFoodList(); @@ -1194,6 +1196,10 @@ public class Worm extends GameObject { } } + public Boolean canEat() { + return getActionPoints() >= 8; + } + // region firing and projectiles //=================================================================================== @@ -1204,7 +1210,7 @@ public class Worm extends GameObject { private double forceProj; public Projectile fire() { - if (getActionPoints() >= 30 && getWorld() != null) { + if (canFire()) { int random = ThreadLocalRandom.current().nextInt(2); @@ -1222,6 +1228,10 @@ public class Worm extends GameObject { throw new IllegalStateException(); } + public Boolean canFire() { + return getActionPoints() >= 30 && getWorld() != null; + } + // public void hitByRifle() { // decreaseHitPoints(hitpointsProj); // } @@ -1235,4 +1245,31 @@ public class Worm extends GameObject { // =================================================================================== // endregion + + // region program + //=================================================================================== + + private Program program = null; + private IActionHandler actionHandler = null; + + public void loadProgram(Program program, IActionHandler actionHandler) { + + if (getWorld().hasActiveGame()) throw new IllegalStateException(); + + this.program = program; + this.actionHandler = actionHandler; + program.setWorm(this); + program.setActionHandler(actionHandler); + } + + public worms.model.Program getProgram() { + return program; + } + + public IActionHandler getActionHandler() { + return actionHandler; + } + // =================================================================================== + // endregion + } diff --git a/OGP1718-Worms/src/worms/programs/ArgumentBinaryExpression.java b/OGP1718-Worms/src/worms/programs/ArgumentBinaryExpression.java index 198dad5..2297422 100644 --- a/OGP1718-Worms/src/worms/programs/ArgumentBinaryExpression.java +++ b/OGP1718-Worms/src/worms/programs/ArgumentBinaryExpression.java @@ -1,24 +1,23 @@ package worms.programs; +import worms.model.Program; + import java.util.function.BiFunction; -public class ArgumentBinaryExpression extends ArgumentExpression { +public class ArgumentBinaryExpression implements Expression { - private final Expression expression; - private final BiFunction function; + private final Expression expression; + private final BiFunction function; - ArgumentBinaryExpression(Expression expression, BiFunction function, Type type) { - super(type); + ArgumentBinaryExpression(Expression expression, BiFunction function) { this.expression = expression; this.function = function; } @Override - @SuppressWarnings("unchecked") - public R execute(O o) { - + public R execute(Program program) { try { - return function.apply(((Expression) expression).execute(), o); + return function.apply(expression.execute(program), program); } catch (ClassCastException e) { throw new IllegalArgumentException(); } diff --git a/OGP1718-Worms/src/worms/programs/ArgumentExpression.java b/OGP1718-Worms/src/worms/programs/ArgumentExpression.java index d5f25e1..4b9327c 100644 --- a/OGP1718-Worms/src/worms/programs/ArgumentExpression.java +++ b/OGP1718-Worms/src/worms/programs/ArgumentExpression.java @@ -8,11 +8,6 @@ public abstract class ArgumentExpression implements Expression { this.type = type; } - @Override - public R execute() { - throw new UnsupportedOperationException(); - } - public abstract R execute(O o); diff --git a/OGP1718-Worms/src/worms/programs/BinaryExpression.java b/OGP1718-Worms/src/worms/programs/BinaryExpression.java index 7099b65..199ce3f 100644 --- a/OGP1718-Worms/src/worms/programs/BinaryExpression.java +++ b/OGP1718-Worms/src/worms/programs/BinaryExpression.java @@ -1,14 +1,16 @@ package worms.programs; +import worms.model.Program; + import java.util.function.BiFunction; public class BinaryExpression implements Expression { - private final Expression left; - private final Expression right; + private final Expression left; + private final Expression right; private final BiFunction function; - public BinaryExpression(Expression left, Expression right, BiFunction function) { + public BinaryExpression(Expression left, Expression right, BiFunction function) { this.left = left; this.right = right; this.function = function; @@ -16,9 +18,9 @@ public class BinaryExpression implements Expression { @Override @SuppressWarnings("unchecked") - public R execute() { + public R execute(Program program) { try { - return function.apply(((Expression) left).execute(), ((Expression) right).execute()); + return function.apply(left.execute(program), right.execute(program)); } catch (ClassCastException e) { throw new IllegalArgumentException(); } diff --git a/OGP1718-Worms/src/worms/programs/Expression.java b/OGP1718-Worms/src/worms/programs/Expression.java index 3620556..ba21b55 100644 --- a/OGP1718-Worms/src/worms/programs/Expression.java +++ b/OGP1718-Worms/src/worms/programs/Expression.java @@ -2,7 +2,7 @@ package worms.programs; import worms.model.Program; -public interface Expression { +public interface Expression { - T execute(); + R execute(Program program); } diff --git a/OGP1718-Worms/src/worms/programs/Procedure.java b/OGP1718-Worms/src/worms/programs/Procedure.java index 88a9300..2275b50 100644 --- a/OGP1718-Worms/src/worms/programs/Procedure.java +++ b/OGP1718-Worms/src/worms/programs/Procedure.java @@ -1,7 +1,5 @@ package worms.programs; -import worms.model.Program; - public class Procedure { diff --git a/OGP1718-Worms/src/worms/programs/ProgramFactory.java b/OGP1718-Worms/src/worms/programs/ProgramFactory.java index 0026cee..5243810 100644 --- a/OGP1718-Worms/src/worms/programs/ProgramFactory.java +++ b/OGP1718-Worms/src/worms/programs/ProgramFactory.java @@ -7,6 +7,7 @@ import worms.util.ModelException; import worms.util.MustNotImplementException; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Set; @@ -196,10 +197,10 @@ public class ProgramFactory implements IProgramFactory>(ArgumentExpression.Type.VAR) { + return new ArgumentExpression>(ArgumentExpression.Type.VAR) { @Override - public Object execute(List o) { - return null; + public Object execute(HashMap map) { + return map.get(variableName).execute(); } }; } @@ -214,7 +215,7 @@ public class ProgramFactory implements IProgramFactory(ArgumentExpression.Type.WORM) { - @Override - public Worm execute(Worm o) { - return o; - } - }; + return new UnaryArgumentExpression(w -> w.getWorm()); } /** @@ -342,17 +338,14 @@ public class ProgramFactory implements IProgramFactory(ArgumentExpression.Type.GOBJECTS) { - @Override - public GameObject execute(Worm o) { - throw new UnsupportedOperationException(); - } - - public GameObject execute(Worm o, Set gobjects) { - return gobjects.stream().filter(g -> g.getAngle(o) == o.getOrientation()).min( - Comparator.comparingDouble(gameObject -> gameObject.getDistance(o))).orElse(null); - } - }; + return new ArgumentBinaryExpression( + angleDelta, (a, p) -> p.getWorm() + .getWorld() + .getGameObjects() + .stream() + .filter(g -> g.getAngle(p.getWorm()) == p.getWorm().getOrientation()) + .min(Comparator.comparingDouble(gameObject -> gameObject.getDistance(p.getWorm()))) + .orElse(null)); } /** @@ -366,7 +359,7 @@ public class ProgramFactory implements IProgramFactory(entity, (w, y) -> w.getTeam().equals(y.getTeam()), ArgumentExpression.Type.WORM); + return new ArgumentBinaryExpression(entity, (w, p) -> w.getTeam().equals(p.getWorm().getTeam())); } /** @@ -379,7 +372,7 @@ public class ProgramFactory implements IProgramFactory(entity, (e, o) -> e.getDistance(o), ArgumentExpression.Type.WORM); + return new ArgumentBinaryExpression(entity, (e, p) -> e.getDistance(p.getWorm()); } /** @@ -392,6 +385,6 @@ public class ProgramFactory implements IProgramFactory(entity, w -> w instanceof Worm); + return new UnaryExpression<>(entity, w -> w instanceof Worm); } } diff --git a/OGP1718-Worms/src/worms/programs/Statement.java b/OGP1718-Worms/src/worms/programs/Statement.java index e1a6c1c..089af84 100644 --- a/OGP1718-Worms/src/worms/programs/Statement.java +++ b/OGP1718-Worms/src/worms/programs/Statement.java @@ -76,9 +76,15 @@ public class Statement { public static class Action { private final Type type; - private final Expression value; + private final Expression value; - public Action(Type type, Expression value) { + /** + * + * @param type + * @param value + */ + @SuppressWarnings("unchecked") + public Action(Type type, Expression value) { this.type = type; this.value = value; } @@ -87,7 +93,7 @@ public class Statement { return type; } - public Expression getValue() { + public Expression getValue() { return value; } @@ -109,5 +115,13 @@ public class Statement { this.variableName = variableName; this.value = value; } + + public Expression getValue() { + return value; + } + + public String getVariableName() { + return variableName; + } } } diff --git a/OGP1718-Worms/src/worms/programs/UnaryArgumentExpression.java b/OGP1718-Worms/src/worms/programs/UnaryArgumentExpression.java new file mode 100644 index 0000000..55933c7 --- /dev/null +++ b/OGP1718-Worms/src/worms/programs/UnaryArgumentExpression.java @@ -0,0 +1,25 @@ +package worms.programs; + +import worms.model.Program; + +import java.util.function.Function; + +public class UnaryArgumentExpression implements Expression { + + private final Function function; + + public UnaryArgumentExpression(Function unaryOperator) { + this.function = unaryOperator; + } + + @Override + @SuppressWarnings("unchecked") + public R execute(Program program) { + + try { + return function.apply(program); + } catch (ClassCastException e) { + throw new IllegalArgumentException(); + } + } +} diff --git a/OGP1718-Worms/src/worms/programs/UnaryExpression.java b/OGP1718-Worms/src/worms/programs/UnaryExpression.java index fd2e7a6..6e8abfc 100644 --- a/OGP1718-Worms/src/worms/programs/UnaryExpression.java +++ b/OGP1718-Worms/src/worms/programs/UnaryExpression.java @@ -1,23 +1,25 @@ package worms.programs; +import worms.model.Program; + import java.util.function.Function; public class UnaryExpression implements Expression { - protected final Expression expression; + protected final Expression expression; private final Function function; - public UnaryExpression(Expression expression, Function unaryOperator) { + public UnaryExpression(Expression expression, Function unaryOperator) { this.expression = expression; this.function = unaryOperator; } @Override @SuppressWarnings("unchecked") - public R execute() { + public R execute(Program program) { try { - return function.apply(((Expression) expression).execute()); + return function.apply( expression.execute(program)); } catch (ClassCastException e) { throw new IllegalArgumentException(); }