This commit is contained in:
2018-05-20 04:23:22 +02:00
parent 4a1a48e1fe
commit 5236d4f0d6
13 changed files with 225 additions and 173 deletions

View File

@@ -76,7 +76,7 @@ public class Facade implements IFacade {
try {
worm.move();
} catch(IllegalArgumentException e) {
} catch(IllegalArgumentException | IllegalStateException e) {
throw new ModelException(e);
}
}
@@ -192,7 +192,11 @@ public class Facade implements IFacade {
*/
@Override
public void jump(Worm worm, double timeStep) throws ModelException {
try {
worm.jump();
} catch (IllegalStateException e) {
throw new ModelException(e);
}
}
/**
@@ -898,7 +902,7 @@ public class Facade implements IFacade {
try {
worm.setName(newName);
}
catch(IllegalNameException e) {
catch(IllegalNameException | IllegalArgumentException e) {
throw new ModelException(e);
}
}
@@ -992,7 +996,7 @@ public class Facade implements IFacade {
public void addWormsToTeam(Team team, Worm... worms) throws ModelException, MustNotImplementException {
try {
team.addWorm(worms);
} catch(IllegalArgumentException e) {
} catch(IllegalArgumentException | IllegalStateException e) {
throw new ModelException(e);
}
}
@@ -1090,6 +1094,10 @@ public class Facade implements IFacade {
*/
@Override
public void castSpell(World world) throws ModelException {
try {
world.castSpell();
} catch (IllegalStateException e) {
throw new ModelException(e);
}
}
}

View File

