improved program

This commit is contained in:
2018-05-19 19:43:06 +02:00
parent d80fb7d284
commit fa65975994
13 changed files with 343 additions and 79 deletions

View File

@@ -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) {
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<Object> executeProgram(Worm worm) throws ModelException {
return null;
try {
return worm.getProgram().debugExecute(worm);
} catch(IllegalArgumentException | IllegalStateException | ClassCastException e) {
throw new ModelException(e);
}
}
/**

View File

@@ -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<Procedure> procedureList;
private final Map<String, Statement> procMap;
private final Map<String, Expression> varMap = new HashMap<>();
private final List<Object> printList = new ArrayList<>();
private boolean enoughAP = true;
private IActionHandler actionHandler;
private Worm worm;
private final Statement main;
public Program(List<Procedure> 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<Statement> it = iteratorStack.pop();
while (it.hasNext()) {
executeStatement(it.next());
if (!enoughAP) {
iteratorStack.push(it);
break;
}
}
if (!enoughAP) break;
}
}
}
public List<Object> 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<Statement>) 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<Iterator<Statement>> iteratorStack = new Stack<>();
private Statement lastStatement = null;
private void executeStatementBlock(List<Statement> list) {
Iterator<Statement> 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;
}
}

View File

@@ -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;

View File

@@ -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<Food> 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
}

View File

@@ -1,24 +1,23 @@
package worms.programs;
import worms.model.Program;
import java.util.function.BiFunction;
public class ArgumentBinaryExpression<T, O, R> extends ArgumentExpression<R, O> {
public class ArgumentBinaryExpression<T, R> implements Expression<R> {
private final Expression expression;
private final BiFunction<T, O, R> function;
private final Expression<T> expression;
private final BiFunction<T, Program, R> function;
ArgumentBinaryExpression(Expression expression, BiFunction<T, O, R> function, Type type) {
super(type);
ArgumentBinaryExpression(Expression<T> expression, BiFunction<T, Program, R> 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<T>) expression).execute(), o);
return function.apply(expression.execute(program), program);
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}

View File

@@ -8,11 +8,6 @@ public abstract class ArgumentExpression<R, O> implements Expression<R> {
this.type = type;
}
@Override
public R execute() {
throw new UnsupportedOperationException();
}
public abstract R execute(O o);

View File

@@ -1,14 +1,16 @@
package worms.programs;
import worms.model.Program;
import java.util.function.BiFunction;
public class BinaryExpression<T, R> implements Expression<R> {
private final Expression left;
private final Expression right;
private final Expression<T> left;
private final Expression<T> right;
private final BiFunction<T, T, R> function;
public BinaryExpression(Expression left, Expression right, BiFunction<T, T, R> function) {
public BinaryExpression(Expression<T> left, Expression<T> right, BiFunction<T, T, R> function) {
this.left = left;
this.right = right;
this.function = function;
@@ -16,9 +18,9 @@ public class BinaryExpression<T, R> implements Expression<R> {
@Override
@SuppressWarnings("unchecked")
public R execute() {
public R execute(Program program) {
try {
return function.apply(((Expression<T>) left).execute(), ((Expression<T>) right).execute());
return function.apply(left.execute(program), right.execute(program));
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}

View File

@@ -2,7 +2,7 @@ package worms.programs;
import worms.model.Program;
public interface Expression<T> {
public interface Expression<R> {
T execute();
R execute(Program program);
}

View File

@@ -1,7 +1,5 @@
package worms.programs;
import worms.model.Program;
public class Procedure {

View File

@@ -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<Expression, Statement, Pr
*/
@Override
public Expression createReadVariableExpression(String variableName, SourceLocation sourceLocation) throws ModelException {
return new ArgumentExpression<Object, List<Object>>(ArgumentExpression.Type.VAR) {
return new ArgumentExpression<Object, HashMap<String, Expression>>(ArgumentExpression.Type.VAR) {
@Override
public Object execute(List<Object> o) {
return null;
public Object execute(HashMap<String, Expression> map) {
return map.get(variableName).execute();
}
};
}
@@ -214,7 +215,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
public Expression createDoubleLiteralExpression(double value, SourceLocation location) throws ModelException {
return new Expression() {
@Override
public Object execute() {
public Object execute(Program program) {
return value;
}
};
@@ -230,7 +231,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
public Expression createBooleanLiteralExpression(boolean value, SourceLocation location) throws ModelException {
return new Expression() {
@Override
public Object execute() {
public Object execute(Program program) {
return value;
}
};
@@ -245,7 +246,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
public Expression createNullExpression(SourceLocation location) throws ModelException {
return new Expression() {
@Override
public Object execute() {
public Object execute(Program program) {
return null;
}
};
@@ -260,12 +261,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createSelfExpression(SourceLocation location) throws ModelException {
return new ArgumentExpression<Worm, Worm>(ArgumentExpression.Type.WORM) {
@Override
public Worm execute(Worm o) {
return o;
}
};
return new UnaryArgumentExpression<Worm>(w -> w.getWorm());
}
/**
@@ -342,17 +338,14 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createSearchObjectExpression(Expression angleDelta, SourceLocation sourceLocation) throws ModelException {
return new ArgumentExpression<GameObject, Worm>(ArgumentExpression.Type.GOBJECTS) {
@Override
public GameObject execute(Worm o) {
throw new UnsupportedOperationException();
}
public GameObject execute(Worm o, Set<GameObject> gobjects) {
return gobjects.stream().filter(g -> g.getAngle(o) == o.getOrientation()).min(
Comparator.comparingDouble(gameObject -> gameObject.getDistance(o))).orElse(null);
}
};
return new ArgumentBinaryExpression<Double, GameObject>(
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<Expression, Statement, Pr
@Override
public Expression createSameTeamExpression(Expression entity, SourceLocation sourceLocation) throws ModelException, MustNotImplementException {
return new ArgumentBinaryExpression<Worm, Worm, Boolean>(entity, (w, y) -> w.getTeam().equals(y.getTeam()), ArgumentExpression.Type.WORM);
return new ArgumentBinaryExpression<Worm, Boolean>(entity, (w, p) -> w.getTeam().equals(p.getWorm().getTeam()));
}
/**
@@ -379,7 +372,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createDistanceExpression(Expression entity, SourceLocation sourceLocation) throws ModelException {
return new ArgumentBinaryExpression<GameObject, Worm, Double>(entity, (e, o) -> e.getDistance(o), ArgumentExpression.Type.WORM);
return new ArgumentBinaryExpression<GameObject, Double>(entity, (e, p) -> e.getDistance(p.getWorm());
}
/**
@@ -392,6 +385,6 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createIsWormExpression(Expression entity, SourceLocation sourceLocation) throws ModelException {
return new UnaryExpression<Object, Boolean>(entity, w -> w instanceof Worm);
return new UnaryExpression<>(entity, w -> w instanceof Worm);
}
}

View File

@@ -76,9 +76,15 @@ public class Statement {
public static class Action {
private final Type type;
private final Expression value;
private final Expression<Double> value;
public Action(Type type, Expression value) {
/**
*
* @param type
* @param value
*/
@SuppressWarnings("unchecked")
public Action(Type type, Expression<Double> value) {
this.type = type;
this.value = value;
}
@@ -87,7 +93,7 @@ public class Statement {
return type;
}
public Expression getValue() {
public Expression<Double> 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;
}
}
}

View File

@@ -0,0 +1,25 @@
package worms.programs;
import worms.model.Program;
import java.util.function.Function;
public class UnaryArgumentExpression<R> implements Expression<R> {
private final Function<Program, R> function;
public UnaryArgumentExpression(Function<Program, R> unaryOperator) {
this.function = unaryOperator;
}
@Override
@SuppressWarnings("unchecked")
public R execute(Program program) {
try {
return function.apply(program);
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
}

View File

@@ -1,23 +1,25 @@
package worms.programs;
import worms.model.Program;
import java.util.function.Function;
public class UnaryExpression<T, R> implements Expression<R> {
protected final Expression expression;
protected final Expression<T> expression;
private final Function<T, R> function;
public UnaryExpression(Expression expression, Function<T, R> unaryOperator) {
public UnaryExpression(Expression<T> expression, Function<T, R> unaryOperator) {
this.expression = expression;
this.function = unaryOperator;
}
@Override
@SuppressWarnings("unchecked")
public R execute() {
public R execute(Program program) {
try {
return function.apply(((Expression<T>) expression).execute());
return function.apply( expression.execute(program));
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}