80% :D
This commit is contained in:
@@ -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 {
|
||||
worm.jump();
|
||||
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 {
|
||||
world.castSpell();
|
||||
try {
|
||||
world.castSpell();
|
||||
} catch (IllegalStateException e) {
|
||||
throw new ModelException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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,18 +41,34 @@ 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 (it.hasNext()) {
|
||||
executeStatement(it.next());
|
||||
if (!enoughAP) {
|
||||
iteratorStack.push(it);
|
||||
break;
|
||||
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()) {
|
||||
Statement current = it.next();
|
||||
executeStatement(current);
|
||||
if (!enoughAP) {
|
||||
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:
|
||||
breakLoop = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
return function.apply(left.execute(program), right.execute(program));
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package worms.programs;
|
||||
|
||||
import worms.model.Program;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Expression<R> {
|
||||
|
||||
R execute(Program program);
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user