@@ -42,10 +42,12 @@ public abstract class GameObject {
* |setRadius(radius)
*/
protected GameObject(World world, double[] location, double radius) {
if (!isValidLocation(Coordinate.create(location))) throw new IllegalArgumentException("Illegal location");
setLocation(location);
setRadius(radius);
setWorld(world);
if (isValidWorld(world)) world.add(this);
setWorld(world);
}
/**
@@ -62,8 +64,8 @@ public abstract class GameObject {
* |setRadius(radius)
*/
protected GameObject(World world, Coordinate location, double radius) {
setWorld(world);
world.add(this);
setWorld(world);
setLocation(location);
setRadius(radius);
}
@@ -139,7 +141,14 @@ public abstract class GameObject {
*/
protected void setLocation(Coordinate location) throws IllegalArgumentException {
if (!isValidLocation(location)) throw new IllegalArgumentException();
if (!isValidLocation(location)) {
if (!(location.getX() - radius < 0) ||
!(location.getX() + radius > getWorld().getWidth()) ||
!(location.getY() + radius > getWorld().getHeight()) ||
!(location.getY() - radius < 0)) {
world.remove(this);
} else throw new IllegalArgumentException();
}
this.location = location;
}
@@ -223,8 +232,7 @@ public abstract class GameObject {
!(location.getX() - radius < 0) &&
!(location.getX() + radius > getWorld().getWidth()) &&
!(location.getY() + radius > getWorld().getHeight()) &&
!(location.getY() - radius < 0 &&
!getWorld().isPassable(location));
!(location.getY() - radius < 0) && getWorld().isPassable(location);
}
/**
@@ -252,16 +260,18 @@ public abstract class GameObject {
Coordinate otherLocation = o.getLocation();
return Math.sqrt(Math.pow((otherLocation.getX() - location.getX()), 2) + Math.pow((otherLocation.getY() - location.getY()), 2));
return Math.sqrt(Math.pow((otherLocation.getX() - location.getX()), 2) + Math.pow((otherLocation.getY() - location.getY()), 2)) - o.getRadius() - getRadius();
}
public double getAngle(GameObject o) {
if (o.equals(this)) return Double.NaN;
double x1 = getLocation().getX();
double y1 = getLocation().getY();
double x2 = o.getLocation().getX();
double y2 = o.getLocation().getY();
return Math.atan(Math.abs(x1 - x2) / Math.abs(y1 - y2));
return Math.abs(Math.atan(Math.abs(x1 - x2) / Math.abs(y1 - y2)) - Math.PI / 2.0);
}
}

View File

@@ -1,7 +1,6 @@
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;
@@ -14,9 +13,15 @@ import static java.lang.Math.toDegrees;
public class Program {
private final Map<String, Statement> procMap;
private final Map<String, Expression> varMap = new HashMap<>();
private final Map<String, Object> varMap = new HashMap<>();
private final List<Object> printList = new ArrayList<>();
private Stack<Statement.Type> currentType = new Stack<>();
private int inLoop = 0;
private int inProcedure = 0;
private boolean breakProcedure = false;
private boolean enoughAP = true;
private IActionHandler actionHandler;
@@ -36,19 +41,35 @@ public class Program {
// reset everything
enoughAP = true;
if (iteratorStack.empty()) {
if (callStack.empty()) {
executeStatement(main);
} else {
executeStatement(lastStatement);
while (!iteratorStack.empty()) {
Iterator<Statement> it = iteratorStack.pop();
while (!callStack.empty()) {
CallStackNode node = callStack.pop();
while(node.statementIterator == null && !callStack.empty()) {
executeStatement(node.lastStatement);
if (!enoughAP) break;
node = callStack.pop();
}
callStack.push(node);
if (node.statementIterator == null) {
executeStatement(node.lastStatement);
} else {
Iterator<Statement> it = node.statementIterator;
if (!enoughAP) break;
while (it.hasNext()) {
executeStatement(it.next());
Statement current = it.next();
executeStatement(current);
if (!enoughAP) {
iteratorStack.push(it);
node.lastStatement = current;
break;
}
}
if (!it.hasNext() && enoughAP) callStack.pop();
}
if (!enoughAP) break;
}
}
@@ -59,13 +80,13 @@ public class Program {
execute(worm);
if (!enoughAP) return null;
iteratorStack.clear();
callStack.clear();
return printList;
}
private boolean breakLoop = false;
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "SuspiciousMethodCalls"})
private void executeStatement(Statement s) {
if (!enoughAP) return;
@@ -79,38 +100,39 @@ public class Program {
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());
varMap.put(data.getVariableName(), data.getValue().execute(this));
break;
case PRINT:
printList.add(processExpression((Expression) s.getData()));
printList.add(((Expression) s.getData()).execute(this));
break;
case ACTION:
Statement.Action action = (Statement.Action) s.getData();
switch (action.getType()) {
case TURN:
Double val = (Double) processExpression(action.getValue());
Double val = action.getValue().execute(this);
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;
callStack.push(new CallStackNode(null, s));
return;
}
else if (!worm.canTurn(val)) throw new IllegalArgumentException("Invalid turn value");
actionHandler.turn(worm, (double) processExpression(action.getValue()));
actionHandler.turn(worm, action.getValue().execute(this));
break;
case MOVE:
try {
actionHandler.move(worm);
} catch (IllegalArgumentException e) {
enoughAP = false;
lastStatement = s;
callStack.push(new CallStackNode(null, s));
return;
}
break;
case JUMP:
if (worm.getActionPoints() < 0) {
if (worm.getActionPoints() <= 0) {
enoughAP = false;
lastStatement = s;
callStack.push(new CallStackNode(null, s));
return;
}
actionHandler.jump(worm);
@@ -118,7 +140,7 @@ public class Program {
case EAT:
if (!worm.canEat()) {
enoughAP = false;
lastStatement = s;
callStack.push(new CallStackNode(null, s));
return;
}
actionHandler.eat(worm);
@@ -126,7 +148,7 @@ public class Program {
case FIRE:
if (!worm.canFire()) {
enoughAP = false;
lastStatement = s;
callStack.push(new CallStackNode(null, s));
return;
}
actionHandler.fire(worm);
@@ -134,20 +156,29 @@ public class Program {
}
break;
case WHILE:
Boolean condition = (Boolean) processExpression(((Statement.While) s.getData()).getCondition());
inLoop++;
currentType.push(Statement.Type.WHILE);
CallStackNode whileNode = new CallStackNode(null, s);
callStack.push(whileNode);
Boolean condition = (Boolean) ((Statement.While) s.getData()).getCondition().execute(this);
if (condition == null) throw new IllegalArgumentException("Condition has to be a boolean");
while(condition) {
executeStatement(((Statement.While) s.getData()).getBody());
if (breakLoop) {
if (breakLoop || !enoughAP) {
breakLoop = false;
break;
}
condition = (Boolean) processExpression(((Statement.While) s.getData()).getCondition());
condition = (Boolean) ((Statement.While) s.getData()).getCondition().execute(this);
if (condition == null) throw new IllegalArgumentException("Condition has to be a boolean");
}
if (enoughAP) {
callStack.remove(whileNode);
}
inLoop--;
currentType.pop();
break;
case IF:
if ((Boolean) processExpression(((Statement.If) s.getData()).getCondition())) {
if ((Boolean) ((Statement.If) s.getData()).getCondition().execute(this)) {
executeStatement(((Statement.If) s.getData()).getIfBody());
} else {
Statement elseBody = ((Statement.If) s.getData()).getElseBody();
@@ -157,48 +188,47 @@ public class Program {
}
break;
case INVOKE:
executeStatement(procMap.get((String) s.getData()));
currentType.push(Statement.Type.ASSIGN);
inProcedure++;
Statement proc = procMap.get(s.getData());
if (proc == null) throw new IllegalArgumentException("Procedure not defined");
executeStatement(proc);
inProcedure--;
currentType.pop();
break;
case BREAK:
if (inLoop == 0 && inProcedure == 0) {
throw new IllegalArgumentException("BREAK out of scope.");
}
if (currentType.peek() == Statement.Type.WHILE) {
breakLoop = true;
} else {
breakProcedure = true;
}
break;
}
}
private Stack<Iterator<Statement>> iteratorStack = new Stack<>();
private Statement lastStatement = null;
private Stack<CallStackNode> callStack = new Stack<>();
private void executeStatementBlock(List<Statement> list) {
Iterator<Statement> it = list.iterator();
iteratorStack.push(it);
CallStackNode node = new CallStackNode(it, null);
callStack.push(node);
while(it.hasNext()) {
executeStatement(it.next());
if (!enoughAP) {
Statement current = it.next();
node.lastStatement = current;
executeStatement(current);
if (!enoughAP || breakLoop || breakProcedure) {
breakProcedure = false;
break;
}
}
}
if (!it.hasNext() && enoughAP) callStack.pop();
@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(this);
}
throw new UnsupportedOperationException();
}
public void setActionHandler(IActionHandler actionHandler) {
@@ -213,7 +243,18 @@ public class Program {
this.worm = worm;
}
public Map<String, Expression> getVariables() {
public Map<String, Object> getVariables() {
return this.varMap;
}
private class CallStackNode {
public Iterator<Statement> statementIterator;
public Statement lastStatement;
public CallStackNode(Iterator<Statement> st, Statement ls) {
statementIterator = st;
lastStatement = ls;
}
}
}

View File

@@ -1,6 +1,7 @@
package worms.model;
import java.util.*;
import java.util.function.BiFunction;
import worms.util.IllegalNameException;
import worms.util.TeamComparator;
@@ -82,7 +83,7 @@ public class Team {
Collection<Worm> worms = getAllWormsOfTeam();
for (Worm w : worm) {
if (w == null) return false;
if (w == null || w.getTeam() != null) return false;
if (!names.add(w.getName())) return false;
if (worms.contains(w)) return false;
if (worms.size() == 0 && !w.isTerminated()) continue;
@@ -109,9 +110,9 @@ public class Team {
*/
public void removeWormsFromTeam(Worm... worm) throws IllegalArgumentException {
if (worm == null) throw new IllegalArgumentException();
if (worm == null || Arrays.stream(worm).anyMatch(w -> Objects.isNull(w) || !getAllWormsOfTeam().contains(w))) throw new IllegalArgumentException();
for (Worm w: worm) {
if (w == null) throw new IllegalArgumentException();
getAllWormsOfTeam().remove(w);
w.setTeam(null);
}
@@ -169,7 +170,8 @@ public class Team {
*/
public static void mergeTeams(Team receivingTeam, Team supplyingTeam) throws IllegalArgumentException {
if (receivingTeam == null || supplyingTeam == null || receivingTeam.equals(supplyingTeam) ) {
if (receivingTeam == null || supplyingTeam == null || receivingTeam.equals(supplyingTeam) ||
supplyingTeam.getAllWormsOfTeam().stream().anyMatch(s -> receivingTeam.getAllWormsOfTeam().contains(s))) {
throw new IllegalArgumentException();
}

View File

@@ -30,7 +30,7 @@ public class World {
*/
public World(double width, double height, boolean[][] map) {
if (!isValidDimension(width) || !isValidDimension(height) || map == null || map.length != height || map[0].length != height) throw new IllegalArgumentException();
if (!isValidDimension(width) || !isValidDimension(height) || map == null || map.length == 0) throw new IllegalArgumentException();
this.width = width;
this.height = height;
@@ -69,7 +69,7 @@ public class World {
public void activateNextWorm() throws IllegalStateException {
if (getWormList().size() == 0) {
throw new IllegalStateException("No worms");
return;
}
this.activeWorm++;
@@ -97,6 +97,9 @@ public class World {
Team lastTeam = getWormList().get(0).getTeam();
for(Worm worm: getWormList()) {
if (worm.getTeam() == null) {
return null;
}
if (!lastTeam.equals(worm.getTeam())) {
return null;
}
@@ -228,7 +231,7 @@ public class World {
if (Math.floor(location[0] / lengthX) >= getMap()[0].length || location[0] < 0.0 ||
location[1] / lengthY >= getMap().length || location[1] < 0.0) {
return false;
return true;
}
return this.map[map.length - 1 - (int) Math.floor(location[1] / lengthY)][(int) Math.floor(location[0] / lengthX)];
@@ -444,9 +447,16 @@ public class World {
*/
public void add(GameObject obj) throws IllegalStateException, IllegalArgumentException {
if (hasActiveGame()) throw new IllegalStateException();
if (obj == null || !getGameObjects().add(obj) || obj.isTerminated()) throw new IllegalArgumentException();
if (obj == null || !getGameObjects().add(obj) || obj.isTerminated() || obj.getWorld() != null) throw new IllegalArgumentException();
obj.setWorld(this);
if (obj.getClass().equals(Food.class) && !((Food) obj).isValidLocation(obj.getLocation(), this)) {
obj.setWorld(null);
throw new IllegalArgumentException();
}
else if(Worm.class.isInstance(obj) && (!obj.isValidLocation(obj.getLocation()) || !isAdjacent(obj.getLocation(), obj.getRadius()) )) {
obj.setWorld(null);
throw new IllegalArgumentException();
}
obj.setWorld(this);
@@ -503,28 +513,9 @@ public class World {
return getGameObjectsByClass(Food.class);
}
/**
*
* @param cl
*
* @return ...
* |list.add(gameObject) for each gameObject
* |result == list (ArrayList<>())
*/
public List<GameObject> getGameObjectList(Class cl) {
List<GameObject> list = new ArrayList<>();
for (GameObject x : getGameObjects()) {
if (x.getClass().equals(cl)) {
list.add(x);
}
}
return list;
}
@SuppressWarnings("unchecked")
public <T extends GameObject> List<T> getGameObjectsByClass(Class<T> cl) {
return (List<T>) getGameObjects().stream().filter(x -> x.getClass().equals(cl)).collect(Collectors.toList());
return getGameObjects().stream().filter(cl::isInstance).map(cl::cast).collect(Collectors.toList());
}
/**
@@ -544,6 +535,7 @@ public class World {
Set<GameObject> gameObjects = getGameObjects();
int size = gameObjects.size();
if (size < 2) throw new IllegalStateException("Less than 2 objects");
int nb1 = new Random().nextInt(size);
int nb2 = new Random().nextInt(size);
while (nb2 == nb1) {

View File

@@ -109,7 +109,6 @@ public class Worm extends GameObject {
public Worm(World world, double[] location, double orientation, String name, double radius, double minRadius, Team team)
throws IllegalArgumentException {
super(world, location, radius);
setTeam(team);
setOrientation(orientation);
@@ -117,7 +116,7 @@ public class Worm extends GameObject {
throw new IllegalArgumentException("Invalid min radius");
this.minRadius = minRadius;
if (this.radius < this.minRadius) throw new IllegalArgumentException("Invalid radius");
if (!canHaveAsRadius(radius)) throw new IllegalArgumentException("Invalid radius");
setActionPoints(getMaxActionPoints());
@@ -132,6 +131,7 @@ public class Worm extends GameObject {
if (team != null) {
team.addWorm(this);
}
setTeam(team);
}
//===================================================================================
@@ -168,7 +168,7 @@ public class Worm extends GameObject {
*/
@Raw
private void setOrientation(double orientation) {
assert isValidOrientation(orientation);
if (!isValidOrientation(orientation)) throw new IllegalArgumentException();
this.orientation = orientation;
}
@@ -248,7 +248,7 @@ public class Worm extends GameObject {
*/
@Raw
private boolean canHaveAsRadius(double radius) {
return !Double.isNaN(radius) && radius >= getMinRadius();
return !Double.isNaN(radius) && radius >= getMinRadius() && !Double.isInfinite(radius);
}
/**
@@ -410,6 +410,8 @@ public class Worm extends GameObject {
*/
public static int isValidName(String name) {
if (name == null) throw new IllegalArgumentException("Name must not be null");
if (name.length() < 2 || !Character.isUpperCase(name.charAt(0))) {
return 0;
}
@@ -473,15 +475,16 @@ public class Worm extends GameObject {
*/
public void move() throws IllegalArgumentException {
if (getWorld() == null) throw new IllegalStateException();
double newDirection = getFurthestLocationDirection();
Coordinate newLocation = getFurthestLocationInDirection(newDirection, this.getRadius());
double distance = getDistance(this.getLocation(), newLocation);
long cost = (long) ceil(abs(distance * cos(newDirection)) + abs(4 * distance * sin(newDirection)));
long cost = (long) round(abs(distance * cos(newDirection)) + abs(4 * distance * sin(newDirection)));
if (cost > getActionPoints())
throw new IllegalArgumentException();
setLocation(newLocation);
subtractActionPoints(cost);
}
@@ -501,6 +504,10 @@ public class Worm extends GameObject {
double radius = getRadius();
World world = getWorld();
if (direction < 0 || direction > 2 * Math.PI || Double.isNaN(direction) || maxDistance < 0 ||
Double.isNaN(maxDistance) || Double.isInfinite(maxDistance))
throw new IllegalArgumentException("Invalid direction/distance");
if (getWorld() == null) {
return Coordinate.create(currentLocation.getX() + maxDistance * cos(direction), currentLocation.getY() + maxDistance * sin(direction));
}
@@ -550,6 +557,7 @@ public class Worm extends GameObject {
double maxLocDirection = minDirection;
Coordinate maxLoc = location;
for (; minDirection <= maxDirection; minDirection += 0.0175) {
if (minDirection < 0) minDirection = 0.0;
Coordinate tempLoc = getFurthestLocationInDirection(minDirection, this.getRadius());
if (!getWorld().isAdjacent(tempLoc, getRadius())) tempLoc = location;
if (getDistance(location, tempLoc) / Math.abs(direction - minDirection) > getDistance(location, maxLoc) / Math.abs(direction - maxLocDirection)) {
@@ -708,8 +716,6 @@ public class Worm extends GameObject {
}
setLocation(newLocation);
setActionPoints(0);
checkEat();
}
/**
@@ -740,7 +746,7 @@ public class Worm extends GameObject {
* |if (Double.isNaN(deltaTime) || deltaTime > this.jumpTime() || deltaTime < 0)
*/
public Coordinate jumpStep(double deltaTime) {
if (Double.isNaN(deltaTime) || deltaTime > this.jumpTime() || deltaTime < 0)
if (Double.isNaN(deltaTime) || deltaTime > this.jumpTime() || deltaTime < 0 || getActionPoints() == 0)
throw new IllegalArgumentException();
double velocity = this.jumpVelocity();
@@ -766,12 +772,14 @@ public class Worm extends GameObject {
* |result == t
*/
private double calcJumpTime() {
double v = jumpVelocity();
World world = getWorld();
if (world == null) throw new IllegalStateException("World cannot be null");
double v = jumpVelocity();
double t = 0;
double a = getOrientation();
Coordinate loc = getLocation();
World world = getWorld();
double radius = getRadius();
Coordinate newLoc;
@@ -1113,19 +1121,18 @@ public class Worm extends GameObject {
if (terminate) food.terminate();
System.out.println(getWorld().isAdjacent(getLocation(), getRadius()));
double radius = getRadius();
double changeRadius = radius * 0.1;
if (food.isPoisonous()) {
changeRadius *= -1;
radius *= 0.9;
if (radius < getMinRadius()) radius = getMinRadius();
} else {
radius *= 1.1;
}
decreaseActionPoints(8);
setRadius(radius);
World world = getWorld();
@@ -1183,7 +1190,7 @@ public class Worm extends GameObject {
*/
public void checkEat() {
if (!canEat()) throw new IllegalStateException();
if (!canEat()) return;
World world = getWorld();
if (world != null) {
@@ -1191,6 +1198,7 @@ public class Worm extends GameObject {
for (Food food : foodList) {
if (getDistance(food.getLocation(), this.getLocation()) < this.getRadius() + food.getRadius()) {
eat(food);
break;
}
}
}
@@ -1272,4 +1280,13 @@ public class Worm extends GameObject {
// ===================================================================================
// endregion
@Override
public void terminate() {
super.terminate();
if (team != null) {
team.removeWormsFromTeam(this);
setTeam(null);
}
}
}

View File

@@ -1,22 +0,0 @@
package worms.programs;
public abstract class ArgumentExpression<R, O> implements Expression<R> {
public final Type type;
protected ArgumentExpression(Type type) {
this.type = type;
}
public abstract R execute(O o);
public Type getType() {
return this.type;
}
public enum Type {
WORM,
VAR,
GOBJECTS
}
}

View File

@@ -19,10 +19,6 @@ public class BinaryExpression<T, R> implements Expression<R> {
@Override
@SuppressWarnings("unchecked")
public R execute(Program program) {
try {
return function.apply(left.execute(program), right.execute(program));
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
}

View File

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

View File

@@ -8,6 +8,7 @@ import worms.util.MustNotImplementException;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
public class ProgramFactory implements IProgramFactory<Expression, Statement, Procedure, Program> {
/**
@@ -58,7 +59,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createAssignmentStatement(String variableName, Expression value, SourceLocation sourceLocation) throws ModelException {
return new Statement(Statement.Type.ASSIGN, new Statement.Assign(variableName, value));
return new Statement<>(Statement.Type.ASSIGN, new Statement.Assign<Object>(variableName, value));
}
/**
@@ -70,7 +71,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createPrintStatement(Expression value, SourceLocation sourceLocation) throws ModelException {
return new Statement(Statement.Type.PRINT, value);
return new Statement<Expression<Object>>(Statement.Type.PRINT, value);
}
/**
@@ -82,7 +83,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createTurnStatement(Expression angle, SourceLocation location) throws ModelException {
return new Statement(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.TURN, angle));
return new Statement<>(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.TURN, angle));
}
/**
@@ -93,7 +94,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createMoveStatement(SourceLocation location) throws ModelException {
return new Statement(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.MOVE, null));
return new Statement<>(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.MOVE, null));
}
/**
@@ -103,7 +104,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createJumpStatement(SourceLocation location) throws ModelException {
return new Statement(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.JUMP, null));
return new Statement<>(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.JUMP, null));
}
/**
@@ -113,7 +114,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createEatStatement(SourceLocation location) {
return new Statement(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.EAT, null));
return new Statement<>(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.EAT, null));
}
/**
@@ -124,7 +125,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createFireStatement(SourceLocation location) throws ModelException {
return new Statement(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.FIRE, null));
return new Statement<>(Statement.Type.ACTION, new Statement.Action(Statement.Action.Type.FIRE, null));
}
/**
@@ -135,7 +136,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createSequenceStatement(List<Statement> statements, SourceLocation sourceLocation) throws ModelException {
return new Statement(Statement.Type.BLOCK, statements);
return new Statement<>(Statement.Type.BLOCK, statements);
}
/**
@@ -150,7 +151,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createIfStatement(Expression condition, Statement ifBody, Statement elseBody, SourceLocation sourceLocation) throws ModelException {
return new Statement(Statement.Type.IF, new Statement.If(condition, ifBody, elseBody));
return new Statement<>(Statement.Type.IF, new Statement.If<Boolean>(condition, ifBody, elseBody));
}
/**
@@ -162,7 +163,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createWhileStatement(Expression condition, Statement body, SourceLocation sourceLocation) throws ModelException {
return new Statement(Statement.Type.WHILE, new Statement.While(condition, body));
return new Statement<>(Statement.Type.WHILE, new Statement.While<Boolean>(condition, body));
}
/**
@@ -172,7 +173,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createBreakStatement(SourceLocation sourceLocation) throws ModelException, MustNotImplementException {
return new Statement(Statement.Type.BREAK, null);
return new Statement<>(Statement.Type.BREAK, null);
}
/**
@@ -183,7 +184,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Statement createInvokeStatement(String procedureName, SourceLocation sourceLocation) throws ModelException, MustNotImplementException {
return new Statement(Statement.Type.INVOKE, procedureName);
return new Statement<String>(Statement.Type.INVOKE, procedureName);
}
/**
@@ -195,7 +196,10 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
*/
@Override
public Expression createReadVariableExpression(String variableName, SourceLocation sourceLocation) throws ModelException {
return (Expression<Object>) program -> program.getVariables().get(variableName).execute(program);
return (Expression<Object>) program -> {
if (!program.getVariables().containsKey(variableName)) throw new IllegalArgumentException("Variable not declared");
return program.getVariables().get(variableName);
};
}
/**
@@ -239,7 +243,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createSelfExpression(SourceLocation location) throws ModelException {
return new UnaryArgumentExpression<Worm>(w -> w.getWorm());
return new UnaryArgumentExpression<Worm>(Program::getWorm);
}
/**
@@ -295,7 +299,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createEqualityExpression(Expression left, Expression right, SourceLocation location) throws ModelException {
return new BinaryExpression<Object, Boolean>(left, right, (l, r) -> l.equals(r));
return new BinaryExpression<Object, Boolean>(left, right, Objects::equals);
}
/**
@@ -321,7 +325,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
.getWorld()
.getGameObjects()
.stream()
.filter(g -> g.getAngle(p.getWorm()) == p.getWorm().getOrientation())
.filter(g -> g.getAngle(p.getWorm()) == p.getWorm().getOrientation() + a)
.min(Comparator.comparingDouble(gameObject -> gameObject.getDistance(p.getWorm())))
.orElse(null));
}
@@ -337,7 +341,7 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createSameTeamExpression(Expression entity, SourceLocation sourceLocation) throws ModelException, MustNotImplementException {
return new BinaryArgumentExpression<Worm, Boolean>(entity, (w, p) -> w.getTeam().equals(p.getWorm().getTeam()));
return new BinaryArgumentExpression<Worm, Boolean>(entity, (w, p) -> {if (w == null) return false; return Objects.equals(w.getTeam(), p.getWorm().getTeam());});
}
/**
@@ -350,7 +354,10 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createDistanceExpression(Expression entity, SourceLocation sourceLocation) throws ModelException {
return new BinaryArgumentExpression<GameObject, Double>(entity, (e, p) -> e.getDistance(p.getWorm()));
return new BinaryArgumentExpression<GameObject, Double>(entity, (e, p) -> {
if (e == null) throw new IllegalArgumentException();
return e.getDistance(p.getWorm());
});
}
/**
@@ -363,6 +370,6 @@ public class ProgramFactory implements IProgramFactory<Expression, Statement, Pr
@Override
public Expression createIsWormExpression(Expression entity, SourceLocation sourceLocation) throws ModelException {
return new UnaryExpression<GameObject, Boolean>(entity, w -> w instanceof Worm);
return new UnaryExpression<Object, Boolean>(entity, e -> e instanceof Worm);
}
}

View File

@@ -1,11 +1,11 @@
package worms.programs;
public class Statement {
public class Statement<T> {
private final Type type;
private final Object data;
private final T data;
public Statement(Type type, Object data) {
public Statement(Type type, T data) {
this.type = type;
this.data = data;
}
@@ -14,7 +14,7 @@ public class Statement {
return this.type;
}
public Object getData() {
public T getData() {
return data;
}
@@ -29,13 +29,13 @@ public class Statement {
BREAK
}
public static class If {
public static class If<T> {
private final Statement ifBody;
private final Statement elseBody;
private final Expression condition;
private final Expression<T> condition;
public If(Expression condition, Statement ifBody, Statement elseBody) {
public If(Expression<T> condition, Statement ifBody, Statement elseBody) {
this.ifBody = ifBody;
this.elseBody = elseBody;
this.condition = condition;
@@ -49,17 +49,17 @@ public class Statement {
return elseBody;
}
public Expression getCondition() {
public Expression<T> getCondition() {
return condition;
}
}
public static class While {
public static class While<T> {
private final Expression condition;
private final Expression<T> condition;
private final Statement body;
public While(Expression condition, Statement body) {
public While(Expression<T> condition, Statement body) {
this.condition = condition;
this.body = body;
}
@@ -68,7 +68,7 @@ public class Statement {
return body;
}
public Expression getCondition() {
public Expression<T> getCondition() {
return condition;
}
}
@@ -106,17 +106,17 @@ public class Statement {
}
}
public static class Assign {
public static class Assign<T> {
private final String variableName;
private final Expression value;
private final Expression<T> value;
public Assign(String variableName, Expression value) {
public Assign(String variableName, Expression<T> value) {
this.variableName = variableName;
this.value = value;
}
public Expression getValue() {
public Expression<T> getValue() {
return value;
}

View File

@@ -7,6 +7,7 @@ import java.util.Comparator;
public class TeamComparator implements Comparator<Worm> {
@Override
public int compare(Worm t1, Worm t2) {
if (t1.equals(t2)) return 0;
return t1.getName().compareTo(t2.getName());
}
}

View File

@@ -976,7 +976,7 @@ public class Part3_FullFacadeTest {
@Test
public void createWorm_IllegalWorld() {
max_score += 2;
World someWorld = facade.createWorld(10.0, 20.0, map10x10);
World someWorld = facade.createWorld(10.0, 10.0, map10x10);
facade.terminate(someWorld);
try {
facade.createWorm(someWorld, new double[] { 8.68, 8.68 }, 0.3, 0.3, "Worm", null);