diff --git a/OGP1718-Worms/.project b/OGP1718-Worms/.project index 7c6ada6..33267ef 100644 --- a/OGP1718-Worms/.project +++ b/OGP1718-Worms/.project @@ -25,5 +25,10 @@ 2 PROJECT_LOC/levels + + resources/programs + 2 + PROJECT_LOC/programs + diff --git a/OGP1718-Worms/images/burger-poisonous.png b/OGP1718-Worms/images/burger-poisonous.png new file mode 100644 index 0000000..692e676 Binary files /dev/null and b/OGP1718-Worms/images/burger-poisonous.png differ diff --git a/OGP1718-Worms/lib/antlr-runtime-4.7.1.jar b/OGP1718-Worms/lib/antlr-runtime-4.7.1.jar new file mode 100644 index 0000000..e2e0ac7 Binary files /dev/null and b/OGP1718-Worms/lib/antlr-runtime-4.7.1.jar differ diff --git a/OGP1718-Worms/programs/program.txt b/OGP1718-Worms/programs/program.txt new file mode 100755 index 0000000..2e51829 --- /dev/null +++ b/OGP1718-Worms/programs/program.txt @@ -0,0 +1,35 @@ +// Worm that turns towards nearest worm, fires, and moves; or turns and tries to jump if no worm is in sight. + +def updateNearestWorm: { + delta := 0; + nearestWorm := null; + turnToNearest := 0; + while delta < 6.28: { + obj := searchobj delta; + if (obj != null && isworm obj): + if !sameteam obj: + if (nearestWorm == null) || (distance obj < distance nearestWorm): { + nearestWorm := obj; + turnToNearest := delta; + } + delta := delta + 0.2; + } +} + +// main program + +while true: { + invoke updateNearestWorm; + + if nearestWorm != null: { + print nearestWorm; + print distance nearestWorm; + turn turnToNearest; + fire; + move; + } + else { + turn 0.2; + jump; + } +} diff --git a/OGP1718-Worms/programs/program_example.txt b/OGP1718-Worms/programs/program_example.txt new file mode 100755 index 0000000..6164e5c --- /dev/null +++ b/OGP1718-Worms/programs/program_example.txt @@ -0,0 +1,20 @@ +def controlled_move: + if getap self > 100.0: + { jump; + print getx self; + print gety self; } + else move; + +max_distance := 10.0; +while true: { + w := searchobj 0.0; + if isworm w: { + if sameteam w: + invoke controlled_move; + else if distance w < max_distance: + fire; + else + { turn d; + max_distance := max_distance + 0.1; } + } +} \ No newline at end of file diff --git a/OGP1718-Worms/programs/program_simple.txt b/OGP1718-Worms/programs/program_simple.txt new file mode 100755 index 0000000..8fb7d8d --- /dev/null +++ b/OGP1718-Worms/programs/program_simple.txt @@ -0,0 +1,3 @@ +turn 0.2; +fire; +move; \ No newline at end of file diff --git a/OGP1718-Worms/programs/syntax_test.txt b/OGP1718-Worms/programs/syntax_test.txt new file mode 100755 index 0000000..f7af558 --- /dev/null +++ b/OGP1718-Worms/programs/syntax_test.txt @@ -0,0 +1,54 @@ +// don't execute this :-) +def test_proc: { + x := +1; + while true: + print false; + if x == 1: { + print x * x; + } else: {} + invoke test_proc; + break; + if 0-x/y*z - y * z - 2*x + 3 == 2 && true != false: {} + move; + jump; + eat; + fire; +} + +def secondProc: { + invoke test_proc; + if getx self > 0: + invoke secondProc; +} + +x := ( 3 * 4 ); // comment +// comment +y := (-33.5 * (+55 / 1.22)); + +jump; +turn 5; +turn 0.2; +turn -0.2; +fire; + +if (x >= 5): + { } +else + fire; + +while y: + { turn (0.01); + y := (y - 1); } + +while y: + { move; + y := (y - 1); + if (true): { turn y; } + else { + while (false): + {print y;} + } + } + +if (true): { } else { invoke test_proc; } + diff --git a/OGP1718-Worms/src-provided/worms/Worms.java b/OGP1718-Worms/src-provided/worms/Worms.java old mode 100644 new mode 100755 index c72466b..0776318 --- a/OGP1718-Worms/src-provided/worms/Worms.java +++ b/OGP1718-Worms/src-provided/worms/Worms.java @@ -22,6 +22,9 @@ public class Worms { options.randomSeed = randomSeed; } else if ("-clickselect".equals(arg)) { options.enableClickToSelect = true; + } else if ("-program".equals(arg)) { + String program = args[++i]; + options.programFile = program; } } diff --git a/OGP1718-Worms/src-provided/worms/facade/IFacade.java b/OGP1718-Worms/src-provided/worms/facade/IFacade.java old mode 100644 new mode 100755 index 9ae00f6..0f34712 --- a/OGP1718-Worms/src-provided/worms/facade/IFacade.java +++ b/OGP1718-Worms/src-provided/worms/facade/IFacade.java @@ -2,21 +2,24 @@ package worms.facade; import java.math.BigInteger; import java.util.*; + +import worms.internal.gui.game.IActionHandler; import worms.model.*; +import worms.programs.IProgramFactory; import worms.util.ModelException; import worms.util.MustNotImplementException; /** * Implement this interface to connect your code to the graphical user interface * (GUI). - * + * * */ public interface IFacade { - - /************ - * WORLD - ************/ - - /** - * Create a new world with given width and given height. - * The passable map is a rectangular matrix indicating which parts of the terrain - * are passable and which parts are impassable. - * This matrix is derived from the transparency of the pixels in the image file - * of the terrain. passableMap[r][c] is true if the location at row r and column c - * is passable, and false if that location is impassable. - * The elements in the first row (row 0) represent the pixels at the top of the - * terrain (i.e., largest y-coordinates). - * The elements in the last row (row passableMap.length-1) represent pixels at the - * bottom of the terrain (smallest y-coordinates). - * The elements in the first column (column 0) represent the pixels at the left - * of the terrain (i.e., smallest x-coordinates). - * The elements in the last column (column passableMap[0].length-1) represent the - * pixels at the right of the terrain (i.e., largest x-coordinates). - */ - public World createWorld(double width, double height, - boolean[][] passableMap) throws ModelException; - - /** - * Terminate the given world. - */ - void terminate(World world) throws ModelException; - - /** - * Check whether the given worls is terminated. - */ - boolean isTerminated(World world) throws ModelException; - - /** - * Return the width of the given world. - */ - public double getWorldWidth(World world) throws ModelException; - - /** - * Return the height of the given world. - */ - public double getWorldHeight(World world) throws ModelException; - - /** - * Check whether the given world is passable at the given location. - * - The location is an array containing the x-coordinate of the location to - * check followed by the y-coordinate of that location. - * - Locations outside the boundaries of the world are always passable. - */ - boolean isPassable(World world, double[] location) throws ModelException; - - /** - * Check whether the circular area with given center and given radius - * is passable in the given world. - * - The circular area must not lie completely within the given world. - */ - boolean isPassable(World world, double[] center, double radius); - - /** - * Check whether the circular area with given center and given radius - * is adjacent to impassable terrain in the given world. - * - The circular area must not lie completely within the given world. - */ - boolean isAdjacent(World world, double[] center, double radius); - - /** - * Check whether the given world contains the given worm. - */ - boolean hasAsWorm(World world, Worm worm) throws ModelException; - - /** - * Add the given worm to the given world. - */ - void addWorm(World world, Worm worm) throws ModelException; - - /** - * Remove the given worm from the given world. - */ - void removeWorm(World world, Worm worm) throws ModelException; - - /** - * Return a list filled with all the worms in the given world. - */ - List getAllWorms(World world) throws ModelException; - - /** - * Check whether the given world contains the given food. - */ - boolean hasAsFood(World world, Food food) throws ModelException; - - /** - * Add the given portion of food to the given world. - */ - void addFood(World world, Food food) throws ModelException; - - /** - * Remove the given portion of food from the given world. - */ - void removeFood(World world, Food food) throws ModelException; - - /** - * Return a collection filled with all the worms and all the - * portions of food in the given world. - */ - Collection getAllItems(World world) throws ModelException; - - /** - * Return a set of all the team in the given world. - */ - Set getAllTeams(World world) throws ModelException; - - /** - * Check whether the given world has an active game. - */ - boolean hasActiveGame(World world) throws ModelException; - - /** - * Return the active worm in the given world. - * - The active worm is the worm whose turn it is to perform - * player-controlled actions. - */ - Worm getActiveWorm(World world) throws ModelException; - - /** - * Start a new game in the given world. - */ - void startGame(World world) throws ModelException; - - /** - * Finish the current game, if any, in the given world. - */ - void finishGame(World world) throws ModelException; - - /** - * Activate the next worm in the given world. - */ - void activateNextWorm(World world) throws ModelException; - - /** - * Return the name of a single worm if that worm is the winner, or the name - * of a team if that team is the winner and the team still has several members. - */ - String getWinner(World world); - - - /************ - * WORM - ************/ - - /** - * Create and return a new worm that is positioned at the given location in - * the given world, that looks in the given direction, that has the given radius - * and the given name, and that is a member of the given team. - * - If the given world is not effective, the new worm is simply positioned - * at the given location. - * - If the given team is not effective, the new worm is not part of any team. - * The location is an array containing the x-coordinate of the location of - * the new worm followed by the y-coordinate of that location. - */ - Worm createWorm(World world, double[] location, double direction, double radius, - String name, Team team) throws ModelException; - - /** - * Terminate the given worm. - */ - void terminate(Worm worm) throws ModelException; - - /** - * Check whether the given worm is terminated. - */ - boolean isTerminated(Worm worm) throws ModelException; - - /** - * Return the current location of the given worm. - * - The resulting array contains the the x-coordinate of the given worm - * followed by its y-coordinate. - */ - double[] getLocation(Worm worm) throws ModelException; - - /** - * Return the current orientation of the given worm (in radians). - */ - double getOrientation(Worm worm) throws ModelException; - - /** - * Return the radius of the given worm. - */ - double getRadius(Worm worm) throws ModelException; - - /** - * Set the radius of the given worm to the given value. - */ - void setRadius(Worm worm, double newRadius) throws ModelException; - - /** - * Return the mass of the given worm. - */ - double getMass(Worm worm) throws ModelException; - - /** - * Return the maximum number of action points of the given worm. - */ - long getMaxNbActionPoints(Worm worm) throws ModelException; - - /** - * Return the current number of action points of the given worm. - */ - long getNbActionPoints(Worm worm) throws ModelException; - - /** - * Decrease the current number of action points of the given worm - * with the given delta. - * - The given delta may be negative. - */ - void decreaseNbActionPoints(Worm worm, long delta) throws ModelException; - - /** - * Return the current number of hit points of the given worm. - */ - BigInteger getNbHitPoints(Worm worm) throws ModelException; - - /** - * Increment the current number of hit points of the given worm - * with the given delta. - * - The given delta may be negative. - */ - void incrementNbHitPoints(Worm worm, long delta) throws ModelException; - - /** - * Return the name the given worm. - */ - String getName(Worm worm) throws ModelException; - - /** - * Rename the given worm. - */ - void rename(Worm worm, String newName) throws ModelException; - - /** - * Return the world to which this worm belongs - */ - World getWorld(Worm worm) throws ModelException; - - - /** - * Turn the given worm by the given angle. - */ - void turn(Worm worm, double angle); - - /** - * Return the location the farthest away from its current location to which the given - * worm can move in the world in which that worm is positioned, if any, following - * the given direction and not exceeding the given maximum distance. - * - The maximum distance must be finite and may not be negative. - * - The given direction must be in the range [0.0 .. PI[. - * - On its road to the resulting location, the given worm will always be - * positioned on passable terrain. - * - The resulting position may be outside the boundaries of the world, if any, in - * which the given worm is located. - */ - double[] getFurthestLocationInDirection(Worm worm, double direction, double maxDistance) throws ModelException; - - /** - * Move the given worm according to the rules in the assignment. - */ - void move(Worm worm) throws ModelException; - - /** - * Returns whether the given worm can fall. - * - Students working alone on the project must not override this method. - */ - default public boolean canFall(Worm worm) throws MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Makes the given worm fall down until it rests on impassable terrain again, - * or until it leaves the world in which it is in. - * - Students working alone on the project must not override this method. - */ - default void fall(Worm worm) throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - /** - * Return the time needed by the given worm to jump to the nearest position - * adjacent to impassable terrain. - * - deltaT determines the resolution to be used in successive steps of the jump. - */ - double getJumpTime(Worm worm, double deltaT) throws ModelException; - - /** - * Returns the location on the jump trajectory of the given worm - * after a time t. - * - The resulting location is an array with two elements, - * with the first element being the x-coordinate and the - * second element the y-coordinate. - */ - double[] getJumpStep(Worm worm, double t) throws ModelException; - - /** - * Make the given worm jump using the given time step. - * - The given time step determines a time interval during which - * you may assume that the worm will not move through a piece - * of impassable terrain. - */ - void jump(Worm worm, double timeStep) throws ModelException; - - - - /************ - * FOOD - ************/ - - /** - * Create and return a new portion of food that is positioned at the given - * location in the given world. - * = If the given world is not effective, the new food is simply positioned - * at the given location. - */ - Food createFood(World world, double[] location) throws ModelException; - - /** - * Terminate the given portion of food. - */ - void terminate(Food food) throws ModelException; - - /** - * Check whether the given portion of food is terminated. - */ - boolean isTerminated(Food food) throws ModelException; - - /** - * Return the current location of the given portion of food. - * - The resulting array contains the the x-coordinate of the given worm - * followed by its y-coordinate. - */ - double[] getLocation(Food food) throws ModelException; - - /** - * Return the radius of the given portion of food. - */ - double getRadius(Food food) throws ModelException; - - /** - * Return the mass of the given portion of food. - */ - double getMass(Food food) throws ModelException; - - /** - * Return the world to which this portion of food belongs. - */ - World getWorld(Food food) throws ModelException; - - - /** - * Make the given worm eat a portion of food. - */ - public void eat(Worm worm); - - /******** - * TEAM - ********/ - - /** - * Create a new team for the given world with given name and with no members yet. - * - Students working alone on the project must not override this method. - */ - default Team createTeam(World world, String name) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Terminate the given team. - */ - default void terminate(Team team) throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Check whether the given portion of food is terminated. - */ - default boolean isTerminated(Team team) throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Return the name of the given team. - * - Students working alone on the project must not override this method. - */ - default String getName(Team team) throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - - /** - * Return the team to which this worm belongs. - * - Students working alone on the project must not override this method. - */ - default Team getTeam(Worm worm) throws ModelException { - throw new MustNotImplementException(); - } - - /** - * Return the number of worms in the given team. - * - Students working alone on the project must not override this method. - */ - default int getNbWormsOfTeam(Team team) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Return a list of all the worms in the given team, sorted alphabetically. - * This method must run in linear time. - * - Students working alone on the project must not override this method. - */ - default List getAllWormsOfTeam(Team team) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - }; - - /** - * Add the given worms to the given team. - * - Students working alone on the project must not override this method. - */ - default void addWormsToTeam(Team team, Worm... worms) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Remove the given worms from the given team. - * - Students working alone on the project must not override this method. - */ - default void removeWormsFromTeam(Team team, Worm... worms) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - - /** - * Merge the given teams. - * - All the worms of the supplying team are transferred to the receiving team. - * - Students working alone on the project must not override this method. - */ - default void mergeTeams(Team recevingTeam, Team supplyingTeam) - throws ModelException, MustNotImplementException { - throw new MustNotImplementException(); - } - -} \ No newline at end of file + + /************ + * WORLD + ************/ + + /** + * Create a new world with given width and given height. + * The passable map is a rectangular matrix indicating which parts of the terrain + * are passable and which parts are impassable. + * This matrix is derived from the transparency of the pixels in the image file + * of the terrain. passableMap[r][c] is true if the location at row r and column c + * is passable, and false if that location is impassable. + * The elements in the first row (row 0) represent the pixels at the top of the + * terrain (i.e., largest y-coordinates). + * The elements in the last row (row passableMap.length-1) represent pixels at the + * bottom of the terrain (smallest y-coordinates). + * The elements in the first column (column 0) represent the pixels at the left + * of the terrain (i.e., smallest x-coordinates). + * The elements in the last column (column passableMap[0].length-1) represent the + * pixels at the right of the terrain (i.e., largest x-coordinates). + */ + public World createWorld(double width, double height, + boolean[][] passableMap) throws ModelException; + + /** + * Terminate the given world. + */ + void terminate(World world) throws ModelException; + + /** + * Check whether the given worls is terminated. + */ + boolean isTerminated(World world) throws ModelException; + + /** + * Return the width of the given world. + */ + public double getWorldWidth(World world) throws ModelException; + + /** + * Return the height of the given world. + */ + public double getWorldHeight(World world) throws ModelException; + + /** + * Check whether the given world is passable at the given location. + * - The location is an array containing the x-coordinate of the location to + * check followed by the y-coordinate of that location. + * - Locations outside the boundaries of the world are always passable. + */ + boolean isPassable(World world, double[] location) throws ModelException; + + /** + * Check whether the circular area with given center and given radius + * is passable in the given world. + * - The circular area must not lie completely within the given world. + */ + boolean isPassable(World world, double[] center, double radius); + + /** + * Check whether the circular area with given center and given radius + * is adjacent to impassable terrain in the given world. + * - The circular area must not lie completely within the given world. + */ + boolean isAdjacent(World world, double[] center, double radius); + + /** + * Check whether the given world contains the given worm. + */ + boolean hasAsWorm(World world, Worm worm) throws ModelException; + + /** + * Add the given worm to the given world. + */ + void addWorm(World world, Worm worm) throws ModelException; + + /** + * Remove the given worm from the given world. + */ + void removeWorm(World world, Worm worm) throws ModelException; + + /** + * Return a list filled with all the worms in the given world. + */ + List getAllWorms(World world) throws ModelException; + + /** + * Check whether the given world contains the given food. + */ + boolean hasAsFood(World world, Food food) throws ModelException; + + /** + * Add the given portion of food to the given world. + */ + void addFood(World world, Food food) throws ModelException; + + /** + * Remove the given portion of food from the given world. + */ + void removeFood(World world, Food food) throws ModelException; + + /** + * Return a collection filled with all the worms and all the + * portions of food in the given world. + */ + Collection getAllItems(World world) throws ModelException; + + /** + * Return a set of all the team in the given world. + */ + Set getAllTeams(World world) throws ModelException; + + /** + * Check whether the given world has an active game. + */ + boolean hasActiveGame(World world) throws ModelException; + + /** + * Return the active worm in the given world. + * - The active worm is the worm whose turn it is to perform + * player-controlled actions. + */ + Worm getActiveWorm(World world) throws ModelException; + + /** + * Start a new game in the given world. + */ + void startGame(World world) throws ModelException; + + /** + * Finish the current game, if any, in the given world. + */ + void finishGame(World world) throws ModelException; + + /** + * Activate the next worm in the given world. + */ + void activateNextWorm(World world) throws ModelException; + + /** + * Return the name of a single worm if that worm is the winner, or the name + * of a team if that team is the winner and the team still has several members. + */ + String getWinner(World world); + + + /************ + * WORM + ************/ + + /** + * Create and return a new worm that is positioned at the given location in + * the given world, that looks in the given direction, that has the given radius + * and the given name, and that is a member of the given team. + * - If the given world is not effective, the new worm is simply positioned + * at the given location. + * - If the given team is not effective, the new worm is not part of any team. + * The location is an array containing the x-coordinate of the location of + * the new worm followed by the y-coordinate of that location. + */ + Worm createWorm(World world, double[] location, double direction, double radius, + String name, Team team) throws ModelException; + + /** + * Terminate the given worm. + */ + void terminate(Worm worm) throws ModelException; + + /** + * Check whether the given worm is terminated. + */ + boolean isTerminated(Worm worm) throws ModelException; + + /** + * Return the current location of the given worm. + * - The resulting array contains the the x-coordinate of the given worm + * followed by its y-coordinate. + */ + double[] getLocation(Worm worm) throws ModelException; + + /** + * Return the current orientation of the given worm (in radians). + */ + double getOrientation(Worm worm) throws ModelException; + + /** + * Return the radius of the given worm. + */ + double getRadius(Worm worm) throws ModelException; + + /** + * Set the radius of the given worm to the given value. + */ + void setRadius(Worm worm, double newRadius) throws ModelException; + + /** + * Return the mass of the given worm. + */ + double getMass(Worm worm) throws ModelException; + + /** + * Return the maximum number of action points of the given worm. + */ + long getMaxNbActionPoints(Worm worm) throws ModelException; + + /** + * Return the current number of action points of the given worm. + */ + long getNbActionPoints(Worm worm) throws ModelException; + + /** + * Decrease the current number of action points of the given worm + * with the given delta. + * - The given delta may be negative. + */ + void decreaseNbActionPoints(Worm worm, long delta) throws ModelException; + + /** + * Return the current number of hit points of the given worm. + */ + BigInteger getNbHitPoints(Worm worm) throws ModelException; + + /** + * Increment the current number of hit points of the given worm + * with the given delta. + * - The given delta may be negative. + */ + void incrementNbHitPoints(Worm worm, long delta) throws ModelException; + + /** + * Return the name the given worm. + */ + String getName(Worm worm) throws ModelException; + + /** + * Rename the given worm. + */ + void rename(Worm worm, String newName) throws ModelException; + + /** + * Return the world to which this worm belongs + */ + World getWorld(Worm worm) throws ModelException; + + + /** + * Turn the given worm by the given angle. + */ + void turn(Worm worm, double angle); + + /** + * Return the location the farthest away from its current location to which the given + * worm can move in the world in which that worm is positioned, if any, following + * the given direction and not exceeding the given maximum distance. + * - The maximum distance must be finite and may not be negative. + * - The given direction must be in the range [0.0 .. PI[. + * - On its road to the resulting location, the given worm will always be + * positioned on passable terrain. + * - The resulting position may be outside the boundaries of the world, if any, in + * which the given worm is located. + */ + double[] getFurthestLocationInDirection(Worm worm, double direction, double maxDistance) throws ModelException; + + /** + * Move the given worm according to the rules in the assignment. + */ + void move(Worm worm) throws ModelException; + + /** + * Returns whether the given worm can fall. + * - Students working alone on the project must not override this method. + */ + default public boolean canFall(Worm worm) throws MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Makes the given worm fall down until it rests on impassable terrain again, + * or until it leaves the world in which it is in. + * - Students working alone on the project must not override this method. + */ + default void fall(Worm worm) throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Return the time needed by the given worm to jump to the nearest position + * adjacent to impassable terrain. + * - deltaT determines the resolution to be used in successive steps of the jump. + */ + double getJumpTime(Worm worm, double deltaT) throws ModelException; + + /** + * Returns the location on the jump trajectory of the given worm + * after a time t. + * - The resulting location is an array with two elements, + * with the first element being the x-coordinate and the + * second element the y-coordinate. + */ + double[] getJumpStep(Worm worm, double t) throws ModelException; + + /** + * Make the given worm jump using the given time step. + * - The given time step determines a time interval during which + * you may assume that the worm will not move through a piece + * of impassable terrain. + */ + void jump(Worm worm, double timeStep) throws ModelException; + + /** + * Make the given worm eat a portion of food. + */ + void eat(Worm worm) throws ModelException; + + /** + * Have the give worm fire a projectile. + * - The method must return the projectile that has been fired. + */ + Projectile fire(Worm worm) throws ModelException; + + + /************ + * FOOD + ************/ + + /** + * Create and return a new portion of food that is positioned at the given + * location in the given world. + * = If the given world is not effective, the new food is simply positioned + * at the given location. + */ + Food createFood(World world, double[] location) throws ModelException; + + /** + * Terminate the given portion of food. + */ + void terminate(Food food) throws ModelException; + + /** + * Check whether the given portion of food is terminated. + */ + boolean isTerminated(Food food) throws ModelException; + + /** + * Return the current location of the given portion of food. + * - The resulting array contains the the x-coordinate of the given worm + * followed by its y-coordinate. + */ + double[] getLocation(Food food) throws ModelException; + + /** + * Return the radius of the given portion of food. + */ + double getRadius(Food food) throws ModelException; + + /** + * Return the mass of the given portion of food. + */ + double getMass(Food food) throws ModelException; + + /** + * Return the world to which this portion of food belongs. + */ + World getWorld(Food food) throws ModelException; + + /** + * Return whether or not the given portion of food is poisonous. + */ + boolean isPoisonous(Food food) throws ModelException; + + /** + * Poison the given portion of food. + */ + void poison(Food food) throws ModelException; + + + + /************* + * PROJECTILE + *************/ + + /** + * Check whether the given projectile is terminated. + */ + boolean isTerminated(Projectile projectile) throws ModelException; + + /** + * Return the current orientation of the given projectile (in radians). + */ + double getOrientation(Projectile projectile) throws ModelException; + + /** + * Return the current location of the given projectile. + * - The resulting array contains the the x-coordinate of the given projectile + * followed by its y-coordinate. + */ + double[] getLocation(Projectile projectile) throws ModelException; + + /** + * Return the radius of the given projectile. + */ + double getRadius(Projectile projectile); + + /** + * Return the number of hit points of the given projectile. + */ + int getNbHitPoints(Projectile projectile) throws ModelException; + + /** + * Returns the location on the jump trajectory of the given projectile + * after a time t. + * - The resulting location is an array with two elements, + * with the first element being the x-coordinate and the + * second element the y-coordinate. + */ + double[] getJumpStep(Projectile projectile, double elapsedTime); + + /** + * Return the time needed by the given projectile to jump to the nearest + * location at which the projectile hits impassable terrain or a worm. + * - deltaT determines the resolution to be used in successive steps of the jump. + */ + double getJumpTime(Projectile projectile, double jumpTimeStep) throws ModelException; + + /** + * Make the given projectile jump using the given time step. + * - The given time step determines a time interval during which + * you may assume that the projectile will not hit impassable + * terrain nor a worm. + */ + void jump(Projectile projectile, double jumpTimeStep) throws ModelException; + + + + + + /******** + * TEAM + ********/ + + /** + * Create a new team for the given world with given name and with no members yet. + * - Students working alone on the project must not override this method. + */ + default Team createTeam(World world, String name) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Terminate the given team. + */ + default void terminate(Team team) throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Check whether the given portion of food is terminated. + */ + default boolean isTerminated(Team team) throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Return the name of the given team. + * - Students working alone on the project must not override this method. + */ + default String getName(Team team) throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + + /** + * Return the team to which this worm belongs. + * - Students working alone on the project must not override this method. + */ + default Team getTeam(Worm worm) throws ModelException { + throw new MustNotImplementException(); + } + + /** + * Return the number of worms in the given team. + * - Students working alone on the project must not override this method. + */ + default int getNbWormsOfTeam(Team team) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Return a list of all the worms in the given team, sorted alphabetically. + * This method must run in linear time. + * - Students working alone on the project must not override this method. + */ + default List getAllWormsOfTeam(Team team) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + }; + + /** + * Add the given worms to the given team. + * - Students working alone on the project must not override this method. + */ + default void addWormsToTeam(Team team, Worm... worms) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Remove the given worms from the given team. + * - Students working alone on the project must not override this method. + */ + default void removeWormsFromTeam(Team team, Worm... worms) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Merge the given teams. + * - All the worms of the supplying team are transferred to the receiving team. + * - Students working alone on the project must not override this method. + */ + default void mergeTeams(Team recevingTeam, Team supplyingTeam) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + + + + + /********** + * PROGRAMS + **********/ + + /** + * Return the program loaded on the given worm. + */ + Program getWormProgram(Worm worm) throws ModelException; + + /** + * Load the given program on the given worm. + * + * While executing the program, the worm must invoke the methods corresponding + * to actions through the provided ActionHandler object (e.g., actionHandler.jump(this), + * actionHandler.turn(this, 0.2), etc.) rather than invoking them directly (e.g., this.jump()). + * This executes the action as if a human player has initiated it, so the GUI can update itself. + * The GUI will also invoke the corresponding method on the worm through the facade. + */ + public void loadProgramOnWorm(Worm worm, Program program, IActionHandler actionHandler) throws ModelException; + + /** + * Execute the program loaded on the given worm. + * The worm is positioned in some world. Returns null if the program + * is not completely executed. Otherwise, returns the objects that have been + * printed. + * + * This method is only used in the tests. The GUI never calls this method; + * you should execute the program when the worm is activated. + */ + public List executeProgram(Worm worm) throws ModelException; + + /** + * Creates a new program factory. + */ + public IProgramFactory createProgramFactory() throws ModelException; + + + + + + /********* + * WIZARD + *********/ + + /** + * Have the wizard cast a spell over two randomly slected game objects in the given + * world. + */ + void castSpell(World world) throws ModelException; + + +} diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/AbstractPainter.java b/OGP1718-Worms/src-provided/worms/internal/gui/AbstractPainter.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/ErrorScreen.java b/OGP1718-Worms/src-provided/worms/internal/gui/ErrorScreen.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/GUIConstants.java b/OGP1718-Worms/src-provided/worms/internal/gui/GUIConstants.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/GUIOptions.java b/OGP1718-Worms/src-provided/worms/internal/gui/GUIOptions.java old mode 100644 new mode 100755 index bad55db..aec42b4 --- a/OGP1718-Worms/src-provided/worms/internal/gui/GUIOptions.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/GUIOptions.java @@ -26,4 +26,11 @@ public class GUIOptions { */ public boolean enableClickToSelect = false; + /** + * The program that is executed by computer-controlled worms. + * Default: "programs/program.txt" + * + * Can also be set from the command line with the -program argument + */ + public String programFile = "programs/program.txt"; } \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/GUIUtils.java b/OGP1718-Worms/src-provided/worms/internal/gui/GUIUtils.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/GameState.java b/OGP1718-Worms/src-provided/worms/internal/gui/GameState.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/InputMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/InputMode.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/Level.java b/OGP1718-Worms/src-provided/worms/internal/gui/Level.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/Screen.java b/OGP1718-Worms/src-provided/worms/internal/gui/Screen.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/WormsGUI.java b/OGP1718-Worms/src-provided/worms/internal/gui/WormsGUI.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/DefaultActionHandler.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/DefaultActionHandler.java old mode 100644 new mode 100755 index 9f25190..51219c8 --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/DefaultActionHandler.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/DefaultActionHandler.java @@ -5,11 +5,13 @@ import java.util.concurrent.Executors; import worms.facade.IFacade; import worms.internal.gui.GameState; +import worms.internal.gui.game.commands.ActivateWizard; import worms.internal.gui.game.commands.AddNewFood; import worms.internal.gui.game.commands.AddNewTeam; import worms.internal.gui.game.commands.AddNewWorm; import worms.internal.gui.game.commands.Command; import worms.internal.gui.game.commands.Eat; +import worms.internal.gui.game.commands.Fire; import worms.internal.gui.game.commands.Jump; import worms.internal.gui.game.commands.Move; import worms.internal.gui.game.commands.Rename; @@ -88,8 +90,14 @@ class DefaultActionHandler implements IActionHandler { executeCommand(new Rename(getFacade(), worm, newName, getScreen())); } - public void eat(Worm worm) { - executeCommand(new Eat(getFacade(), worm, getScreen())); + @Override + public boolean eat(Worm worm) { + return executeCommand(new Eat(getFacade(), worm, getScreen())); + } + + @Override + public boolean fire(Worm worm) { + return executeCommand(new Fire(getFacade(), worm, getScreen())); } public void selectNextWorm() { @@ -100,8 +108,8 @@ class DefaultActionHandler implements IActionHandler { executeCommand(new StartGame(getFacade(), getScreen())); } - public void addNewWorm() { - executeCommand(new AddNewWorm(getFacade(), getScreen())); + public void addNewWorm(boolean withProgram) { + executeCommand(new AddNewWorm(getFacade(), withProgram, getScreen())); } public void addEmptyTeam(String name) { @@ -111,5 +119,9 @@ class DefaultActionHandler implements IActionHandler { public void addNewFood() { executeCommand(new AddNewFood(getFacade(), getScreen())); } + + public void activateWizard() { + executeCommand(new ActivateWizard(getFacade(), getScreen())); + } } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/IActionHandler.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/IActionHandler.java old mode 100644 new mode 100755 index e0bb5c5..933ea9f --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/IActionHandler.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/IActionHandler.java @@ -14,6 +14,7 @@ import worms.model.Worm; *
  • shows periodic updates on the GUI (such as jump animations) *
  • eventually calls the corresponding facade methods, exactly like what * happens with a human player + *
  • makes sure a worm will fall after moving *
  • returns true if the action has been completed successfully; false * otherwise * @@ -29,6 +30,10 @@ public interface IActionHandler { public boolean move(Worm worm); public boolean jump(Worm worm); + + public boolean eat(Worm worm); + + public boolean fire(Worm worm); /** * Print a message on the screen for a short amount of time. diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/ImageSprite.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/ImageSprite.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreen.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreen.java old mode 100644 new mode 100755 index 4a6c295..23c4d91 --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreen.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreen.java @@ -224,6 +224,14 @@ public class PlayGameScreen extends Screen { } } + + public void fire() { + Worm worm = getSelectedWorm(); + if (worm != null) { + userActionHandler.fire(worm); + } + + } public void turn(double angle) { Worm worm = getSelectedWorm(); @@ -397,7 +405,11 @@ public class PlayGameScreen extends Screen { } public void addPlayerControlledWorm() { - userActionHandler.addNewWorm(); + userActionHandler.addNewWorm(false); + } + + public void addComputerControlledWorm() { + userActionHandler.addNewWorm(true); } public void addFood() { @@ -445,4 +457,8 @@ public class PlayGameScreen extends Screen { return programActionHandler; } + public void activateWizard() { + userActionHandler.activateWizard(); + } + } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenDebugPainter.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenDebugPainter.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenPainter.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenPainter.java old mode 100644 new mode 100755 index b8fc34e..a92ebe9 --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenPainter.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/PlayGameScreenPainter.java @@ -17,6 +17,7 @@ import worms.internal.gui.GUIUtils; import worms.internal.gui.GameState; import worms.internal.gui.Level; import worms.internal.gui.game.sprites.FoodSprite; +import worms.internal.gui.game.sprites.ProjectileSprite; import worms.internal.gui.game.sprites.WormSprite; import worms.model.World; import worms.util.ModelException; @@ -102,9 +103,18 @@ public class PlayGameScreenPainter extends AbstractPainter { paintWorm(sprite); } + for (ProjectileSprite sprite : getScreen().getSpritesOfType( + ProjectileSprite.class)) { + paintProjectile(sprite); + } + this.currentGraphics = null; } + protected void paintProjectile(ProjectileSprite sprite) { + sprite.draw(currentGraphics); + } + protected void paintFood(FoodSprite sprite) { sprite.draw(currentGraphics); } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/Sprite.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/Sprite.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/ActivateWizard.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/ActivateWizard.java new file mode 100755 index 0000000..5a0bbd9 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/ActivateWizard.java @@ -0,0 +1,29 @@ +package worms.internal.gui.game.commands; + +import worms.facade.IFacade; +import worms.internal.gui.game.PlayGameScreen; +import worms.internal.gui.messages.MessageType; +import worms.util.ModelException; + +public class ActivateWizard extends InstantaneousCommand { + + public ActivateWizard(IFacade facade, + PlayGameScreen screen) { + super(facade, screen); + } + + @Override + protected boolean canStart() { + return true; + } + + @Override + protected void doStartExecution() { + try { + getFacade().castSpell(getWorld()); + getScreen().addMessage("The wizard has done wizardry things!", MessageType.INFO); + } catch (ModelException e) { + getScreen().addMessage("The wizard could not cast its spell :(", MessageType.ERROR); + } + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewFood.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewFood.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewTeam.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewTeam.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewWorm.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewWorm.java old mode 100644 new mode 100755 index 021a848..cf1ba9b --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewWorm.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/AddNewWorm.java @@ -1,21 +1,34 @@ package worms.internal.gui.game.commands; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; import java.util.Random; import worms.facade.IFacade; import worms.internal.gui.GUIUtils; +import worms.internal.gui.WormsGUI; import worms.internal.gui.game.PlayGameScreen; import worms.internal.gui.messages.MessageType; +import worms.model.Program; import worms.model.Team; +import worms.model.Worm; +import worms.programs.IProgramFactory; +import worms.programs.ParseOutcome; +import worms.programs.ProgramParser; import worms.util.ModelException; public class AddNewWorm extends InstantaneousCommand { private static final double MIN_RADIUS = 0.25; - private static final double MAX_RADIUS = Math.pow(2, 1.0/3.0) * MIN_RADIUS; - - public AddNewWorm(IFacade facade, PlayGameScreen screen) { + private static final double MAX_RADIUS = Math.pow(2, 1.0 / 3.0) * MIN_RADIUS; + private boolean withProgram; + + public AddNewWorm(IFacade facade, boolean withProgram, PlayGameScreen screen) { super(facade, screen); + this.withProgram = withProgram; } @Override @@ -36,10 +49,82 @@ public class AddNewWorm extends InstantaneousCommand { double direction = random.nextDouble() * 2 * Math.PI; Team team = getScreen().getLastCreatedTeam(); - getFacade().createWorm(getWorld(), p, direction, radius, name, team); + Worm worm = getFacade().createWorm(getWorld(), p, direction, radius, name, team); + + if (withProgram) { + loadProgram(worm); + } + } catch (ModelException e) { e.printStackTrace(); getScreen().addMessage("Could not create worm", MessageType.ERROR); } } + + private void loadProgram(Worm worm) { + String programText = readProgramText(); + if (programText != null) { + IProgramFactory factory = getFacade().createProgramFactory(); + ProgramParser parser = ProgramParser.create(factory); + ParseOutcome outcome = parser.parseString(programText); + + if (outcome != null) { + if (outcome.isSuccess()) { + Program program = outcome.getSuccessValue(); + getFacade().loadProgramOnWorm(worm, program, getScreen().getProgramActionHandler()); + } else { + List errors = outcome.getFailValue(); + String msg = "Parsing failed\nwith the following errors:\n"; + for (String error : errors) { + msg += error + "\n"; + } + cancelExecution(); + getGUI().showError(msg); + return; + } + } + } else { + cancelExecution(); + getGUI().showError("Could not parse program"); + } + } + + private WormsGUI getGUI() { + return getScreen().getGUI(); + } + + protected String readProgramText() { + InputStream stream; + try { + stream = GUIUtils.openResource(getGUI().getOptions().programFile); + } catch (IOException e) { + e.printStackTrace(); + getGUI().showError(e.getMessage()); + return null; + } + + BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); + StringBuilder programText = new StringBuilder(); + String line; + try { + line = reader.readLine(); + while (line != null) { + programText.append(line); + programText.append("\n"); + line = reader.readLine(); + } + } catch (IOException e) { + e.printStackTrace(); + cancelExecution(e); + return null; + } finally { + try { + reader.close(); + } catch (IOException e) { + // I don't care + } + } + return programText.toString(); + } + } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Command.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Command.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Eat.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Eat.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Fire.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Fire.java new file mode 100755 index 0000000..95e7b29 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Fire.java @@ -0,0 +1,83 @@ +package worms.internal.gui.game.commands; + +import worms.facade.IFacade; +import worms.internal.gui.GUIConstants; +import worms.internal.gui.game.PlayGameScreen; +import worms.internal.gui.game.sprites.ProjectileSprite; +import worms.internal.gui.messages.MessageType; +import worms.model.Projectile; +import worms.model.Worm; +import worms.util.ModelException; + +public class Fire extends Command { + private final Worm worm; + + private Projectile projectile; + private double totalDuration; + private boolean hasJumped; + + public Fire(IFacade facade, Worm worm, PlayGameScreen screen) { + super(facade, screen); + this.worm = worm; + } + + @Override + protected boolean canStart() { + return worm != null; + } + + @Override + protected void doStartExecution() { + try { + projectile = getFacade().fire(worm); + if (projectile != null) { + totalDuration = getFacade().getJumpTime(projectile, GUIConstants.JUMP_TIME_STEP); + ProjectileSprite sprite = new ProjectileSprite(getScreen(), projectile); + sprite.update(); + getScreen().addSprite(sprite); + } else { + cancelExecution(); + } + } catch (ModelException e) { + e.printStackTrace(); + cancelExecution(); + } + } + + @Override + protected void afterExecutionCompleted() { + super.afterExecutionCompleted(); + ProjectileSprite sprite = getScreen().getSpriteOfTypeFor(ProjectileSprite.class, projectile); + if (sprite != null) { + sprite.setDoneMoving(); + } + } + + @Override + protected void afterExecutionCancelled(Throwable e) { + getScreen().addMessage("This worm cannot shoot :(" + (e != null ? "\n" + e.getMessage() : ""), + MessageType.ERROR); + } + + @Override + protected void doUpdate(double dt) { + try { + if (getElapsedTime() >= totalDuration) { + if (!hasJumped) { + hasJumped = true; + getFacade().jump(projectile, GUIConstants.JUMP_TIME_STEP); + completeExecution(); + } + } else { + ProjectileSprite sprite = getScreen().getSpriteOfTypeFor(ProjectileSprite.class, projectile); + + double[] xy = getFacade().getJumpStep(projectile, getElapsedTime()); + + sprite.setCenterLocation(getScreen().getScreenX(xy[0]), getScreen().getScreenY(xy[1])); + } + } catch (ModelException e) { + e.printStackTrace(); + cancelExecution(); + } + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/InstantaneousCommand.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/InstantaneousCommand.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Jump.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Jump.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Move.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Move.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Rename.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Rename.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/SelectNextWorm.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/SelectNextWorm.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/StartGame.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/StartGame.java old mode 100644 new mode 100755 index 7445771..fdf0375 --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/StartGame.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/StartGame.java @@ -24,6 +24,7 @@ public class StartGame extends InstantaneousCommand { protected void afterExecutionCancelled(Throwable e) { if (e != null) { getScreen().addMessage("Cannot start the game: " + e.getMessage(), MessageType.ERROR); + e.printStackTrace(); } else { getScreen().addMessage("Cannot start the game without worms", MessageType.ERROR); } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Turn.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/commands/Turn.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/DefaultInputMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/DefaultInputMode.java old mode 100644 new mode 100755 index 39e5d9c..c534583 --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/DefaultInputMode.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/DefaultInputMode.java @@ -55,6 +55,14 @@ public class DefaultInputMode extends InputMode { case 'E': getScreen().eat(); break; + case 'f': + case 'F': + getScreen().fire(); + break; + case 's': + case 'S': + getScreen().activateWizard(); + break; } } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/EnteringNameMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/EnteringNameMode.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/GameOverMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/GameOverMode.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/SetupInputMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/SetupInputMode.java old mode 100644 new mode 100755 index a3c8517..6d492ce --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/SetupInputMode.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/SetupInputMode.java @@ -24,6 +24,10 @@ public class SetupInputMode extends InputMode { case 'W': getScreen().addPlayerControlledWorm(); break; + case 'c': + case 'C': + getScreen().addComputerControlledWorm(); + break; case 'f': case 'F': getScreen().addFood(); @@ -49,7 +53,12 @@ public class SetupInputMode extends InputMode { getScreen() .showInstructions( g, - "Press\n'T' to create a new team\n'W' to add a new worm\n'F' to add food\n'S' to start the game"); + "Press\n" + + "'T' to create a new team\n" + + "'W' to add a new player-controlled worm\n" + + "'C' to add a new computer-controlled worm\n" + + "'F' to add food\n" + + "'S' to start the game"); } } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/TurningMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/modes/TurningMode.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/FoodSprite.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/FoodSprite.java old mode 100644 new mode 100755 index e990efa..e2f091e --- a/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/FoodSprite.java +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/FoodSprite.java @@ -1,5 +1,8 @@ package worms.internal.gui.game.sprites; +import java.awt.Image; +import java.awt.image.BufferedImage; + import worms.internal.gui.game.ImageSprite; import worms.internal.gui.game.PlayGameScreen; import worms.model.Food; @@ -12,10 +15,22 @@ public class FoodSprite extends ImageSprite { private final Food food; private double radius; + + private boolean poisonous = false; + + // original image, at original scale + private final BufferedImage originalPoisonousImage; + + // only created when scale != 1.0 + private BufferedImage scaledPoisonousImage; public FoodSprite(PlayGameScreen screen, Food food) { super(screen, "images/burger.png"); this.food = food; + // constraint: must have same dimensions as original image + // constraint: does not respect hflipping + this.originalPoisonousImage = loadImage("images/burger-poisonous.png"); + this.scaledPoisonousImage = this.originalPoisonousImage; update(); } @@ -45,9 +60,52 @@ public class FoodSprite extends ImageSprite { setScale(scaleFactor); } + + @Override + public void setScale(double newScale) { + double oldScale = getScale(); + + super.setScale(newScale); + + if (newScale == oldScale) { + return; + } + + if (newScale != 1.0) { + this.scaledPoisonousImage = toBufferedImage(originalPoisonousImage.getScaledInstance( + (int) (newScale * originalPoisonousImage.getWidth()), + (int) (newScale * originalPoisonousImage.getHeight()), + Image.SCALE_SMOOTH)); + } else { + this.scaledPoisonousImage = originalPoisonousImage; + } + } + + + @Override + protected Image getImageToDraw() { + if (isPoisonous()) { + return scaledPoisonousImage; + } else { + return super.getImageToDraw(); + } + } + + public synchronized double getRadius() { + return radius; + } + + public synchronized boolean isPoisonous() { + return poisonous; + } + + public void setPoisonous(boolean poisonous) { + this.poisonous = poisonous; + } @Override public synchronized void update() { + setPoisonous(getFacade().isPoisonous(getFood())); setRadius(getFacade().getRadius(getFood())); double[] xy = getFacade().getLocation(getFood()); setCenterLocation(getScreen().getScreenX(xy[0]), getScreen().getScreenY(xy[1])); @@ -67,8 +125,5 @@ public class FoodSprite extends ImageSprite { return !getFacade().isTerminated(food); } - public synchronized double getRadius() { - return radius; - } } diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/ProjectileSprite.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/ProjectileSprite.java new file mode 100755 index 0000000..c166da1 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/ProjectileSprite.java @@ -0,0 +1,143 @@ +package worms.internal.gui.game.sprites; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import worms.internal.gui.GUIUtils; +import worms.internal.gui.game.PlayGameScreen; +import worms.internal.gui.game.Sprite; +import worms.model.Projectile; + +public class ProjectileSprite extends Sprite { + + private static final int MIN_DISPLAY_SIZE = 3; // pixels + private static final int MAX_DISPLAY_SIZE = 10; // pixels + private static final int DISPLAY_SCALE = 10; + + private static final int NB_HISTORY = 15; + private static final Color[] colors = new Color[NB_HISTORY]; + static { + for (int i = 0; i < colors.length; i++) { + float t = (float) i / colors.length; + colors[i] = new Color(1.0F, (1 - t), 0, 0.8F); + } + } + + private final Projectile projectile; + + private double sizeInPixels; + + @SuppressWarnings("serial") + private static class LimitedQueue extends LinkedList { + private int limit; + + public LimitedQueue(int limit) { + this.limit = limit; + } + + @Override + public boolean add(E o) { + boolean result = super.add(o); + while (size() > limit) { + super.remove(); + } + return result; + } + } + + private final List lastLocations = Collections.synchronizedList(new LimitedQueue( + NB_HISTORY)); + private boolean moving; + + public ProjectileSprite(PlayGameScreen screen, Projectile projectile) { + super(screen); + this.projectile = projectile; + this.moving = true; + } + + @Override + public synchronized void draw(Graphics2D g) { + if (moving) { + for (int i = 0; i < lastLocations.size(); i++) { + double[] loc = lastLocations.get(i); + g.setColor(colors[i]); + double t = (double) (i + 1) / lastLocations.size(); + double size = sizeInPixels * t * t * t; + g.fill(GUIUtils.circleAt(loc[0], loc[1], size)); + } + } else { + g.setColor(colors[NB_HISTORY-1]); + g.fill(GUIUtils.circleAt(getCenterX(), getCenterY(), sizeInPixels)); + } + } + + @Override + public Projectile getObject() { + return getProjectile(); + } + + public Projectile getProjectile() { + return projectile; + } + + public synchronized void setSize(double sizeInPixels) { + this.sizeInPixels = Math.min(MAX_DISPLAY_SIZE, + Math.max(MIN_DISPLAY_SIZE, DISPLAY_SCALE * sizeInPixels)); + } + + @Override + public double getHeight(Graphics2D g) { + return sizeInPixels; + } + + @Override + public double getWidth(Graphics2D g) { + return sizeInPixels; + } + + @Override + public boolean isObjectAlive() { + return !getFacade().isTerminated(getProjectile()); + } + + @Override + public synchronized void update() { + setSize(getScreen().worldToScreenDistance(getFacade().getRadius(getProjectile()))); + double[] loc = getFacade().getLocation(getProjectile()); + setCenterLocation(getScreen().getScreenX(loc[0]), getScreen().getScreenY(loc[1])); + } + + @Override + public synchronized void setCenterLocation(double x, double y) { + super.setCenterLocation(x, y); + if (moving && !lastLocations.isEmpty()) { + // do some averaving to show some intermediate positions for + // fast-moving object (rifle projectiles) + + if (lastLocations.size() > 1) { + double[] c1 = lastLocations.get(lastLocations.size() - 1); + double[] c2 = lastLocations.get(0); + lastLocations.add(new double[] { (c1[0] + c2[0]) / 2, + (c1[1] + c2[1]) / 2 }); + } + double[] prev = lastLocations.get(lastLocations.size() - 1); + lastLocations.remove(prev); + + for (int i = 0; i < NB_HISTORY; i++) { + if (prev != null) { + double t = (double) i / (NB_HISTORY); + lastLocations.add(new double[] { t * x + (1 - t) * prev[0], + t * y + (1 - t) * prev[1] }); + } + } + } + lastLocations.add(new double[] { x, y }); + } + + public synchronized void setDoneMoving() { + this.moving = false; + } +} diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/WormSprite.java b/OGP1718-Worms/src-provided/worms/internal/gui/game/sprites/WormSprite.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/menu/AbstractMenuScreen.java b/OGP1718-Worms/src-provided/worms/internal/gui/menu/AbstractMenuScreen.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/menu/ChooseLevelScreen.java b/OGP1718-Worms/src-provided/worms/internal/gui/menu/ChooseLevelScreen.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/menu/MainMenuScreen.java b/OGP1718-Worms/src-provided/worms/internal/gui/menu/MainMenuScreen.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/menu/MenuInputMode.java b/OGP1718-Worms/src-provided/worms/internal/gui/menu/MenuInputMode.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/messages/Message.java b/OGP1718-Worms/src-provided/worms/internal/gui/messages/Message.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessageDisplay.java b/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessageDisplay.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessagePainter.java b/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessagePainter.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessageType.java b/OGP1718-Worms/src-provided/worms/internal/gui/messages/MessageType.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/programs/IProgramFactory.java b/OGP1718-Worms/src-provided/worms/programs/IProgramFactory.java new file mode 100755 index 0000000..c2b4acf --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/IProgramFactory.java @@ -0,0 +1,443 @@ +package worms.programs; + +import java.util.ArrayList; +import java.util.List; + +import worms.util.ModelException; +import worms.util.MustNotImplementException; + +/** + * A program factory is used by the parser ({@link ProgramParser}) to construct + * an in-memory representation of your program. For example, when reading the + * program source code + * + *
    + * print 2.0
    + * 
    + * + * the parser will create a Program object by (conceptually) executing the + * following code: + * + *
    + * factory.createProgram(Collections.emptyList(),
    + * 		factory.createPrintStatement(factory.createDoubleLiteral(2.0)));
    + * 
    + * + * on the returned factory object. + * + *

    + * For testing, you may use the methods from {@link ProgramParser} yourself. + *

    + * + *

    + * You should declare your class as follows:

    + * public class ProgramFactory implements IProgramFactory<MyExpression, MyStatement, MyProc, Program>
    + * 
    where MyExpression, MyStatement, MyProc, and Program are your classes + * for representing expressions, statements, procedure definitions, and programs, + * respectively. + * + *

    + * The SourceLocation object in the methods defined by this factory refers to + * the location (line and column) in the text file where the statement or + * expression begins. + * + * @param + * Your class for representing an expression. + * @param + * Your class for representing a statement. + * @param

    + * Your class for representing a procedure. + * @param + * Your class for representing a program (should be Program). + * + * + */ +public interface IProgramFactory { + + /* PROGRAM */ + + /** + * Create a program from the given arguments. + * + * @param procs + * The procedure definitions for the program. + * @param main + * The main statement of the program. Most likely this is a + * sequence statement. + * @return A new program. + */ + public Program createProgram(List

    procs, S main) throws ModelException; + + /** + * Create a program from the given argument. + * + * @param main + * The main statement of the program. Most likely this is a + * sequence statement. + * @return A new program without procedure definitions. + */ + public default Program createProgram(S main) throws ModelException { + return createProgram(new ArrayList

    (), main); + } + + /* PROCEDURE DEFINITIONS */ + + /** + * Create a procedure definition with the given name and body. + * + * @param procedureName + * The name of the procedure + * @param body + * The body of the procedure. + */ + public P createProcedureDefinition(String procedureName, S body, SourceLocation sourceLocation); + + /* STATEMENTS */ + + /** + * Create a statement that assigns the value obtained by evaluating the + * given expression to a variable with the given name. + */ + public S createAssignmentStatement(String variableName, E value, SourceLocation sourceLocation) + throws ModelException; + + /** + * Create a print statement that prints the value obtained by evaluating the + * given expression. + */ + public S createPrintStatement(E value, SourceLocation sourceLocation) throws ModelException; + + /** + * Create a turn statement that makes the worm that is executing the program + * turn by the amount obtained by evaluating the given expression. + */ + public S createTurnStatement(E angle, SourceLocation location) throws ModelException; + + /** + * Create a statement that makes the worm that is executing the program move + * one step. + */ + public S createMoveStatement(SourceLocation location) throws ModelException; + + /** + * Returns a statement that makes the worm that is executing the program jump. + */ + public S createJumpStatement(SourceLocation location) throws ModelException; + + /** + * Returns a statement that makes the worm that is executing the program eat. + */ + public S createEatStatement(SourceLocation location); + + /** + * Returns a statement that makes the worm that is executing the program fire + * a weapon. + */ + public S createFireStatement(SourceLocation location) throws ModelException; + + /** + * Create a sequence of statements involving the given list of statements. + */ + public S createSequenceStatement(List statements, SourceLocation sourceLocation) throws ModelException; + + /** + * Create an if-then-else statement involving the given condition and the + * given then-part and else-part. + * The else-part may be null. + */ + public S createIfStatement(E condition, S ifBody, S elseBody, SourceLocation sourceLocation) throws ModelException; + + /** + * Create a while statement involving the given condition and given body. + */ + public S createWhileStatement(E condition, S body, SourceLocation sourceLocation) throws ModelException; + + /** + * Create a break statement. + */ + public default S createBreakStatement(SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + // Individual students must not work out this method. + throw new MustNotImplementException(); + } + + /** + * Create an invoke statement that invokes the procedure with the given name. + */ + public default S createInvokeStatement(String procedureName, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + // Individual students must not work out this method. + throw new MustNotImplementException(); + } + + /* EXPRESSIONS */ + + /** + * Create an expression that evaluates to the current value of the given + * variable. + */ + public E createReadVariableExpression(String variableName, SourceLocation sourceLocation) throws ModelException; + + /** + * Creates an expression that represents a literal double value. + */ + public E createDoubleLiteralExpression(double value, SourceLocation location) throws ModelException; + + /** + * Creates an expression that represents a literal boolean value. + */ + public E createBooleanLiteralExpression(boolean value, SourceLocation location) throws ModelException; + + /** + * Creates an expression that represents the null value. + */ + public E createNullExpression(SourceLocation location) throws ModelException; + + /** + * Creates an expression that represents the self value, evaluating to the + * worm that executes the program. + */ + public E createSelfExpression(SourceLocation location) throws ModelException; + + /** + * Returns an expression that evaluates to the addition of the values + * obtained by evaluating the given left and second expressions. + */ + public E createAdditionExpression(E left, E right, SourceLocation location) throws ModelException; + + /** + * Returns an expression that evaluates to the subtraction of the values + * obtained by evaluating the first and second given expressions. + */ + public default E createSubtractionExpression(E left, E right, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the multiplication of the values + * obtained by evaluating the first and second given expressions. + */ + public default E createMultiplicationExpression(E left, E right, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the division of the values + * obtained by evaluating the first and second given expressions. + */ + public default E createDivisionExpression(E left, E right, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the square root of the value + * obtained by evaluating the given expression. + */ + public default E createSqrtExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the sine of the value + * obtained by evaluating the given expression. + */ + public default E createSinExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the cosine of the value + * obtained by evaluating the given expression. + */ + public default E createCosExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the conjunction of the values + * obtained by evaluating the given left and right expressions. + */ + public E createAndExpression(E left, E right, SourceLocation sourceLocation) throws ModelException; + + /** + * Returns an expression that evaluates to the disjunction of the values + * obtained by evaluating the given left and right expressions. + */ + public default E createOrExpression(E left, E right, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to true when the given expression + * evaluates to false, and vice versa. + */ + public E createNotExpression(E expression, SourceLocation sourceLocation) throws ModelException; + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is equal to the value obtained by + * evaluating the right expression. + */ + public E createEqualityExpression(E left, E right, SourceLocation location) throws ModelException; + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is different from the value obtained by + * evaluating the right expression. + */ + public default E createInequalityExpression(E left, E right, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is less than the value obtained by + * evaluating the right expression. + */ + public E createLessThanExpression(E left, E right, SourceLocation location); + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is less than or equal to the value obtained by + * evaluating the right expression. + */ + public default E createLessThanOrEqualExpression(E left, E right, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is greater than the value obtained by + * evaluating the right expression. + */ + public default E createGreaterThanExpression(E left, E right, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to true if the evaluation of the + * left expression yields a value that is greater than or equal to the value obtained by + * evaluating the right expression. + */ + public default E createGreaterThanOrEqualExpression(E left, E right, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the position along the x-axis of + * the game object to which the given expression evaluates. + */ + public default E createGetXExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the position along the y-axis of + * the game object to which the given expression evaluates. + */ + public default E createGetYExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the radius of the game object to which + * the given expression evaluates. + */ + public default E createGetRadiusExpression(E e, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the direction of the game object to which + * the given expression evaluates. + */ + public default E createGetDirectionExpression(E entity, SourceLocation location) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the number of action points of the worm to which + * the given expression evaluates. + */ + public default E createGetActionPointsExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the maximum number of action points of the worm to which + * the given expression evaluates. + */ + public default E createGetMaxActionPointsExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the number of hit points of the game object to which + * the given expression evaluates. + */ + public default E createHitPointsExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + public E createSearchObjectExpression(E angleDelta, SourceLocation sourceLocation) throws ModelException; + + /** + * Returns an expression that evaluates to a boolean reflecting whether or not + * the executing worm belongs to the same team as the worm to which the given + * expression evaluates. + */ + public default E createSameTeamExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + // Individual students must not work out this method. + throw new MustNotImplementException(); + } + + /** + * Returns an expression that evaluates to the distance between the executing worm + * and the game object to which the given expression evaluates. + */ + public E createDistanceExpression(E entity, SourceLocation sourceLocation) throws ModelException; + + /** + * Returns a boolean indicating whether or not the object to which the given + * expression evaluates is a worm. + */ + public E createIsWormExpression(E entity, SourceLocation sourceLocation) throws ModelException; + + /** + * Returns a boolean indicating whether or not the object to which the given + * expression evaluates is a portion of food. + */ + public default E createIsFoodExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + + /** + * Returns a boolean indicating whether or not the object to which the given + * expression evaluates is a projectile. + */ + public default E createIsProjectileExpression(E entity, SourceLocation sourceLocation) + throws ModelException, MustNotImplementException { + throw new MustNotImplementException(); + } + +} diff --git a/OGP1718-Worms/src-provided/worms/programs/ParseOutcome.java b/OGP1718-Worms/src-provided/worms/programs/ParseOutcome.java new file mode 100755 index 0000000..ec6d287 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/ParseOutcome.java @@ -0,0 +1,20 @@ +package worms.programs; + +import java.util.List; + +import worms.programs.SuccessOrFail.WrappedSuccessOrFail; + +public class ParseOutcome

    extends WrappedSuccessOrFail> { + + private ParseOutcome(SuccessOrFail> outcome) { + super(outcome); + } + + public static

    ParseOutcome

    success(P p) { + return new ParseOutcome<>(DefaultSuccessOrFail.success(p)); + } + + public static

    ParseOutcome

    failure(List errors) { + return new ParseOutcome<>(DefaultSuccessOrFail.failure(errors)); + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/ProgramParser.java b/OGP1718-Worms/src-provided/worms/programs/ProgramParser.java new file mode 100755 index 0000000..877b01c --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/ProgramParser.java @@ -0,0 +1,245 @@ +package worms.programs; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.antlr.v4.runtime.BaseErrorListener; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.RecognitionException; +import org.antlr.v4.runtime.Recognizer; + +import worms.programs.IProgramFactory; +import worms.programs.internal.parser.ParserVisitor; +import worms.programs.internal.parser.generated.WormsProgramLexer; +import worms.programs.internal.parser.generated.WormsProgramParser; +import worms.internal.gui.GUIUtils; +import worms.model.Program; + +/** + * Parser for Worms programs. + * + * To use this class, first create an implementation of {@link IProgramFactory}: + * + *

    + * 
    + * IProgramFactory<MyExpression, MyStatement, MyProcedure, Program> factory = new ProgramFactory();
    + * 
    + * 
    + * + * The easiest way to use this class for parsing a Program given as a String is + * via the {@link #parseProgramFromString(String, IProgramFactory)} method: + * + *
    + * 
    + * Program program = ProgramParser.parseProgram(text, factory);
    + * 
    + * 
    + * + * For more control, create an instance of this class: + * + *
    + * 
    + * ProgramParser<MyExpression, MyStatement, Task> parser = new ProgramParser<>(factory);
    + * 
    + * 
    + * + * Finally, parse a string or file:
    + * ParseOurcome<Program> parseResult = parser.parse(textToParse);
    + * 
    + * + * If parsing is successful, parseResult.isSuccess() returns true + * and parseResult.getSuccessValue() returns the created program. + * + * If parsing was not successful, parseResult.ifSuccess() returns + * false and parseResult.getFailValue() returns the list of errors + * during parsing. + * + * + * @param E + * The type of expressions + * @param S + * The type of statements + * @param P + * The type of procedures + * @param Prg + * The type of program that is created; should be your + * worms.model.Program class + */ +public class ProgramParser { + + private final IProgramFactory factory; + + private final List errors = new ArrayList<>(); + + protected ProgramParser(IProgramFactory factory) { + if (factory == null) { + throw new NullPointerException("Factory must be effective."); + } + this.factory = factory; + } + + public IProgramFactory getFactory() { + return factory; + } + + /** + * Returns the program that results from parsing the given string, or + * Optional.empty() if parsing has failed. + * + * When parsing has failed, the error messages can be retrieved with the + * getErrors() method. + * + */ + public ParseOutcome parseString(String string) { + return parse(CharStreams.fromString(string)); + } + + /** + * Returns the program that results from parsing the file with the given name, + * or Optional.empty() if parsing has failed. + * + * When parsing has failed, the error messages can be retrieved with the + * getErrors() method. + */ + public ParseOutcome parseFile(String filename) throws IOException { + return parse(CharStreams.fromStream(GUIUtils.openResource(filename))); + } + + /** + * Returns the program that results from parsing the file with the given URL, or + * Optional.empty() if parsing has failed. + * + * When parsing has failed, the error messages can be retrieved with the + * getErrors() method. + */ + public ParseOutcome parseFile(URL url) throws IOException { + return parse(CharStreams.fromStream(GUIUtils.openResource(url))); + } + + /** + * Returns the program that results from parsing the given CharStream, or + * Optional.empty() if parsing has failed. + * + * When parsing has failed, the error messages can be retrieved with the + * getErrors() method. + * + * @note For more convenient methods, see the + * {@link #parseProgramFromString(String, ITaskFactory, List)}, + * {@link #parseProgramFromFile(String, ITaskFactory, List)}, + * {@link #parseString(String, List)} and {@link #parseFile(String, List)} + * methods. + */ + protected ParseOutcome parse(CharStream input) { + reset(); + + WormsProgramLexer lexer = new WormsProgramLexer(input); + WormsProgramParser parser = new WormsProgramParser(new CommonTokenStream(lexer)); + parser.addErrorListener(new BaseErrorListener() { + @Override + public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, + int charPositionInLine, String msg, RecognitionException e) { + errors.add(msg + " (" + line + ", " + charPositionInLine + ")"); + } + }); + ParserVisitor visitor = new ParserVisitor<>(factory); + try { + visitor.visitProgram(parser.program()); + if (errors.isEmpty()) { + assert visitor.getMain() != null; + Prg program = factory.createProgram(visitor.getProcedures(), visitor.getMain()); + if (program != null) { + return ParseOutcome.success(program); + } + errors.add("Factory did not return a Program object"); + } + } catch (Exception e) { + e.printStackTrace(); + errors.add(e.toString()); + } + return ParseOutcome.failure(errors); + } + + protected void reset() { + this.errors.clear(); + } + + public List getErrors() { + return Collections.unmodifiableList(errors); + } + + /** + * Create a new parser from the given factory. + * + * @param factory + * @return + */ + public static ProgramParser create(IProgramFactory factory) { + return new ProgramParser<>(factory); + } + + /** + * Parse program text using the given factory. + * + * @param text + * The text to parse + * @param factory + * The factory to use + * @return The parsed program, if any, or null if an error occurred during + * parsing. + */ + public static Program parseProgramFromString(String text, IProgramFactory factory) { + ProgramParser parser = create(factory); + ParseOutcome outcome = parser.parseString(text); + if (outcome.isFail()) { + System.out.println("Parsing failed: " + outcome.getFailValue()); + return null; + } + return outcome.getSuccessValue(); + } + + /** + * Parse program from a file using the given factory. + * + * @param filename + * The filename from which to read the program text + * @param factory + * The factory to use + * @return The parsed program, if any, or null if an error occurred during + * parsing. + */ + public static Program parseProgramFromFile(String filename, IProgramFactory factory) + throws IOException { + ProgramParser parser = create(factory); + ParseOutcome outcome = parser.parseFile(filename); + if (outcome.isFail()) { + System.out.println("Parsing failed: " + outcome.getFailValue()); + return null; + } + return outcome.getSuccessValue(); + } + + /** + * Parse program from a file using the given factory. + * + * @param filename + * The filename from which to read the program text + * @param factory + * The factory to use + * @return The parsed program, if any, or null if an error occurred during + * parsing. + */ + public static Program parseProgramFromURL(URL url, IProgramFactory factory) throws IOException { + ProgramParser parser = create(factory); + ParseOutcome outcome = parser.parseFile(url); + if (outcome.isFail()) { + System.out.println("Parsing failed: " + outcome.getFailValue()); + return null; + } + return outcome.getSuccessValue(); + } +} diff --git a/OGP1718-Worms/src-provided/worms/programs/SourceLocation.java b/OGP1718-Worms/src-provided/worms/programs/SourceLocation.java new file mode 100755 index 0000000..9ab882f --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/SourceLocation.java @@ -0,0 +1,61 @@ +package worms.programs; + +import be.kuleuven.cs.som.annotate.Value; + +/** + * A source location represents a position in a source file, + * denoted by the line and column (position in the line) of + * a certain character in the file. + * + * This class is a value class. + */ +@Value +public final class SourceLocation { + + private final int line; + private final int column; + + public SourceLocation(int line, int column) { + this.line = line; + this.column = column; + } + + public int getLine() { + return line; + } + + public int getColumn() { + return column; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + column; + result = prime * result + line; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SourceLocation other = (SourceLocation) obj; + if (column != other.column) + return false; + if (line != other.line) + return false; + return true; + } + + @Override + public String toString() { + return String.format("@%d,%d", line, column); + } + +} diff --git a/OGP1718-Worms/src-provided/worms/programs/SuccessOrFail.java b/OGP1718-Worms/src-provided/worms/programs/SuccessOrFail.java new file mode 100755 index 0000000..211b391 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/SuccessOrFail.java @@ -0,0 +1,100 @@ +package worms.programs; + +/** + * An interface that holds either a success value of type S or a failure value of type F. + */ +public interface SuccessOrFail { + + public boolean isSuccess(); + + public S getSuccessValue(); + + public F getFailValue(); + + public default boolean isFail() { + return !isSuccess(); + } + + public static class DefaultSuccessOrFail implements SuccessOrFail { + private final boolean success; + private final F failValue; + private final S successValue; + + private DefaultSuccessOrFail(boolean success, S successValue, F failValue) { + if (success && failValue != null) { + throw new IllegalArgumentException(); + } + if (!success && successValue != null) { + throw new IllegalArgumentException(); + } + this.success = success; + this.successValue = successValue; + this.failValue = failValue; + } + + @Override + public boolean isSuccess() { + return success; + } + + @Override + public F getFailValue() { + return failValue; + } + + @Override + public S getSuccessValue() { + return successValue; + } + + public static SuccessOrFail success(S successValue) { + return new DefaultSuccessOrFail<>(true, successValue, null); + } + + public static SuccessOrFail failure(F failValue) { + return new DefaultSuccessOrFail<>(false, null, failValue); + } + + @Override + public String toString() { + if (isSuccess()) { + return "SUCCESS value: " + getSuccessValue(); + } else { + return "FAIL value: " + getFailValue(); + } + } + + } + + public static class WrappedSuccessOrFail implements SuccessOrFail { + private final SuccessOrFail wrapped; + + protected WrappedSuccessOrFail(SuccessOrFail wrapped) { + if (wrapped == null) { + throw new NullPointerException(); + } + this.wrapped = wrapped; + } + + @Override + public boolean isSuccess() { + return wrapped.isSuccess(); + } + + @Override + public S getSuccessValue() { + return wrapped.getSuccessValue(); + } + + @Override + public F getFailValue() { + return wrapped.getFailValue(); + } + + @Override + public String toString() { + return wrapped.toString(); + } + + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/ParserVisitor.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/ParserVisitor.java new file mode 100755 index 0000000..55fc02c --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/ParserVisitor.java @@ -0,0 +1,392 @@ +package worms.programs.internal.parser; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import org.antlr.v4.runtime.ParserRuleContext; +import org.antlr.v4.runtime.Token; + +import worms.programs.IProgramFactory; +import worms.programs.SourceLocation; +import worms.programs.internal.parser.generated.WormsProgramBaseVisitor; +import worms.programs.internal.parser.generated.WormsProgramLexer; +import worms.programs.internal.parser.generated.WormsProgramParser.AddSubExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.AndOrExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.AssignmentStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.BreakStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ComparisonExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ConstantExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.CosExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.DistanceExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.EatActionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.FalseLiteralExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.FireActionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetAPExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetDirectionExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetHPExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetMaxAPExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetRadiusExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetXExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.GetYExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.IfStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.InvokeStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.IsFoodExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.IsProjectileExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.IsWormExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.JumpActionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.MoveActionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.MulDivExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.NotExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.NullExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ParenExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.PrintStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ProceduredefContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ProgramContext; +import worms.programs.internal.parser.generated.WormsProgramParser.ReadVariableExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SameTeamExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SearchObjExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SelfExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SequenceStatementContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SinExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.SqrtExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.TrueLiteralExpressionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.TurnActionContext; +import worms.programs.internal.parser.generated.WormsProgramParser.WhileStatementContext; + +public class ParserVisitor extends WormsProgramBaseVisitor { + + @Override + public Void visitProgram(ProgramContext ctx) { + procedures = ctx.procdef.stream().map(procdef -> procDefVisitor.visit(procdef)).collect(Collectors.toList()); + List mainStmts = ctx.programBody.stream().map(stmt -> statementVisitor.visit(stmt)) + .collect(Collectors.toList()); + if (mainStmts.size() == 1) { + main = mainStmts.get(0); + } else { + main = factory.createSequenceStatement(mainStmts, toSourceLocation(ctx)); + } + assert main != null; + return null; + } + + private class ProcedureDefinitionVisitor extends WormsProgramBaseVisitor

    { + + @Override + public P visitProceduredef(ProceduredefContext ctx) { + return getFactory().createProcedureDefinition(ctx.procname.getText(), statementVisitor.visit(ctx.body), + toSourceLocation(ctx)); + } + } + + private class StatementVisitor extends WormsProgramBaseVisitor { + + @Override + public S visitAssignmentStatement(AssignmentStatementContext ctx) { + return getFactory().createAssignmentStatement(ctx.variableName.getText(), + expressionVisitor.visit(ctx.value), toSourceLocation(ctx)); + } + + @Override + public S visitWhileStatement(WhileStatementContext ctx) { + return getFactory().createWhileStatement(expressionVisitor.visit(ctx.condition), + statementVisitor.visit(ctx.body), toSourceLocation(ctx)); + } + + @Override + public S visitIfStatement(IfStatementContext ctx) { + S ifBody = statementVisitor.visit(ctx.ifbody); + S elseBody = null; + if (ctx.elsebody != null) + elseBody = statementVisitor.visit(ctx.elsebody); + return getFactory().createIfStatement(expressionVisitor.visit(ctx.condition), ifBody, elseBody, + toSourceLocation(ctx)); + } + + @Override + public S visitPrintStatement(PrintStatementContext ctx) { + return getFactory().createPrintStatement(expressionVisitor.visit(ctx.value), toSourceLocation(ctx)); + } + + @Override + public S visitSequenceStatement(SequenceStatementContext ctx) { + if (ctx.stmts.size() != 1) { + return getFactory().createSequenceStatement( + ctx.stmts.stream().map(this::visit).collect(Collectors.toList()), toSourceLocation(ctx)); + } else { + return visit(ctx.stmts.get(0)); + } + } + + @Override + public S visitInvokeStatement(InvokeStatementContext ctx) { + return getFactory().createInvokeStatement(ctx.procName.getText(), toSourceLocation(ctx)); + } + + @Override + public S visitBreakStatement(BreakStatementContext ctx) { + return getFactory().createBreakStatement(toSourceLocation(ctx)); + } + + @Override + public S visitTurnAction(TurnActionContext ctx) { + return getFactory().createTurnStatement(expressionVisitor.visit(ctx.angle), toSourceLocation(ctx)); + } + + @Override + public S visitMoveAction(MoveActionContext ctx) { + return getFactory().createMoveStatement(toSourceLocation(ctx)); + } + + @Override + public S visitJumpAction(JumpActionContext ctx) { + return getFactory().createJumpStatement(toSourceLocation(ctx)); + } + + @Override + public S visitEatAction(EatActionContext ctx) { + return getFactory().createEatStatement(toSourceLocation(ctx)); + } + + @Override + public S visitFireAction(FireActionContext ctx) { + return getFactory().createFireStatement(toSourceLocation(ctx)); + } + + } + + private class ExpressionVisitor extends WormsProgramBaseVisitor { + + @Override + public E visitReadVariableExpression(ReadVariableExpressionContext ctx) { + return getFactory().createReadVariableExpression(ctx.variable.getText(), toSourceLocation(ctx)); + } + + @Override + public E visitConstantExpression(ConstantExpressionContext ctx) { + return getFactory().createDoubleLiteralExpression(Double.parseDouble(ctx.value.getText()), + toSourceLocation(ctx)); + } + + @Override + public E visitTrueLiteralExpression(TrueLiteralExpressionContext ctx) { + return getFactory().createBooleanLiteralExpression(true, toSourceLocation(ctx)); + } + + @Override + public E visitFalseLiteralExpression(FalseLiteralExpressionContext ctx) { + return getFactory().createBooleanLiteralExpression(false, toSourceLocation(ctx)); + } + + @Override + public E visitNullExpression(NullExpressionContext ctx) { + return getFactory().createNullExpression(toSourceLocation(ctx)); + } + + @Override + public E visitSelfExpression(SelfExpressionContext ctx) { + return getFactory().createSelfExpression(toSourceLocation(ctx)); + } + + @Override + public E visitParenExpression(ParenExpressionContext ctx) { + return expressionVisitor.visit(ctx.subExpr); + } + + @Override + public E visitAddSubExpression(AddSubExpressionContext ctx) { + switch (ctx.op.getType()) { + case WormsProgramLexer.ADD: + return getFactory().createAdditionExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.SUB: + return getFactory().createSubtractionExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + default: + throw new IllegalArgumentException("Unknown operator: " + ctx.op); + } + } + + @Override + public E visitMulDivExpression(MulDivExpressionContext ctx) { + switch (ctx.op.getType()) { + case WormsProgramLexer.MUL: + return getFactory().createMultiplicationExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.DIV: + return getFactory().createDivisionExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + default: + throw new IllegalArgumentException("Unknown operator: " + ctx.op); + } + } + + @Override + public E visitSqrtExpression(SqrtExpressionContext ctx) { + return getFactory().createSqrtExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitSinExpression(SinExpressionContext ctx) { + return getFactory().createSinExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitCosExpression(CosExpressionContext ctx) { + return getFactory().createCosExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitAndOrExpression(AndOrExpressionContext ctx) { + switch (ctx.op.getType()) { + case WormsProgramLexer.AND: + return getFactory().createAndExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.OR: + return getFactory().createOrExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + default: + throw new IllegalArgumentException("Unknown operator: " + ctx.op); + } + } + + @Override + public E visitNotExpression(NotExpressionContext ctx) { + return getFactory().createNotExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitComparisonExpression(ComparisonExpressionContext ctx) { + switch (ctx.op.getType()) { + case WormsProgramLexer.LT: + return getFactory().createLessThanExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.LTE: + return getFactory().createLessThanOrEqualExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.GT: + return getFactory().createGreaterThanExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.GTE: + return getFactory().createGreaterThanOrEqualExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.EQ: + return getFactory().createEqualityExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + case WormsProgramLexer.NEQ: + return getFactory().createInequalityExpression(expressionVisitor.visit(ctx.left), + expressionVisitor.visit(ctx.right), toSourceLocation(ctx)); + default: + throw new IllegalArgumentException("Unknown operand: " + ctx.op); + } + + } + + @Override + public E visitGetXExpression(GetXExpressionContext ctx) { + return getFactory().createGetXExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitGetYExpression(GetYExpressionContext ctx) { + return getFactory().createGetYExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitGetRadiusExpression(GetRadiusExpressionContext ctx) { + return getFactory().createGetRadiusExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitGetDirectionExpression(GetDirectionExpressionContext ctx) { + return getFactory().createGetDirectionExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitGetAPExpression(GetAPExpressionContext ctx) { + return getFactory().createGetActionPointsExpression(expressionVisitor.visit(ctx.expr), + toSourceLocation(ctx)); + } + + @Override + public E visitGetMaxAPExpression(GetMaxAPExpressionContext ctx) { + return getFactory().createGetMaxActionPointsExpression(expressionVisitor.visit(ctx.expr), + toSourceLocation(ctx)); + } + + @Override + public E visitGetHPExpression(GetHPExpressionContext ctx) { + return getFactory().createHitPointsExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitSameTeamExpression(SameTeamExpressionContext ctx) { + return getFactory().createSameTeamExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitSearchObjExpression(SearchObjExpressionContext ctx) { + return getFactory().createSearchObjectExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitDistanceExpression(DistanceExpressionContext ctx) { + return getFactory().createDistanceExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitIsWormExpression(IsWormExpressionContext ctx) { + return getFactory().createIsWormExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitIsFoodExpression(IsFoodExpressionContext ctx) { + return getFactory().createIsFoodExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + @Override + public E visitIsProjectileExpression(IsProjectileExpressionContext ctx) { + return getFactory().createIsProjectileExpression(expressionVisitor.visit(ctx.expr), toSourceLocation(ctx)); + } + + } + + private final IProgramFactory factory; + + private final ProcedureDefinitionVisitor procDefVisitor = new ProcedureDefinitionVisitor(); + private final StatementVisitor statementVisitor = new StatementVisitor(); + private final ExpressionVisitor expressionVisitor = new ExpressionVisitor(); + + private S main; + private List

    procedures; + + public ParserVisitor(IProgramFactory factory) { + if (factory == null) { + throw new NullPointerException(); + } + this.factory = factory; + } + + private SourceLocation toSourceLocation(ParserRuleContext ctx) { + int line = ctx.getStart().getLine(); + int column = ctx.getStart().getCharPositionInLine(); + return new SourceLocation(line, column); + } + + public IProgramFactory getFactory() { + return factory; + } + + public int toInt(Token z) { + return Integer.parseInt(z.getText()); + } + + public S getMain() { + return main; + } + + public List

    getProcedures() { + return Collections.unmodifiableList(procedures); + } + +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/WormsProgram.g4 b/OGP1718-Worms/src-provided/worms/programs/internal/parser/WormsProgram.g4 new file mode 100755 index 0000000..4ceae35 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/WormsProgram.g4 @@ -0,0 +1,200 @@ +// ANTLR v4 Grammar for controling Worms. +// Check the tutorial at http://jnb.ociweb.com/jnb/jnbJun2008.html +// or http://www.antlr.org/ for details. + + +grammar WormsProgram; + +@header { + package worms.programs.internal.parser.generated; +} + + +// ------------------------------------------------------------------------ +// --- Eval and Related Definitions --------------------------------------- +// ------------------------------------------------------------------------ +program: (procdef+=proceduredef)* + (programBody+=statement)* +; + +proceduredef: DEF procname=IDENTIFIER COLON? + body=statement +; + +statement: assignmentStatement + | whileStatement + | ifStatement + | printStatement + | sequenceStatement + | invokeStatement + | breakStatement + | actionStatement +; + +assignmentStatement: variableName=IDENTIFIER ASSIGN value=expression ';' +; + +whileStatement: WHILE condition=expression COLON? + body=statement +; + +ifStatement: IF condition=expression COLON? + ifbody=statement + (ELSE COLON? + elsebody=statement)? +; + +printStatement: PRINT value=expression ';' +; + +sequenceStatement: LEFT_BRACE (stmts+=statement)* RIGHT_BRACE +; + +invokeStatement: INVOKE procName=IDENTIFIER ';' +; + + +breakStatement: BREAK ';' +; + + +actionStatement: TURN angle=expression ';' #turnAction + | MOVE ';' #moveAction + | JUMP ';' #jumpAction + | EAT ';' #eatAction + | FIRE ';' #fireAction +; + +// order here sets order of operations (important for left-recursive expressions!) +expression: variable=IDENTIFIER #readVariableExpression + | value=NUMBER #constantExpression + | TRUE #trueLiteralExpression + | FALSE #falseLiteralExpression + | NULL #nullExpression + | SELF #selfExpression + | LEFT_PAREN subExpr=expression RIGHT_PAREN #parenExpression + | left=expression op=(MUL | DIV) right=expression #mulDivExpression + | left=expression op=(ADD | SUB) right=expression #addSubExpression + | left=expression op=(LT | LTE | GT | GTE | EQ | NEQ) right=expression #comparisonExpression + | left=expression op=(AND | OR) right=expression #andOrExpression + | SQRT LEFT_PAREN expr=expression RIGHT_PAREN #sqrtExpression + | SIN LEFT_PAREN expr=expression RIGHT_PAREN #sinExpression + | COS LEFT_PAREN expr=expression RIGHT_PAREN #cosExpression + | NOT expr=expression #notExpression + | GETX expr=expression #getXExpression + | GETY expr=expression #getYExpression + | GETRADIUS expr=expression #getRadiusExpression + | GETDIR expr=expression #getDirectionExpression + | GETAP expr=expression #getAPExpression + | GETMAXAP expr=expression #getMaxAPExpression + | GETHP expr=expression #getHPExpression + | SAMETEAM expr=expression #sameTeamExpression + | SEARCHOBJ expr=expression #searchObjExpression + | DISTANCE expr=expression #distanceExpression + | ISWORM expr=expression #isWormExpression + | ISFOOD expr=expression #isFoodExpression + | ISPROJECTILE expr=expression #isProjectileExpression +; + +// ------------------------------------------------------------------------ +// --- Specifiers ----------------------------------------------- +// ------------------------------------------------------------------------ + +NULL: 'null'; +SELF: 'self'; +TRUE: 'true'; +FALSE: 'false'; + +// ------------------------------------------------------------------------ +// --- Unary Operations --------------------------------------------------- +// ------------------------------------------------------------------------ +SQRT: 'sqrt'; +SIN: 'sin'; +COS: 'cos'; +NOT: '!'; +GETX: 'getx'; +GETY: 'gety'; +GETRADIUS: 'getradius'; +GETDIR: 'getdir'; +GETAP: 'getap'; +GETMAXAP: 'getmaxap'; +GETHP: 'gethp'; +SAMETEAM: 'sameteam'; +SEARCHOBJ: 'searchobj'; +DISTANCE: 'distance'; +ISWORM: 'isworm'; +ISFOOD: 'isfood'; +ISPROJECTILE: 'isprojectile'; + +// ------------------------------------------------------------------------ +// --- Actions ----------------------------------------------- +// ------------------------------------------------------------------------ +TURN: 'turn'; +MOVE: 'move'; +JUMP: 'jump'; +EAT: 'eat'; +FIRE: 'fire'; + + +// ------------------------------------------------------------------------ +// --- Control Flow ------------------------------------------------------- +// ------------------------------------------------------------------------ +DEF: 'def'; +IF: 'if'; +INVOKE: 'invoke'; +THEN: 'then'; +ELSE: 'else'; +WHILE: 'while'; +BREAK: 'break'; +PRINT: 'print'; + + +// ------------------------------------------------------------------------ +// --- Assignment and Arithmetics ----------------------------------------- +// ------------------------------------------------------------------------ +ASSIGN: ':='; +ADD: '+'; +SUB: '-'; +MUL: '*'; +DIV: '/'; +AND: '&&'; +OR: '||'; +LT: '<'; +LTE: '<='; +GT: '>'; +GTE: '>='; +EQ: '=='; +NEQ: '!='; + +// ------------------------------------------------------------------------ +// --- Literals and Variables --------------------------------------------- +// ------------------------------------------------------------------------ + +NUMBER: INTEGER | FLOAT; +FLOAT: INTEGER '.' ('0'..'9')+; +INTEGER: ('-'|'+')? ('0'..'9')+; + +IDENTIFIER: LETTER (LETTER | DIGIT | '_')*; +fragment LETTER: LOWER | UPPER; +fragment LOWER: 'a'..'z'; +fragment UPPER: 'A'..'Z'; +fragment DIGIT: '0'..'9'; + +LEFT_PAREN: '('; +RIGHT_PAREN: ')'; +LEFT_BRACE: '{'; +RIGHT_BRACE: '}'; +COLON: ':'; + +// ------------------------------------------------------------------------ +// --- Syntactical Ballast ------------------------------------------------ +// ------------------------------------------------------------------------ + +// Skip runs of newline, space and tab characters. +WHITESPACE: [ \t\r\n]+ -> skip; + +// Single-line comments begin with //, are followed by any characters +// other than those in a newline, and are terminated by newline characters. +SINGLE_COMMENT: '//' ~('\r' | '\n')* NEWLINE -> skip; +fragment NEWLINE: ('\r'? '\n')+; + diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/ExamplePrinter.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/ExamplePrinter.java new file mode 100755 index 0000000..d5db737 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/ExamplePrinter.java @@ -0,0 +1,42 @@ +package worms.programs.internal.parser.example; + +import java.io.IOException; + +import worms.programs.IProgramFactory; +import worms.programs.ParseOutcome; +import worms.programs.ProgramParser; + +public class ExamplePrinter { + public static void main(String[] args) throws IOException { + IProgramFactory factory = PrintingObjectFactory.create(); + ProgramParser parser = ProgramParser.create(factory); + + /* + ParseOutcome outcome = parser.parseString( + "def controlled_move:" + + " if getap self > 100.0:" + + " { jump; print getx self; print gety self; }" + + " else move;" + + "" + + "max_distance := 10.0;" + + "while true: {" + + " w := searchobj 0.0;" + + " if isworm w: {" + + " if sameteam w:" + + " invoke controlled_move;" + + " else if distance w < max_distance:" + + " fire;" + + " else" + + " { turn d; max_distance := max_distance + 0.1; }" + + " }" + + "}"); + */ + //ParseOutcome outcome = parser.parseFile("programs/program_example.txt"); + //ParseOutcome outcome = parser.parseFile("programs/syntax_test.txt"); + ParseOutcome outcome = parser.parseFile("programs/program.txt"); + + System.out.println(outcome); + + } + +} diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObject.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObject.java new file mode 100755 index 0000000..2183b4c --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObject.java @@ -0,0 +1,80 @@ +package worms.programs.internal.parser.example; + +import java.util.List; +import java.util.StringTokenizer; +import java.util.stream.Collectors; + +import worms.programs.SourceLocation; + +public class PrintingObject { + + private boolean indented = false; + + private final StringBuilder repr = new StringBuilder(); + + public PrintingObject(SourceLocation loc, String method, Object... args) { + if (loc != null) { + method = loc + " " + method; + } + if (args.length > 1) { + indented(method + "("); + indented = true; + for (int i = 0; i < args.length; i++) { + indented(repr(args[i]), args.length > 1 && i < args.length - 1); + } + indented = false; + indented(")"); + } else { + String msg = method + "( "; + if (args.length > 0) { + msg += repr(args[0]).toString().trim(); + } + msg += " )"; + indented(msg); + } + } + + private String repr(Object object) { + if (object instanceof String) { + object = "\"" + object + "\""; + } else if (object instanceof List) { + object = String.format("Arrays.toList(%s)", ((List) object) + .stream().map(this::repr) + .collect(Collectors.joining(", ### Arrays.toList\n"))); + } + if (object != null) { + return object.toString(); + } else { + return "null"; + } + } + + @Override + public String toString() { + return repr.toString(); + } + + private void indented(Object object) { + indented(object, false); + } + + private void indented(Object object, boolean appendComma) { + if (object != null) { + String str = object.toString(); + StringTokenizer tok = new StringTokenizer(str, "\n"); + while (tok.hasMoreTokens()) { + if (indented) + repr.append("| "); + repr.append(tok.nextToken()); + if (!tok.hasMoreTokens() && appendComma) { + repr.append(","); + } + repr.append("\n"); + } + } else { + if (indented) + repr.append(" null"); + } + + } +} diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObjectFactory.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObjectFactory.java new file mode 100755 index 0000000..1950b1c --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingObjectFactory.java @@ -0,0 +1,49 @@ +package worms.programs.internal.parser.example; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import java.util.List; + +import worms.programs.IProgramFactory; +import worms.programs.SourceLocation; + + +public class PrintingObjectFactory { + + /** + * Creates an implementation of IProgramFactory where the implementation of + * each interface method (except createProgram) just creates a + * PrintingObject with all arguments. + */ + @SuppressWarnings("unchecked") + public static IProgramFactory create() { + + InvocationHandler handler = new InvocationHandler() { + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().equals("createProgram")) { + List functions = (List)args[0]; + PrintingObject main = (PrintingObject) args[1]; + return new PrintingProgram(functions, main); + } + if (args != null) { + SourceLocation sourceLocation = (SourceLocation) args[args.length - 1]; + if (args.length >= 1) { + return new PrintingObject(sourceLocation, method.getName(), + Arrays.copyOfRange(args, 0, args.length - 1)); + } else { + return new PrintingObject(sourceLocation, method.getName()); + } + } else { + return new PrintingObject(null, method.getName()); + } + } + }; + + return (IProgramFactory) Proxy.newProxyInstance( + IProgramFactory.class.getClassLoader(), new Class[] { IProgramFactory.class }, handler); + } +} diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingProgram.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingProgram.java new file mode 100755 index 0000000..685d7c5 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/example/PrintingProgram.java @@ -0,0 +1,22 @@ +package worms.programs.internal.parser.example; + +import java.util.List; + +public class PrintingProgram { + + private List procedures; + private PrintingObject main; + + public PrintingProgram(List procedures, PrintingObject main) { + if (main == null) { + throw new NullPointerException("main null"); + } + this.main = main; + this.procedures = procedures; + } + + @Override + public String toString() { + return "Procedures: " + procedures.toString() + "\nMain:" + main.toString(); + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.interp b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.interp new file mode 100755 index 0000000..e3d1b4b --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.interp @@ -0,0 +1,141 @@ +token literal names: +null +';' +'null' +'self' +'true' +'false' +'sqrt' +'sin' +'cos' +'!' +'getx' +'gety' +'getradius' +'getdir' +'getap' +'getmaxap' +'gethp' +'sameteam' +'searchobj' +'distance' +'isworm' +'isfood' +'isprojectile' +'turn' +'move' +'jump' +'eat' +'fire' +'def' +'if' +'invoke' +'then' +'else' +'while' +'break' +'print' +':=' +'+' +'-' +'*' +'/' +'&&' +'||' +'<' +'<=' +'>' +'>=' +'==' +'!=' +null +null +null +null +'(' +')' +'{' +'}' +':' +null +null + +token symbolic names: +null +null +NULL +SELF +TRUE +FALSE +SQRT +SIN +COS +NOT +GETX +GETY +GETRADIUS +GETDIR +GETAP +GETMAXAP +GETHP +SAMETEAM +SEARCHOBJ +DISTANCE +ISWORM +ISFOOD +ISPROJECTILE +TURN +MOVE +JUMP +EAT +FIRE +DEF +IF +INVOKE +THEN +ELSE +WHILE +BREAK +PRINT +ASSIGN +ADD +SUB +MUL +DIV +AND +OR +LT +LTE +GT +GTE +EQ +NEQ +NUMBER +FLOAT +INTEGER +IDENTIFIER +LEFT_PAREN +RIGHT_PAREN +LEFT_BRACE +RIGHT_BRACE +COLON +WHITESPACE +SINGLE_COMMENT + +rule names: +program +proceduredef +statement +assignmentStatement +whileStatement +ifStatement +printStatement +sequenceStatement +invokeStatement +breakStatement +actionStatement +expression + + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 3, 61, 188, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 3, 2, 7, 2, 28, 10, 2, 12, 2, 14, 2, 31, 11, 2, 3, 2, 7, 2, 34, 10, 2, 12, 2, 14, 2, 37, 11, 2, 3, 3, 3, 3, 3, 3, 5, 3, 42, 10, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 5, 4, 54, 10, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 5, 6, 64, 10, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 5, 7, 71, 10, 7, 3, 7, 3, 7, 3, 7, 5, 7, 76, 10, 7, 3, 7, 5, 7, 79, 10, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 7, 9, 87, 10, 9, 12, 9, 14, 9, 90, 11, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 5, 12, 113, 10, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 5, 13, 169, 10, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 7, 13, 183, 10, 13, 12, 13, 14, 13, 186, 11, 13, 3, 13, 2, 3, 24, 14, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 2, 6, 3, 2, 41, 42, 3, 2, 39, 40, 3, 2, 45, 50, 3, 2, 43, 44, 2, 221, 2, 29, 3, 2, 2, 2, 4, 38, 3, 2, 2, 2, 6, 53, 3, 2, 2, 2, 8, 55, 3, 2, 2, 2, 10, 60, 3, 2, 2, 2, 12, 67, 3, 2, 2, 2, 14, 80, 3, 2, 2, 2, 16, 84, 3, 2, 2, 2, 18, 93, 3, 2, 2, 2, 20, 97, 3, 2, 2, 2, 22, 112, 3, 2, 2, 2, 24, 168, 3, 2, 2, 2, 26, 28, 5, 4, 3, 2, 27, 26, 3, 2, 2, 2, 28, 31, 3, 2, 2, 2, 29, 27, 3, 2, 2, 2, 29, 30, 3, 2, 2, 2, 30, 35, 3, 2, 2, 2, 31, 29, 3, 2, 2, 2, 32, 34, 5, 6, 4, 2, 33, 32, 3, 2, 2, 2, 34, 37, 3, 2, 2, 2, 35, 33, 3, 2, 2, 2, 35, 36, 3, 2, 2, 2, 36, 3, 3, 2, 2, 2, 37, 35, 3, 2, 2, 2, 38, 39, 7, 30, 2, 2, 39, 41, 7, 54, 2, 2, 40, 42, 7, 59, 2, 2, 41, 40, 3, 2, 2, 2, 41, 42, 3, 2, 2, 2, 42, 43, 3, 2, 2, 2, 43, 44, 5, 6, 4, 2, 44, 5, 3, 2, 2, 2, 45, 54, 5, 8, 5, 2, 46, 54, 5, 10, 6, 2, 47, 54, 5, 12, 7, 2, 48, 54, 5, 14, 8, 2, 49, 54, 5, 16, 9, 2, 50, 54, 5, 18, 10, 2, 51, 54, 5, 20, 11, 2, 52, 54, 5, 22, 12, 2, 53, 45, 3, 2, 2, 2, 53, 46, 3, 2, 2, 2, 53, 47, 3, 2, 2, 2, 53, 48, 3, 2, 2, 2, 53, 49, 3, 2, 2, 2, 53, 50, 3, 2, 2, 2, 53, 51, 3, 2, 2, 2, 53, 52, 3, 2, 2, 2, 54, 7, 3, 2, 2, 2, 55, 56, 7, 54, 2, 2, 56, 57, 7, 38, 2, 2, 57, 58, 5, 24, 13, 2, 58, 59, 7, 3, 2, 2, 59, 9, 3, 2, 2, 2, 60, 61, 7, 35, 2, 2, 61, 63, 5, 24, 13, 2, 62, 64, 7, 59, 2, 2, 63, 62, 3, 2, 2, 2, 63, 64, 3, 2, 2, 2, 64, 65, 3, 2, 2, 2, 65, 66, 5, 6, 4, 2, 66, 11, 3, 2, 2, 2, 67, 68, 7, 31, 2, 2, 68, 70, 5, 24, 13, 2, 69, 71, 7, 59, 2, 2, 70, 69, 3, 2, 2, 2, 70, 71, 3, 2, 2, 2, 71, 72, 3, 2, 2, 2, 72, 78, 5, 6, 4, 2, 73, 75, 7, 34, 2, 2, 74, 76, 7, 59, 2, 2, 75, 74, 3, 2, 2, 2, 75, 76, 3, 2, 2, 2, 76, 77, 3, 2, 2, 2, 77, 79, 5, 6, 4, 2, 78, 73, 3, 2, 2, 2, 78, 79, 3, 2, 2, 2, 79, 13, 3, 2, 2, 2, 80, 81, 7, 37, 2, 2, 81, 82, 5, 24, 13, 2, 82, 83, 7, 3, 2, 2, 83, 15, 3, 2, 2, 2, 84, 88, 7, 57, 2, 2, 85, 87, 5, 6, 4, 2, 86, 85, 3, 2, 2, 2, 87, 90, 3, 2, 2, 2, 88, 86, 3, 2, 2, 2, 88, 89, 3, 2, 2, 2, 89, 91, 3, 2, 2, 2, 90, 88, 3, 2, 2, 2, 91, 92, 7, 58, 2, 2, 92, 17, 3, 2, 2, 2, 93, 94, 7, 32, 2, 2, 94, 95, 7, 54, 2, 2, 95, 96, 7, 3, 2, 2, 96, 19, 3, 2, 2, 2, 97, 98, 7, 36, 2, 2, 98, 99, 7, 3, 2, 2, 99, 21, 3, 2, 2, 2, 100, 101, 7, 25, 2, 2, 101, 102, 5, 24, 13, 2, 102, 103, 7, 3, 2, 2, 103, 113, 3, 2, 2, 2, 104, 105, 7, 26, 2, 2, 105, 113, 7, 3, 2, 2, 106, 107, 7, 27, 2, 2, 107, 113, 7, 3, 2, 2, 108, 109, 7, 28, 2, 2, 109, 113, 7, 3, 2, 2, 110, 111, 7, 29, 2, 2, 111, 113, 7, 3, 2, 2, 112, 100, 3, 2, 2, 2, 112, 104, 3, 2, 2, 2, 112, 106, 3, 2, 2, 2, 112, 108, 3, 2, 2, 2, 112, 110, 3, 2, 2, 2, 113, 23, 3, 2, 2, 2, 114, 115, 8, 13, 1, 2, 115, 169, 7, 54, 2, 2, 116, 169, 7, 51, 2, 2, 117, 169, 7, 6, 2, 2, 118, 169, 7, 7, 2, 2, 119, 169, 7, 4, 2, 2, 120, 169, 7, 5, 2, 2, 121, 122, 7, 55, 2, 2, 122, 123, 5, 24, 13, 2, 123, 124, 7, 56, 2, 2, 124, 169, 3, 2, 2, 2, 125, 126, 7, 8, 2, 2, 126, 127, 7, 55, 2, 2, 127, 128, 5, 24, 13, 2, 128, 129, 7, 56, 2, 2, 129, 169, 3, 2, 2, 2, 130, 131, 7, 9, 2, 2, 131, 132, 7, 55, 2, 2, 132, 133, 5, 24, 13, 2, 133, 134, 7, 56, 2, 2, 134, 169, 3, 2, 2, 2, 135, 136, 7, 10, 2, 2, 136, 137, 7, 55, 2, 2, 137, 138, 5, 24, 13, 2, 138, 139, 7, 56, 2, 2, 139, 169, 3, 2, 2, 2, 140, 141, 7, 11, 2, 2, 141, 169, 5, 24, 13, 16, 142, 143, 7, 12, 2, 2, 143, 169, 5, 24, 13, 15, 144, 145, 7, 13, 2, 2, 145, 169, 5, 24, 13, 14, 146, 147, 7, 14, 2, 2, 147, 169, 5, 24, 13, 13, 148, 149, 7, 15, 2, 2, 149, 169, 5, 24, 13, 12, 150, 151, 7, 16, 2, 2, 151, 169, 5, 24, 13, 11, 152, 153, 7, 17, 2, 2, 153, 169, 5, 24, 13, 10, 154, 155, 7, 18, 2, 2, 155, 169, 5, 24, 13, 9, 156, 157, 7, 19, 2, 2, 157, 169, 5, 24, 13, 8, 158, 159, 7, 20, 2, 2, 159, 169, 5, 24, 13, 7, 160, 161, 7, 21, 2, 2, 161, 169, 5, 24, 13, 6, 162, 163, 7, 22, 2, 2, 163, 169, 5, 24, 13, 5, 164, 165, 7, 23, 2, 2, 165, 169, 5, 24, 13, 4, 166, 167, 7, 24, 2, 2, 167, 169, 5, 24, 13, 3, 168, 114, 3, 2, 2, 2, 168, 116, 3, 2, 2, 2, 168, 117, 3, 2, 2, 2, 168, 118, 3, 2, 2, 2, 168, 119, 3, 2, 2, 2, 168, 120, 3, 2, 2, 2, 168, 121, 3, 2, 2, 2, 168, 125, 3, 2, 2, 2, 168, 130, 3, 2, 2, 2, 168, 135, 3, 2, 2, 2, 168, 140, 3, 2, 2, 2, 168, 142, 3, 2, 2, 2, 168, 144, 3, 2, 2, 2, 168, 146, 3, 2, 2, 2, 168, 148, 3, 2, 2, 2, 168, 150, 3, 2, 2, 2, 168, 152, 3, 2, 2, 2, 168, 154, 3, 2, 2, 2, 168, 156, 3, 2, 2, 2, 168, 158, 3, 2, 2, 2, 168, 160, 3, 2, 2, 2, 168, 162, 3, 2, 2, 2, 168, 164, 3, 2, 2, 2, 168, 166, 3, 2, 2, 2, 169, 184, 3, 2, 2, 2, 170, 171, 12, 23, 2, 2, 171, 172, 9, 2, 2, 2, 172, 183, 5, 24, 13, 24, 173, 174, 12, 22, 2, 2, 174, 175, 9, 3, 2, 2, 175, 183, 5, 24, 13, 23, 176, 177, 12, 21, 2, 2, 177, 178, 9, 4, 2, 2, 178, 183, 5, 24, 13, 22, 179, 180, 12, 20, 2, 2, 180, 181, 9, 5, 2, 2, 181, 183, 5, 24, 13, 21, 182, 170, 3, 2, 2, 2, 182, 173, 3, 2, 2, 2, 182, 176, 3, 2, 2, 2, 182, 179, 3, 2, 2, 2, 183, 186, 3, 2, 2, 2, 184, 182, 3, 2, 2, 2, 184, 185, 3, 2, 2, 2, 185, 25, 3, 2, 2, 2, 186, 184, 3, 2, 2, 2, 15, 29, 35, 41, 53, 63, 70, 75, 78, 88, 112, 168, 182, 184] \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.tokens b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.tokens new file mode 100755 index 0000000..a4780f1 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgram.tokens @@ -0,0 +1,112 @@ +T__0=1 +NULL=2 +SELF=3 +TRUE=4 +FALSE=5 +SQRT=6 +SIN=7 +COS=8 +NOT=9 +GETX=10 +GETY=11 +GETRADIUS=12 +GETDIR=13 +GETAP=14 +GETMAXAP=15 +GETHP=16 +SAMETEAM=17 +SEARCHOBJ=18 +DISTANCE=19 +ISWORM=20 +ISFOOD=21 +ISPROJECTILE=22 +TURN=23 +MOVE=24 +JUMP=25 +EAT=26 +FIRE=27 +DEF=28 +IF=29 +INVOKE=30 +THEN=31 +ELSE=32 +WHILE=33 +BREAK=34 +PRINT=35 +ASSIGN=36 +ADD=37 +SUB=38 +MUL=39 +DIV=40 +AND=41 +OR=42 +LT=43 +LTE=44 +GT=45 +GTE=46 +EQ=47 +NEQ=48 +NUMBER=49 +FLOAT=50 +INTEGER=51 +IDENTIFIER=52 +LEFT_PAREN=53 +RIGHT_PAREN=54 +LEFT_BRACE=55 +RIGHT_BRACE=56 +COLON=57 +WHITESPACE=58 +SINGLE_COMMENT=59 +';'=1 +'null'=2 +'self'=3 +'true'=4 +'false'=5 +'sqrt'=6 +'sin'=7 +'cos'=8 +'!'=9 +'getx'=10 +'gety'=11 +'getradius'=12 +'getdir'=13 +'getap'=14 +'getmaxap'=15 +'gethp'=16 +'sameteam'=17 +'searchobj'=18 +'distance'=19 +'isworm'=20 +'isfood'=21 +'isprojectile'=22 +'turn'=23 +'move'=24 +'jump'=25 +'eat'=26 +'fire'=27 +'def'=28 +'if'=29 +'invoke'=30 +'then'=31 +'else'=32 +'while'=33 +'break'=34 +'print'=35 +':='=36 +'+'=37 +'-'=38 +'*'=39 +'/'=40 +'&&'=41 +'||'=42 +'<'=43 +'<='=44 +'>'=45 +'>='=46 +'=='=47 +'!='=48 +'('=53 +')'=54 +'{'=55 +'}'=56 +':'=57 diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramBaseVisitor.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramBaseVisitor.java new file mode 100755 index 0000000..eed84d5 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramBaseVisitor.java @@ -0,0 +1,317 @@ +// Generated from WormsProgram.g4 by ANTLR 4.7.1 + + package worms.programs.internal.parser.generated; + +import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor; + +/** + * This class provides an empty implementation of {@link WormsProgramVisitor}, + * which can be extended to create a visitor which only needs to handle a subset + * of the available methods. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public class WormsProgramBaseVisitor extends AbstractParseTreeVisitor implements WormsProgramVisitor { + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitProgram(WormsProgramParser.ProgramContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitProceduredef(WormsProgramParser.ProceduredefContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitStatement(WormsProgramParser.StatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitAssignmentStatement(WormsProgramParser.AssignmentStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitWhileStatement(WormsProgramParser.WhileStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitIfStatement(WormsProgramParser.IfStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitPrintStatement(WormsProgramParser.PrintStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSequenceStatement(WormsProgramParser.SequenceStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitInvokeStatement(WormsProgramParser.InvokeStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitBreakStatement(WormsProgramParser.BreakStatementContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitTurnAction(WormsProgramParser.TurnActionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitMoveAction(WormsProgramParser.MoveActionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitJumpAction(WormsProgramParser.JumpActionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitEatAction(WormsProgramParser.EatActionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitFireAction(WormsProgramParser.FireActionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitDistanceExpression(WormsProgramParser.DistanceExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitCosExpression(WormsProgramParser.CosExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetYExpression(WormsProgramParser.GetYExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitAndOrExpression(WormsProgramParser.AndOrExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitIsWormExpression(WormsProgramParser.IsWormExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitNotExpression(WormsProgramParser.NotExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitComparisonExpression(WormsProgramParser.ComparisonExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitParenExpression(WormsProgramParser.ParenExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetRadiusExpression(WormsProgramParser.GetRadiusExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitTrueLiteralExpression(WormsProgramParser.TrueLiteralExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitNullExpression(WormsProgramParser.NullExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSqrtExpression(WormsProgramParser.SqrtExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSinExpression(WormsProgramParser.SinExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSameTeamExpression(WormsProgramParser.SameTeamExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitIsProjectileExpression(WormsProgramParser.IsProjectileExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitIsFoodExpression(WormsProgramParser.IsFoodExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitConstantExpression(WormsProgramParser.ConstantExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSearchObjExpression(WormsProgramParser.SearchObjExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetXExpression(WormsProgramParser.GetXExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitReadVariableExpression(WormsProgramParser.ReadVariableExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitMulDivExpression(WormsProgramParser.MulDivExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetDirectionExpression(WormsProgramParser.GetDirectionExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitSelfExpression(WormsProgramParser.SelfExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetHPExpression(WormsProgramParser.GetHPExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitAddSubExpression(WormsProgramParser.AddSubExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetMaxAPExpression(WormsProgramParser.GetMaxAPExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitGetAPExpression(WormsProgramParser.GetAPExpressionContext ctx) { return visitChildren(ctx); } + /** + * {@inheritDoc} + * + *

    The default implementation returns the result of calling + * {@link #visitChildren} on {@code ctx}.

    + */ + @Override public T visitFalseLiteralExpression(WormsProgramParser.FalseLiteralExpressionContext ctx) { return visitChildren(ctx); } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.interp b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.interp new file mode 100755 index 0000000..5386a5e --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.interp @@ -0,0 +1,199 @@ +token literal names: +null +';' +'null' +'self' +'true' +'false' +'sqrt' +'sin' +'cos' +'!' +'getx' +'gety' +'getradius' +'getdir' +'getap' +'getmaxap' +'gethp' +'sameteam' +'searchobj' +'distance' +'isworm' +'isfood' +'isprojectile' +'turn' +'move' +'jump' +'eat' +'fire' +'def' +'if' +'invoke' +'then' +'else' +'while' +'break' +'print' +':=' +'+' +'-' +'*' +'/' +'&&' +'||' +'<' +'<=' +'>' +'>=' +'==' +'!=' +null +null +null +null +'(' +')' +'{' +'}' +':' +null +null + +token symbolic names: +null +null +NULL +SELF +TRUE +FALSE +SQRT +SIN +COS +NOT +GETX +GETY +GETRADIUS +GETDIR +GETAP +GETMAXAP +GETHP +SAMETEAM +SEARCHOBJ +DISTANCE +ISWORM +ISFOOD +ISPROJECTILE +TURN +MOVE +JUMP +EAT +FIRE +DEF +IF +INVOKE +THEN +ELSE +WHILE +BREAK +PRINT +ASSIGN +ADD +SUB +MUL +DIV +AND +OR +LT +LTE +GT +GTE +EQ +NEQ +NUMBER +FLOAT +INTEGER +IDENTIFIER +LEFT_PAREN +RIGHT_PAREN +LEFT_BRACE +RIGHT_BRACE +COLON +WHITESPACE +SINGLE_COMMENT + +rule names: +T__0 +NULL +SELF +TRUE +FALSE +SQRT +SIN +COS +NOT +GETX +GETY +GETRADIUS +GETDIR +GETAP +GETMAXAP +GETHP +SAMETEAM +SEARCHOBJ +DISTANCE +ISWORM +ISFOOD +ISPROJECTILE +TURN +MOVE +JUMP +EAT +FIRE +DEF +IF +INVOKE +THEN +ELSE +WHILE +BREAK +PRINT +ASSIGN +ADD +SUB +MUL +DIV +AND +OR +LT +LTE +GT +GTE +EQ +NEQ +NUMBER +FLOAT +INTEGER +IDENTIFIER +LETTER +LOWER +UPPER +DIGIT +LEFT_PAREN +RIGHT_PAREN +LEFT_BRACE +RIGHT_BRACE +COLON +WHITESPACE +SINGLE_COMMENT +NEWLINE + +channel names: +DEFAULT_TOKEN_CHANNEL +HIDDEN + +mode names: +DEFAULT_MODE + +atn: +[3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 61, 447, 8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7, 9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12, 4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4, 18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23, 9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9, 28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33, 4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4, 39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44, 9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9, 49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54, 4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4, 60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65, 9, 65, 3, 2, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 5, 3, 5, 3, 5, 3, 5, 3, 5, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 6, 3, 7, 3, 7, 3, 7, 3, 7, 3, 7, 3, 8, 3, 8, 3, 8, 3, 8, 3, 9, 3, 9, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11, 3, 11, 3, 11, 3, 11, 3, 12, 3, 12, 3, 12, 3, 12, 3, 12, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 13, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 14, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 15, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 16, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 17, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 18, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 19, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 20, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 21, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 22, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 23, 3, 24, 3, 24, 3, 24, 3, 24, 3, 24, 3, 25, 3, 25, 3, 25, 3, 25, 3, 25, 3, 26, 3, 26, 3, 26, 3, 26, 3, 26, 3, 27, 3, 27, 3, 27, 3, 27, 3, 28, 3, 28, 3, 28, 3, 28, 3, 28, 3, 29, 3, 29, 3, 29, 3, 29, 3, 30, 3, 30, 3, 30, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 36, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 39, 3, 39, 3, 40, 3, 40, 3, 41, 3, 41, 3, 42, 3, 42, 3, 42, 3, 43, 3, 43, 3, 43, 3, 44, 3, 44, 3, 45, 3, 45, 3, 45, 3, 46, 3, 46, 3, 47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 48, 3, 49, 3, 49, 3, 49, 3, 50, 3, 50, 5, 50, 374, 10, 50, 3, 51, 3, 51, 3, 51, 6, 51, 379, 10, 51, 13, 51, 14, 51, 380, 3, 52, 5, 52, 384, 10, 52, 3, 52, 6, 52, 387, 10, 52, 13, 52, 14, 52, 388, 3, 53, 3, 53, 3, 53, 3, 53, 7, 53, 395, 10, 53, 12, 53, 14, 53, 398, 11, 53, 3, 54, 3, 54, 5, 54, 402, 10, 54, 3, 55, 3, 55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 60, 3, 60, 3, 61, 3, 61, 3, 62, 3, 62, 3, 63, 6, 63, 421, 10, 63, 13, 63, 14, 63, 422, 3, 63, 3, 63, 3, 64, 3, 64, 3, 64, 3, 64, 7, 64, 431, 10, 64, 12, 64, 14, 64, 434, 11, 64, 3, 64, 3, 64, 3, 64, 3, 64, 3, 65, 5, 65, 441, 10, 65, 3, 65, 6, 65, 444, 10, 65, 13, 65, 14, 65, 445, 2, 2, 66, 3, 3, 5, 4, 7, 5, 9, 6, 11, 7, 13, 8, 15, 9, 17, 10, 19, 11, 21, 12, 23, 13, 25, 14, 27, 15, 29, 16, 31, 17, 33, 18, 35, 19, 37, 20, 39, 21, 41, 22, 43, 23, 45, 24, 47, 25, 49, 26, 51, 27, 53, 28, 55, 29, 57, 30, 59, 31, 61, 32, 63, 33, 65, 34, 67, 35, 69, 36, 71, 37, 73, 38, 75, 39, 77, 40, 79, 41, 81, 42, 83, 43, 85, 44, 87, 45, 89, 46, 91, 47, 93, 48, 95, 49, 97, 50, 99, 51, 101, 52, 103, 53, 105, 54, 107, 2, 109, 2, 111, 2, 113, 2, 115, 55, 117, 56, 119, 57, 121, 58, 123, 59, 125, 60, 127, 61, 129, 2, 3, 2, 5, 4, 2, 45, 45, 47, 47, 5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 453, 2, 3, 3, 2, 2, 2, 2, 5, 3, 2, 2, 2, 2, 7, 3, 2, 2, 2, 2, 9, 3, 2, 2, 2, 2, 11, 3, 2, 2, 2, 2, 13, 3, 2, 2, 2, 2, 15, 3, 2, 2, 2, 2, 17, 3, 2, 2, 2, 2, 19, 3, 2, 2, 2, 2, 21, 3, 2, 2, 2, 2, 23, 3, 2, 2, 2, 2, 25, 3, 2, 2, 2, 2, 27, 3, 2, 2, 2, 2, 29, 3, 2, 2, 2, 2, 31, 3, 2, 2, 2, 2, 33, 3, 2, 2, 2, 2, 35, 3, 2, 2, 2, 2, 37, 3, 2, 2, 2, 2, 39, 3, 2, 2, 2, 2, 41, 3, 2, 2, 2, 2, 43, 3, 2, 2, 2, 2, 45, 3, 2, 2, 2, 2, 47, 3, 2, 2, 2, 2, 49, 3, 2, 2, 2, 2, 51, 3, 2, 2, 2, 2, 53, 3, 2, 2, 2, 2, 55, 3, 2, 2, 2, 2, 57, 3, 2, 2, 2, 2, 59, 3, 2, 2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3, 2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75, 3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2, 83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2, 2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2, 2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2, 2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127, 3, 2, 2, 2, 3, 131, 3, 2, 2, 2, 5, 133, 3, 2, 2, 2, 7, 138, 3, 2, 2, 2, 9, 143, 3, 2, 2, 2, 11, 148, 3, 2, 2, 2, 13, 154, 3, 2, 2, 2, 15, 159, 3, 2, 2, 2, 17, 163, 3, 2, 2, 2, 19, 167, 3, 2, 2, 2, 21, 169, 3, 2, 2, 2, 23, 174, 3, 2, 2, 2, 25, 179, 3, 2, 2, 2, 27, 189, 3, 2, 2, 2, 29, 196, 3, 2, 2, 2, 31, 202, 3, 2, 2, 2, 33, 211, 3, 2, 2, 2, 35, 217, 3, 2, 2, 2, 37, 226, 3, 2, 2, 2, 39, 236, 3, 2, 2, 2, 41, 245, 3, 2, 2, 2, 43, 252, 3, 2, 2, 2, 45, 259, 3, 2, 2, 2, 47, 272, 3, 2, 2, 2, 49, 277, 3, 2, 2, 2, 51, 282, 3, 2, 2, 2, 53, 287, 3, 2, 2, 2, 55, 291, 3, 2, 2, 2, 57, 296, 3, 2, 2, 2, 59, 300, 3, 2, 2, 2, 61, 303, 3, 2, 2, 2, 63, 310, 3, 2, 2, 2, 65, 315, 3, 2, 2, 2, 67, 320, 3, 2, 2, 2, 69, 326, 3, 2, 2, 2, 71, 332, 3, 2, 2, 2, 73, 338, 3, 2, 2, 2, 75, 341, 3, 2, 2, 2, 77, 343, 3, 2, 2, 2, 79, 345, 3, 2, 2, 2, 81, 347, 3, 2, 2, 2, 83, 349, 3, 2, 2, 2, 85, 352, 3, 2, 2, 2, 87, 355, 3, 2, 2, 2, 89, 357, 3, 2, 2, 2, 91, 360, 3, 2, 2, 2, 93, 362, 3, 2, 2, 2, 95, 365, 3, 2, 2, 2, 97, 368, 3, 2, 2, 2, 99, 373, 3, 2, 2, 2, 101, 375, 3, 2, 2, 2, 103, 383, 3, 2, 2, 2, 105, 390, 3, 2, 2, 2, 107, 401, 3, 2, 2, 2, 109, 403, 3, 2, 2, 2, 111, 405, 3, 2, 2, 2, 113, 407, 3, 2, 2, 2, 115, 409, 3, 2, 2, 2, 117, 411, 3, 2, 2, 2, 119, 413, 3, 2, 2, 2, 121, 415, 3, 2, 2, 2, 123, 417, 3, 2, 2, 2, 125, 420, 3, 2, 2, 2, 127, 426, 3, 2, 2, 2, 129, 443, 3, 2, 2, 2, 131, 132, 7, 61, 2, 2, 132, 4, 3, 2, 2, 2, 133, 134, 7, 112, 2, 2, 134, 135, 7, 119, 2, 2, 135, 136, 7, 110, 2, 2, 136, 137, 7, 110, 2, 2, 137, 6, 3, 2, 2, 2, 138, 139, 7, 117, 2, 2, 139, 140, 7, 103, 2, 2, 140, 141, 7, 110, 2, 2, 141, 142, 7, 104, 2, 2, 142, 8, 3, 2, 2, 2, 143, 144, 7, 118, 2, 2, 144, 145, 7, 116, 2, 2, 145, 146, 7, 119, 2, 2, 146, 147, 7, 103, 2, 2, 147, 10, 3, 2, 2, 2, 148, 149, 7, 104, 2, 2, 149, 150, 7, 99, 2, 2, 150, 151, 7, 110, 2, 2, 151, 152, 7, 117, 2, 2, 152, 153, 7, 103, 2, 2, 153, 12, 3, 2, 2, 2, 154, 155, 7, 117, 2, 2, 155, 156, 7, 115, 2, 2, 156, 157, 7, 116, 2, 2, 157, 158, 7, 118, 2, 2, 158, 14, 3, 2, 2, 2, 159, 160, 7, 117, 2, 2, 160, 161, 7, 107, 2, 2, 161, 162, 7, 112, 2, 2, 162, 16, 3, 2, 2, 2, 163, 164, 7, 101, 2, 2, 164, 165, 7, 113, 2, 2, 165, 166, 7, 117, 2, 2, 166, 18, 3, 2, 2, 2, 167, 168, 7, 35, 2, 2, 168, 20, 3, 2, 2, 2, 169, 170, 7, 105, 2, 2, 170, 171, 7, 103, 2, 2, 171, 172, 7, 118, 2, 2, 172, 173, 7, 122, 2, 2, 173, 22, 3, 2, 2, 2, 174, 175, 7, 105, 2, 2, 175, 176, 7, 103, 2, 2, 176, 177, 7, 118, 2, 2, 177, 178, 7, 123, 2, 2, 178, 24, 3, 2, 2, 2, 179, 180, 7, 105, 2, 2, 180, 181, 7, 103, 2, 2, 181, 182, 7, 118, 2, 2, 182, 183, 7, 116, 2, 2, 183, 184, 7, 99, 2, 2, 184, 185, 7, 102, 2, 2, 185, 186, 7, 107, 2, 2, 186, 187, 7, 119, 2, 2, 187, 188, 7, 117, 2, 2, 188, 26, 3, 2, 2, 2, 189, 190, 7, 105, 2, 2, 190, 191, 7, 103, 2, 2, 191, 192, 7, 118, 2, 2, 192, 193, 7, 102, 2, 2, 193, 194, 7, 107, 2, 2, 194, 195, 7, 116, 2, 2, 195, 28, 3, 2, 2, 2, 196, 197, 7, 105, 2, 2, 197, 198, 7, 103, 2, 2, 198, 199, 7, 118, 2, 2, 199, 200, 7, 99, 2, 2, 200, 201, 7, 114, 2, 2, 201, 30, 3, 2, 2, 2, 202, 203, 7, 105, 2, 2, 203, 204, 7, 103, 2, 2, 204, 205, 7, 118, 2, 2, 205, 206, 7, 111, 2, 2, 206, 207, 7, 99, 2, 2, 207, 208, 7, 122, 2, 2, 208, 209, 7, 99, 2, 2, 209, 210, 7, 114, 2, 2, 210, 32, 3, 2, 2, 2, 211, 212, 7, 105, 2, 2, 212, 213, 7, 103, 2, 2, 213, 214, 7, 118, 2, 2, 214, 215, 7, 106, 2, 2, 215, 216, 7, 114, 2, 2, 216, 34, 3, 2, 2, 2, 217, 218, 7, 117, 2, 2, 218, 219, 7, 99, 2, 2, 219, 220, 7, 111, 2, 2, 220, 221, 7, 103, 2, 2, 221, 222, 7, 118, 2, 2, 222, 223, 7, 103, 2, 2, 223, 224, 7, 99, 2, 2, 224, 225, 7, 111, 2, 2, 225, 36, 3, 2, 2, 2, 226, 227, 7, 117, 2, 2, 227, 228, 7, 103, 2, 2, 228, 229, 7, 99, 2, 2, 229, 230, 7, 116, 2, 2, 230, 231, 7, 101, 2, 2, 231, 232, 7, 106, 2, 2, 232, 233, 7, 113, 2, 2, 233, 234, 7, 100, 2, 2, 234, 235, 7, 108, 2, 2, 235, 38, 3, 2, 2, 2, 236, 237, 7, 102, 2, 2, 237, 238, 7, 107, 2, 2, 238, 239, 7, 117, 2, 2, 239, 240, 7, 118, 2, 2, 240, 241, 7, 99, 2, 2, 241, 242, 7, 112, 2, 2, 242, 243, 7, 101, 2, 2, 243, 244, 7, 103, 2, 2, 244, 40, 3, 2, 2, 2, 245, 246, 7, 107, 2, 2, 246, 247, 7, 117, 2, 2, 247, 248, 7, 121, 2, 2, 248, 249, 7, 113, 2, 2, 249, 250, 7, 116, 2, 2, 250, 251, 7, 111, 2, 2, 251, 42, 3, 2, 2, 2, 252, 253, 7, 107, 2, 2, 253, 254, 7, 117, 2, 2, 254, 255, 7, 104, 2, 2, 255, 256, 7, 113, 2, 2, 256, 257, 7, 113, 2, 2, 257, 258, 7, 102, 2, 2, 258, 44, 3, 2, 2, 2, 259, 260, 7, 107, 2, 2, 260, 261, 7, 117, 2, 2, 261, 262, 7, 114, 2, 2, 262, 263, 7, 116, 2, 2, 263, 264, 7, 113, 2, 2, 264, 265, 7, 108, 2, 2, 265, 266, 7, 103, 2, 2, 266, 267, 7, 101, 2, 2, 267, 268, 7, 118, 2, 2, 268, 269, 7, 107, 2, 2, 269, 270, 7, 110, 2, 2, 270, 271, 7, 103, 2, 2, 271, 46, 3, 2, 2, 2, 272, 273, 7, 118, 2, 2, 273, 274, 7, 119, 2, 2, 274, 275, 7, 116, 2, 2, 275, 276, 7, 112, 2, 2, 276, 48, 3, 2, 2, 2, 277, 278, 7, 111, 2, 2, 278, 279, 7, 113, 2, 2, 279, 280, 7, 120, 2, 2, 280, 281, 7, 103, 2, 2, 281, 50, 3, 2, 2, 2, 282, 283, 7, 108, 2, 2, 283, 284, 7, 119, 2, 2, 284, 285, 7, 111, 2, 2, 285, 286, 7, 114, 2, 2, 286, 52, 3, 2, 2, 2, 287, 288, 7, 103, 2, 2, 288, 289, 7, 99, 2, 2, 289, 290, 7, 118, 2, 2, 290, 54, 3, 2, 2, 2, 291, 292, 7, 104, 2, 2, 292, 293, 7, 107, 2, 2, 293, 294, 7, 116, 2, 2, 294, 295, 7, 103, 2, 2, 295, 56, 3, 2, 2, 2, 296, 297, 7, 102, 2, 2, 297, 298, 7, 103, 2, 2, 298, 299, 7, 104, 2, 2, 299, 58, 3, 2, 2, 2, 300, 301, 7, 107, 2, 2, 301, 302, 7, 104, 2, 2, 302, 60, 3, 2, 2, 2, 303, 304, 7, 107, 2, 2, 304, 305, 7, 112, 2, 2, 305, 306, 7, 120, 2, 2, 306, 307, 7, 113, 2, 2, 307, 308, 7, 109, 2, 2, 308, 309, 7, 103, 2, 2, 309, 62, 3, 2, 2, 2, 310, 311, 7, 118, 2, 2, 311, 312, 7, 106, 2, 2, 312, 313, 7, 103, 2, 2, 313, 314, 7, 112, 2, 2, 314, 64, 3, 2, 2, 2, 315, 316, 7, 103, 2, 2, 316, 317, 7, 110, 2, 2, 317, 318, 7, 117, 2, 2, 318, 319, 7, 103, 2, 2, 319, 66, 3, 2, 2, 2, 320, 321, 7, 121, 2, 2, 321, 322, 7, 106, 2, 2, 322, 323, 7, 107, 2, 2, 323, 324, 7, 110, 2, 2, 324, 325, 7, 103, 2, 2, 325, 68, 3, 2, 2, 2, 326, 327, 7, 100, 2, 2, 327, 328, 7, 116, 2, 2, 328, 329, 7, 103, 2, 2, 329, 330, 7, 99, 2, 2, 330, 331, 7, 109, 2, 2, 331, 70, 3, 2, 2, 2, 332, 333, 7, 114, 2, 2, 333, 334, 7, 116, 2, 2, 334, 335, 7, 107, 2, 2, 335, 336, 7, 112, 2, 2, 336, 337, 7, 118, 2, 2, 337, 72, 3, 2, 2, 2, 338, 339, 7, 60, 2, 2, 339, 340, 7, 63, 2, 2, 340, 74, 3, 2, 2, 2, 341, 342, 7, 45, 2, 2, 342, 76, 3, 2, 2, 2, 343, 344, 7, 47, 2, 2, 344, 78, 3, 2, 2, 2, 345, 346, 7, 44, 2, 2, 346, 80, 3, 2, 2, 2, 347, 348, 7, 49, 2, 2, 348, 82, 3, 2, 2, 2, 349, 350, 7, 40, 2, 2, 350, 351, 7, 40, 2, 2, 351, 84, 3, 2, 2, 2, 352, 353, 7, 126, 2, 2, 353, 354, 7, 126, 2, 2, 354, 86, 3, 2, 2, 2, 355, 356, 7, 62, 2, 2, 356, 88, 3, 2, 2, 2, 357, 358, 7, 62, 2, 2, 358, 359, 7, 63, 2, 2, 359, 90, 3, 2, 2, 2, 360, 361, 7, 64, 2, 2, 361, 92, 3, 2, 2, 2, 362, 363, 7, 64, 2, 2, 363, 364, 7, 63, 2, 2, 364, 94, 3, 2, 2, 2, 365, 366, 7, 63, 2, 2, 366, 367, 7, 63, 2, 2, 367, 96, 3, 2, 2, 2, 368, 369, 7, 35, 2, 2, 369, 370, 7, 63, 2, 2, 370, 98, 3, 2, 2, 2, 371, 374, 5, 103, 52, 2, 372, 374, 5, 101, 51, 2, 373, 371, 3, 2, 2, 2, 373, 372, 3, 2, 2, 2, 374, 100, 3, 2, 2, 2, 375, 376, 5, 103, 52, 2, 376, 378, 7, 48, 2, 2, 377, 379, 4, 50, 59, 2, 378, 377, 3, 2, 2, 2, 379, 380, 3, 2, 2, 2, 380, 378, 3, 2, 2, 2, 380, 381, 3, 2, 2, 2, 381, 102, 3, 2, 2, 2, 382, 384, 9, 2, 2, 2, 383, 382, 3, 2, 2, 2, 383, 384, 3, 2, 2, 2, 384, 386, 3, 2, 2, 2, 385, 387, 4, 50, 59, 2, 386, 385, 3, 2, 2, 2, 387, 388, 3, 2, 2, 2, 388, 386, 3, 2, 2, 2, 388, 389, 3, 2, 2, 2, 389, 104, 3, 2, 2, 2, 390, 396, 5, 107, 54, 2, 391, 395, 5, 107, 54, 2, 392, 395, 5, 113, 57, 2, 393, 395, 7, 97, 2, 2, 394, 391, 3, 2, 2, 2, 394, 392, 3, 2, 2, 2, 394, 393, 3, 2, 2, 2, 395, 398, 3, 2, 2, 2, 396, 394, 3, 2, 2, 2, 396, 397, 3, 2, 2, 2, 397, 106, 3, 2, 2, 2, 398, 396, 3, 2, 2, 2, 399, 402, 5, 109, 55, 2, 400, 402, 5, 111, 56, 2, 401, 399, 3, 2, 2, 2, 401, 400, 3, 2, 2, 2, 402, 108, 3, 2, 2, 2, 403, 404, 4, 99, 124, 2, 404, 110, 3, 2, 2, 2, 405, 406, 4, 67, 92, 2, 406, 112, 3, 2, 2, 2, 407, 408, 4, 50, 59, 2, 408, 114, 3, 2, 2, 2, 409, 410, 7, 42, 2, 2, 410, 116, 3, 2, 2, 2, 411, 412, 7, 43, 2, 2, 412, 118, 3, 2, 2, 2, 413, 414, 7, 125, 2, 2, 414, 120, 3, 2, 2, 2, 415, 416, 7, 127, 2, 2, 416, 122, 3, 2, 2, 2, 417, 418, 7, 60, 2, 2, 418, 124, 3, 2, 2, 2, 419, 421, 9, 3, 2, 2, 420, 419, 3, 2, 2, 2, 421, 422, 3, 2, 2, 2, 422, 420, 3, 2, 2, 2, 422, 423, 3, 2, 2, 2, 423, 424, 3, 2, 2, 2, 424, 425, 8, 63, 2, 2, 425, 126, 3, 2, 2, 2, 426, 427, 7, 49, 2, 2, 427, 428, 7, 49, 2, 2, 428, 432, 3, 2, 2, 2, 429, 431, 10, 4, 2, 2, 430, 429, 3, 2, 2, 2, 431, 434, 3, 2, 2, 2, 432, 430, 3, 2, 2, 2, 432, 433, 3, 2, 2, 2, 433, 435, 3, 2, 2, 2, 434, 432, 3, 2, 2, 2, 435, 436, 5, 129, 65, 2, 436, 437, 3, 2, 2, 2, 437, 438, 8, 64, 2, 2, 438, 128, 3, 2, 2, 2, 439, 441, 7, 15, 2, 2, 440, 439, 3, 2, 2, 2, 440, 441, 3, 2, 2, 2, 441, 442, 3, 2, 2, 2, 442, 444, 7, 12, 2, 2, 443, 440, 3, 2, 2, 2, 444, 445, 3, 2, 2, 2, 445, 443, 3, 2, 2, 2, 445, 446, 3, 2, 2, 2, 446, 130, 3, 2, 2, 2, 14, 2, 373, 380, 383, 388, 394, 396, 401, 422, 432, 440, 445, 3, 8, 2, 2] \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.java new file mode 100755 index 0000000..6f3be40 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.java @@ -0,0 +1,280 @@ +// Generated from WormsProgram.g4 by ANTLR 4.7.1 + + package worms.programs.internal.parser.generated; + +import org.antlr.v4.runtime.Lexer; +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenStream; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.misc.*; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class WormsProgramLexer extends Lexer { + static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, NULL=2, SELF=3, TRUE=4, FALSE=5, SQRT=6, SIN=7, COS=8, NOT=9, + GETX=10, GETY=11, GETRADIUS=12, GETDIR=13, GETAP=14, GETMAXAP=15, GETHP=16, + SAMETEAM=17, SEARCHOBJ=18, DISTANCE=19, ISWORM=20, ISFOOD=21, ISPROJECTILE=22, + TURN=23, MOVE=24, JUMP=25, EAT=26, FIRE=27, DEF=28, IF=29, INVOKE=30, + THEN=31, ELSE=32, WHILE=33, BREAK=34, PRINT=35, ASSIGN=36, ADD=37, SUB=38, + MUL=39, DIV=40, AND=41, OR=42, LT=43, LTE=44, GT=45, GTE=46, EQ=47, NEQ=48, + NUMBER=49, FLOAT=50, INTEGER=51, IDENTIFIER=52, LEFT_PAREN=53, RIGHT_PAREN=54, + LEFT_BRACE=55, RIGHT_BRACE=56, COLON=57, WHITESPACE=58, SINGLE_COMMENT=59; + public static String[] channelNames = { + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" + }; + + public static String[] modeNames = { + "DEFAULT_MODE" + }; + + public static final String[] ruleNames = { + "T__0", "NULL", "SELF", "TRUE", "FALSE", "SQRT", "SIN", "COS", "NOT", + "GETX", "GETY", "GETRADIUS", "GETDIR", "GETAP", "GETMAXAP", "GETHP", "SAMETEAM", + "SEARCHOBJ", "DISTANCE", "ISWORM", "ISFOOD", "ISPROJECTILE", "TURN", "MOVE", + "JUMP", "EAT", "FIRE", "DEF", "IF", "INVOKE", "THEN", "ELSE", "WHILE", + "BREAK", "PRINT", "ASSIGN", "ADD", "SUB", "MUL", "DIV", "AND", "OR", "LT", + "LTE", "GT", "GTE", "EQ", "NEQ", "NUMBER", "FLOAT", "INTEGER", "IDENTIFIER", + "LETTER", "LOWER", "UPPER", "DIGIT", "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", + "RIGHT_BRACE", "COLON", "WHITESPACE", "SINGLE_COMMENT", "NEWLINE" + }; + + private static final String[] _LITERAL_NAMES = { + null, "';'", "'null'", "'self'", "'true'", "'false'", "'sqrt'", "'sin'", + "'cos'", "'!'", "'getx'", "'gety'", "'getradius'", "'getdir'", "'getap'", + "'getmaxap'", "'gethp'", "'sameteam'", "'searchobj'", "'distance'", "'isworm'", + "'isfood'", "'isprojectile'", "'turn'", "'move'", "'jump'", "'eat'", "'fire'", + "'def'", "'if'", "'invoke'", "'then'", "'else'", "'while'", "'break'", + "'print'", "':='", "'+'", "'-'", "'*'", "'/'", "'&&'", "'||'", "'<'", + "'<='", "'>'", "'>='", "'=='", "'!='", null, null, null, null, "'('", + "')'", "'{'", "'}'", "':'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, "NULL", "SELF", "TRUE", "FALSE", "SQRT", "SIN", "COS", "NOT", + "GETX", "GETY", "GETRADIUS", "GETDIR", "GETAP", "GETMAXAP", "GETHP", "SAMETEAM", + "SEARCHOBJ", "DISTANCE", "ISWORM", "ISFOOD", "ISPROJECTILE", "TURN", "MOVE", + "JUMP", "EAT", "FIRE", "DEF", "IF", "INVOKE", "THEN", "ELSE", "WHILE", + "BREAK", "PRINT", "ASSIGN", "ADD", "SUB", "MUL", "DIV", "AND", "OR", "LT", + "LTE", "GT", "GTE", "EQ", "NEQ", "NUMBER", "FLOAT", "INTEGER", "IDENTIFIER", + "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "COLON", "WHITESPACE", + "SINGLE_COMMENT" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + + public WormsProgramLexer(CharStream input) { + super(input); + _interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + + @Override + public String getGrammarFileName() { return "WormsProgram.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public String[] getChannelNames() { return channelNames; } + + @Override + public String[] getModeNames() { return modeNames; } + + @Override + public ATN getATN() { return _ATN; } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2=\u01bf\b\1\4\2\t"+ + "\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+ + "\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+ + "\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+ + "\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+ + "\t!\4\"\t\"\4#\t#\4$\t$\4%\t%\4&\t&\4\'\t\'\4(\t(\4)\t)\4*\t*\4+\t+\4"+ + ",\t,\4-\t-\4.\t.\4/\t/\4\60\t\60\4\61\t\61\4\62\t\62\4\63\t\63\4\64\t"+ + "\64\4\65\t\65\4\66\t\66\4\67\t\67\48\t8\49\t9\4:\t:\4;\t;\4<\t<\4=\t="+ + "\4>\t>\4?\t?\4@\t@\4A\tA\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\3\4\3"+ + "\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\3\6\3\6\3\6\3\7\3\7\3\7\3\7\3\7\3\b"+ + "\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\f\3\f"+ + "\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16\3\16\3\16\3"+ + "\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3"+ + "\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21\3\21\3\21\3\22\3\22\3\22\3"+ + "\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3\23\3"+ + "\23\3\23\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3"+ + "\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27\3\27\3\27\3"+ + "\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3"+ + "\30\3\31\3\31\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3"+ + "\33\3\34\3\34\3\34\3\34\3\34\3\35\3\35\3\35\3\35\3\36\3\36\3\36\3\37\3"+ + "\37\3\37\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \3!\3!\3!\3!\3!\3\"\3\"\3\""+ + "\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3$\3%\3%\3%\3&\3&\3\'\3"+ + "\'\3(\3(\3)\3)\3*\3*\3*\3+\3+\3+\3,\3,\3-\3-\3-\3.\3.\3/\3/\3/\3\60\3"+ + "\60\3\60\3\61\3\61\3\61\3\62\3\62\5\62\u0176\n\62\3\63\3\63\3\63\6\63"+ + "\u017b\n\63\r\63\16\63\u017c\3\64\5\64\u0180\n\64\3\64\6\64\u0183\n\64"+ + "\r\64\16\64\u0184\3\65\3\65\3\65\3\65\7\65\u018b\n\65\f\65\16\65\u018e"+ + "\13\65\3\66\3\66\5\66\u0192\n\66\3\67\3\67\38\38\39\39\3:\3:\3;\3;\3<"+ + "\3<\3=\3=\3>\3>\3?\6?\u01a5\n?\r?\16?\u01a6\3?\3?\3@\3@\3@\3@\7@\u01af"+ + "\n@\f@\16@\u01b2\13@\3@\3@\3@\3@\3A\5A\u01b9\nA\3A\6A\u01bc\nA\rA\16A"+ + "\u01bd\2\2B\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33"+ + "\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67"+ + "\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\62c\63e\64g\65"+ + "i\66k\2m\2o\2q\2s\67u8w9y:{;}<\177=\u0081\2\3\2\5\4\2--//\5\2\13\f\17"+ + "\17\"\"\4\2\f\f\17\17\2\u01c5\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t"+ + "\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2"+ + "\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2"+ + "\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2"+ + "+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2"+ + "\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2"+ + "C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3"+ + "\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2"+ + "\2\2]\3\2\2\2\2_\3\2\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2"+ + "i\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2{\3\2\2\2\2}\3"+ + "\2\2\2\2\177\3\2\2\2\3\u0083\3\2\2\2\5\u0085\3\2\2\2\7\u008a\3\2\2\2\t"+ + "\u008f\3\2\2\2\13\u0094\3\2\2\2\r\u009a\3\2\2\2\17\u009f\3\2\2\2\21\u00a3"+ + "\3\2\2\2\23\u00a7\3\2\2\2\25\u00a9\3\2\2\2\27\u00ae\3\2\2\2\31\u00b3\3"+ + "\2\2\2\33\u00bd\3\2\2\2\35\u00c4\3\2\2\2\37\u00ca\3\2\2\2!\u00d3\3\2\2"+ + "\2#\u00d9\3\2\2\2%\u00e2\3\2\2\2\'\u00ec\3\2\2\2)\u00f5\3\2\2\2+\u00fc"+ + "\3\2\2\2-\u0103\3\2\2\2/\u0110\3\2\2\2\61\u0115\3\2\2\2\63\u011a\3\2\2"+ + "\2\65\u011f\3\2\2\2\67\u0123\3\2\2\29\u0128\3\2\2\2;\u012c\3\2\2\2=\u012f"+ + "\3\2\2\2?\u0136\3\2\2\2A\u013b\3\2\2\2C\u0140\3\2\2\2E\u0146\3\2\2\2G"+ + "\u014c\3\2\2\2I\u0152\3\2\2\2K\u0155\3\2\2\2M\u0157\3\2\2\2O\u0159\3\2"+ + "\2\2Q\u015b\3\2\2\2S\u015d\3\2\2\2U\u0160\3\2\2\2W\u0163\3\2\2\2Y\u0165"+ + "\3\2\2\2[\u0168\3\2\2\2]\u016a\3\2\2\2_\u016d\3\2\2\2a\u0170\3\2\2\2c"+ + "\u0175\3\2\2\2e\u0177\3\2\2\2g\u017f\3\2\2\2i\u0186\3\2\2\2k\u0191\3\2"+ + "\2\2m\u0193\3\2\2\2o\u0195\3\2\2\2q\u0197\3\2\2\2s\u0199\3\2\2\2u\u019b"+ + "\3\2\2\2w\u019d\3\2\2\2y\u019f\3\2\2\2{\u01a1\3\2\2\2}\u01a4\3\2\2\2\177"+ + "\u01aa\3\2\2\2\u0081\u01bb\3\2\2\2\u0083\u0084\7=\2\2\u0084\4\3\2\2\2"+ + "\u0085\u0086\7p\2\2\u0086\u0087\7w\2\2\u0087\u0088\7n\2\2\u0088\u0089"+ + "\7n\2\2\u0089\6\3\2\2\2\u008a\u008b\7u\2\2\u008b\u008c\7g\2\2\u008c\u008d"+ + "\7n\2\2\u008d\u008e\7h\2\2\u008e\b\3\2\2\2\u008f\u0090\7v\2\2\u0090\u0091"+ + "\7t\2\2\u0091\u0092\7w\2\2\u0092\u0093\7g\2\2\u0093\n\3\2\2\2\u0094\u0095"+ + "\7h\2\2\u0095\u0096\7c\2\2\u0096\u0097\7n\2\2\u0097\u0098\7u\2\2\u0098"+ + "\u0099\7g\2\2\u0099\f\3\2\2\2\u009a\u009b\7u\2\2\u009b\u009c\7s\2\2\u009c"+ + "\u009d\7t\2\2\u009d\u009e\7v\2\2\u009e\16\3\2\2\2\u009f\u00a0\7u\2\2\u00a0"+ + "\u00a1\7k\2\2\u00a1\u00a2\7p\2\2\u00a2\20\3\2\2\2\u00a3\u00a4\7e\2\2\u00a4"+ + "\u00a5\7q\2\2\u00a5\u00a6\7u\2\2\u00a6\22\3\2\2\2\u00a7\u00a8\7#\2\2\u00a8"+ + "\24\3\2\2\2\u00a9\u00aa\7i\2\2\u00aa\u00ab\7g\2\2\u00ab\u00ac\7v\2\2\u00ac"+ + "\u00ad\7z\2\2\u00ad\26\3\2\2\2\u00ae\u00af\7i\2\2\u00af\u00b0\7g\2\2\u00b0"+ + "\u00b1\7v\2\2\u00b1\u00b2\7{\2\2\u00b2\30\3\2\2\2\u00b3\u00b4\7i\2\2\u00b4"+ + "\u00b5\7g\2\2\u00b5\u00b6\7v\2\2\u00b6\u00b7\7t\2\2\u00b7\u00b8\7c\2\2"+ + "\u00b8\u00b9\7f\2\2\u00b9\u00ba\7k\2\2\u00ba\u00bb\7w\2\2\u00bb\u00bc"+ + "\7u\2\2\u00bc\32\3\2\2\2\u00bd\u00be\7i\2\2\u00be\u00bf\7g\2\2\u00bf\u00c0"+ + "\7v\2\2\u00c0\u00c1\7f\2\2\u00c1\u00c2\7k\2\2\u00c2\u00c3\7t\2\2\u00c3"+ + "\34\3\2\2\2\u00c4\u00c5\7i\2\2\u00c5\u00c6\7g\2\2\u00c6\u00c7\7v\2\2\u00c7"+ + "\u00c8\7c\2\2\u00c8\u00c9\7r\2\2\u00c9\36\3\2\2\2\u00ca\u00cb\7i\2\2\u00cb"+ + "\u00cc\7g\2\2\u00cc\u00cd\7v\2\2\u00cd\u00ce\7o\2\2\u00ce\u00cf\7c\2\2"+ + "\u00cf\u00d0\7z\2\2\u00d0\u00d1\7c\2\2\u00d1\u00d2\7r\2\2\u00d2 \3\2\2"+ + "\2\u00d3\u00d4\7i\2\2\u00d4\u00d5\7g\2\2\u00d5\u00d6\7v\2\2\u00d6\u00d7"+ + "\7j\2\2\u00d7\u00d8\7r\2\2\u00d8\"\3\2\2\2\u00d9\u00da\7u\2\2\u00da\u00db"+ + "\7c\2\2\u00db\u00dc\7o\2\2\u00dc\u00dd\7g\2\2\u00dd\u00de\7v\2\2\u00de"+ + "\u00df\7g\2\2\u00df\u00e0\7c\2\2\u00e0\u00e1\7o\2\2\u00e1$\3\2\2\2\u00e2"+ + "\u00e3\7u\2\2\u00e3\u00e4\7g\2\2\u00e4\u00e5\7c\2\2\u00e5\u00e6\7t\2\2"+ + "\u00e6\u00e7\7e\2\2\u00e7\u00e8\7j\2\2\u00e8\u00e9\7q\2\2\u00e9\u00ea"+ + "\7d\2\2\u00ea\u00eb\7l\2\2\u00eb&\3\2\2\2\u00ec\u00ed\7f\2\2\u00ed\u00ee"+ + "\7k\2\2\u00ee\u00ef\7u\2\2\u00ef\u00f0\7v\2\2\u00f0\u00f1\7c\2\2\u00f1"+ + "\u00f2\7p\2\2\u00f2\u00f3\7e\2\2\u00f3\u00f4\7g\2\2\u00f4(\3\2\2\2\u00f5"+ + "\u00f6\7k\2\2\u00f6\u00f7\7u\2\2\u00f7\u00f8\7y\2\2\u00f8\u00f9\7q\2\2"+ + "\u00f9\u00fa\7t\2\2\u00fa\u00fb\7o\2\2\u00fb*\3\2\2\2\u00fc\u00fd\7k\2"+ + "\2\u00fd\u00fe\7u\2\2\u00fe\u00ff\7h\2\2\u00ff\u0100\7q\2\2\u0100\u0101"+ + "\7q\2\2\u0101\u0102\7f\2\2\u0102,\3\2\2\2\u0103\u0104\7k\2\2\u0104\u0105"+ + "\7u\2\2\u0105\u0106\7r\2\2\u0106\u0107\7t\2\2\u0107\u0108\7q\2\2\u0108"+ + "\u0109\7l\2\2\u0109\u010a\7g\2\2\u010a\u010b\7e\2\2\u010b\u010c\7v\2\2"+ + "\u010c\u010d\7k\2\2\u010d\u010e\7n\2\2\u010e\u010f\7g\2\2\u010f.\3\2\2"+ + "\2\u0110\u0111\7v\2\2\u0111\u0112\7w\2\2\u0112\u0113\7t\2\2\u0113\u0114"+ + "\7p\2\2\u0114\60\3\2\2\2\u0115\u0116\7o\2\2\u0116\u0117\7q\2\2\u0117\u0118"+ + "\7x\2\2\u0118\u0119\7g\2\2\u0119\62\3\2\2\2\u011a\u011b\7l\2\2\u011b\u011c"+ + "\7w\2\2\u011c\u011d\7o\2\2\u011d\u011e\7r\2\2\u011e\64\3\2\2\2\u011f\u0120"+ + "\7g\2\2\u0120\u0121\7c\2\2\u0121\u0122\7v\2\2\u0122\66\3\2\2\2\u0123\u0124"+ + "\7h\2\2\u0124\u0125\7k\2\2\u0125\u0126\7t\2\2\u0126\u0127\7g\2\2\u0127"+ + "8\3\2\2\2\u0128\u0129\7f\2\2\u0129\u012a\7g\2\2\u012a\u012b\7h\2\2\u012b"+ + ":\3\2\2\2\u012c\u012d\7k\2\2\u012d\u012e\7h\2\2\u012e<\3\2\2\2\u012f\u0130"+ + "\7k\2\2\u0130\u0131\7p\2\2\u0131\u0132\7x\2\2\u0132\u0133\7q\2\2\u0133"+ + "\u0134\7m\2\2\u0134\u0135\7g\2\2\u0135>\3\2\2\2\u0136\u0137\7v\2\2\u0137"+ + "\u0138\7j\2\2\u0138\u0139\7g\2\2\u0139\u013a\7p\2\2\u013a@\3\2\2\2\u013b"+ + "\u013c\7g\2\2\u013c\u013d\7n\2\2\u013d\u013e\7u\2\2\u013e\u013f\7g\2\2"+ + "\u013fB\3\2\2\2\u0140\u0141\7y\2\2\u0141\u0142\7j\2\2\u0142\u0143\7k\2"+ + "\2\u0143\u0144\7n\2\2\u0144\u0145\7g\2\2\u0145D\3\2\2\2\u0146\u0147\7"+ + "d\2\2\u0147\u0148\7t\2\2\u0148\u0149\7g\2\2\u0149\u014a\7c\2\2\u014a\u014b"+ + "\7m\2\2\u014bF\3\2\2\2\u014c\u014d\7r\2\2\u014d\u014e\7t\2\2\u014e\u014f"+ + "\7k\2\2\u014f\u0150\7p\2\2\u0150\u0151\7v\2\2\u0151H\3\2\2\2\u0152\u0153"+ + "\7<\2\2\u0153\u0154\7?\2\2\u0154J\3\2\2\2\u0155\u0156\7-\2\2\u0156L\3"+ + "\2\2\2\u0157\u0158\7/\2\2\u0158N\3\2\2\2\u0159\u015a\7,\2\2\u015aP\3\2"+ + "\2\2\u015b\u015c\7\61\2\2\u015cR\3\2\2\2\u015d\u015e\7(\2\2\u015e\u015f"+ + "\7(\2\2\u015fT\3\2\2\2\u0160\u0161\7~\2\2\u0161\u0162\7~\2\2\u0162V\3"+ + "\2\2\2\u0163\u0164\7>\2\2\u0164X\3\2\2\2\u0165\u0166\7>\2\2\u0166\u0167"+ + "\7?\2\2\u0167Z\3\2\2\2\u0168\u0169\7@\2\2\u0169\\\3\2\2\2\u016a\u016b"+ + "\7@\2\2\u016b\u016c\7?\2\2\u016c^\3\2\2\2\u016d\u016e\7?\2\2\u016e\u016f"+ + "\7?\2\2\u016f`\3\2\2\2\u0170\u0171\7#\2\2\u0171\u0172\7?\2\2\u0172b\3"+ + "\2\2\2\u0173\u0176\5g\64\2\u0174\u0176\5e\63\2\u0175\u0173\3\2\2\2\u0175"+ + "\u0174\3\2\2\2\u0176d\3\2\2\2\u0177\u0178\5g\64\2\u0178\u017a\7\60\2\2"+ + "\u0179\u017b\4\62;\2\u017a\u0179\3\2\2\2\u017b\u017c\3\2\2\2\u017c\u017a"+ + "\3\2\2\2\u017c\u017d\3\2\2\2\u017df\3\2\2\2\u017e\u0180\t\2\2\2\u017f"+ + "\u017e\3\2\2\2\u017f\u0180\3\2\2\2\u0180\u0182\3\2\2\2\u0181\u0183\4\62"+ + ";\2\u0182\u0181\3\2\2\2\u0183\u0184\3\2\2\2\u0184\u0182\3\2\2\2\u0184"+ + "\u0185\3\2\2\2\u0185h\3\2\2\2\u0186\u018c\5k\66\2\u0187\u018b\5k\66\2"+ + "\u0188\u018b\5q9\2\u0189\u018b\7a\2\2\u018a\u0187\3\2\2\2\u018a\u0188"+ + "\3\2\2\2\u018a\u0189\3\2\2\2\u018b\u018e\3\2\2\2\u018c\u018a\3\2\2\2\u018c"+ + "\u018d\3\2\2\2\u018dj\3\2\2\2\u018e\u018c\3\2\2\2\u018f\u0192\5m\67\2"+ + "\u0190\u0192\5o8\2\u0191\u018f\3\2\2\2\u0191\u0190\3\2\2\2\u0192l\3\2"+ + "\2\2\u0193\u0194\4c|\2\u0194n\3\2\2\2\u0195\u0196\4C\\\2\u0196p\3\2\2"+ + "\2\u0197\u0198\4\62;\2\u0198r\3\2\2\2\u0199\u019a\7*\2\2\u019at\3\2\2"+ + "\2\u019b\u019c\7+\2\2\u019cv\3\2\2\2\u019d\u019e\7}\2\2\u019ex\3\2\2\2"+ + "\u019f\u01a0\7\177\2\2\u01a0z\3\2\2\2\u01a1\u01a2\7<\2\2\u01a2|\3\2\2"+ + "\2\u01a3\u01a5\t\3\2\2\u01a4\u01a3\3\2\2\2\u01a5\u01a6\3\2\2\2\u01a6\u01a4"+ + "\3\2\2\2\u01a6\u01a7\3\2\2\2\u01a7\u01a8\3\2\2\2\u01a8\u01a9\b?\2\2\u01a9"+ + "~\3\2\2\2\u01aa\u01ab\7\61\2\2\u01ab\u01ac\7\61\2\2\u01ac\u01b0\3\2\2"+ + "\2\u01ad\u01af\n\4\2\2\u01ae\u01ad\3\2\2\2\u01af\u01b2\3\2\2\2\u01b0\u01ae"+ + "\3\2\2\2\u01b0\u01b1\3\2\2\2\u01b1\u01b3\3\2\2\2\u01b2\u01b0\3\2\2\2\u01b3"+ + "\u01b4\5\u0081A\2\u01b4\u01b5\3\2\2\2\u01b5\u01b6\b@\2\2\u01b6\u0080\3"+ + "\2\2\2\u01b7\u01b9\7\17\2\2\u01b8\u01b7\3\2\2\2\u01b8\u01b9\3\2\2\2\u01b9"+ + "\u01ba\3\2\2\2\u01ba\u01bc\7\f\2\2\u01bb\u01b8\3\2\2\2\u01bc\u01bd\3\2"+ + "\2\2\u01bd\u01bb\3\2\2\2\u01bd\u01be\3\2\2\2\u01be\u0082\3\2\2\2\16\2"+ + "\u0175\u017c\u017f\u0184\u018a\u018c\u0191\u01a6\u01b0\u01b8\u01bd\3\b"+ + "\2\2"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.tokens b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.tokens new file mode 100755 index 0000000..a4780f1 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramLexer.tokens @@ -0,0 +1,112 @@ +T__0=1 +NULL=2 +SELF=3 +TRUE=4 +FALSE=5 +SQRT=6 +SIN=7 +COS=8 +NOT=9 +GETX=10 +GETY=11 +GETRADIUS=12 +GETDIR=13 +GETAP=14 +GETMAXAP=15 +GETHP=16 +SAMETEAM=17 +SEARCHOBJ=18 +DISTANCE=19 +ISWORM=20 +ISFOOD=21 +ISPROJECTILE=22 +TURN=23 +MOVE=24 +JUMP=25 +EAT=26 +FIRE=27 +DEF=28 +IF=29 +INVOKE=30 +THEN=31 +ELSE=32 +WHILE=33 +BREAK=34 +PRINT=35 +ASSIGN=36 +ADD=37 +SUB=38 +MUL=39 +DIV=40 +AND=41 +OR=42 +LT=43 +LTE=44 +GT=45 +GTE=46 +EQ=47 +NEQ=48 +NUMBER=49 +FLOAT=50 +INTEGER=51 +IDENTIFIER=52 +LEFT_PAREN=53 +RIGHT_PAREN=54 +LEFT_BRACE=55 +RIGHT_BRACE=56 +COLON=57 +WHITESPACE=58 +SINGLE_COMMENT=59 +';'=1 +'null'=2 +'self'=3 +'true'=4 +'false'=5 +'sqrt'=6 +'sin'=7 +'cos'=8 +'!'=9 +'getx'=10 +'gety'=11 +'getradius'=12 +'getdir'=13 +'getap'=14 +'getmaxap'=15 +'gethp'=16 +'sameteam'=17 +'searchobj'=18 +'distance'=19 +'isworm'=20 +'isfood'=21 +'isprojectile'=22 +'turn'=23 +'move'=24 +'jump'=25 +'eat'=26 +'fire'=27 +'def'=28 +'if'=29 +'invoke'=30 +'then'=31 +'else'=32 +'while'=33 +'break'=34 +'print'=35 +':='=36 +'+'=37 +'-'=38 +'*'=39 +'/'=40 +'&&'=41 +'||'=42 +'<'=43 +'<='=44 +'>'=45 +'>='=46 +'=='=47 +'!='=48 +'('=53 +')'=54 +'{'=55 +'}'=56 +':'=57 diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramParser.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramParser.java new file mode 100755 index 0000000..ba4c1e0 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramParser.java @@ -0,0 +1,1757 @@ +// Generated from WormsProgram.g4 by ANTLR 4.7.1 + + package worms.programs.internal.parser.generated; + +import org.antlr.v4.runtime.atn.*; +import org.antlr.v4.runtime.dfa.DFA; +import org.antlr.v4.runtime.*; +import org.antlr.v4.runtime.misc.*; +import org.antlr.v4.runtime.tree.*; +import java.util.List; +import java.util.Iterator; +import java.util.ArrayList; + +@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) +public class WormsProgramParser extends Parser { + static { RuntimeMetaData.checkVersion("4.7.1", RuntimeMetaData.VERSION); } + + protected static final DFA[] _decisionToDFA; + protected static final PredictionContextCache _sharedContextCache = + new PredictionContextCache(); + public static final int + T__0=1, NULL=2, SELF=3, TRUE=4, FALSE=5, SQRT=6, SIN=7, COS=8, NOT=9, + GETX=10, GETY=11, GETRADIUS=12, GETDIR=13, GETAP=14, GETMAXAP=15, GETHP=16, + SAMETEAM=17, SEARCHOBJ=18, DISTANCE=19, ISWORM=20, ISFOOD=21, ISPROJECTILE=22, + TURN=23, MOVE=24, JUMP=25, EAT=26, FIRE=27, DEF=28, IF=29, INVOKE=30, + THEN=31, ELSE=32, WHILE=33, BREAK=34, PRINT=35, ASSIGN=36, ADD=37, SUB=38, + MUL=39, DIV=40, AND=41, OR=42, LT=43, LTE=44, GT=45, GTE=46, EQ=47, NEQ=48, + NUMBER=49, FLOAT=50, INTEGER=51, IDENTIFIER=52, LEFT_PAREN=53, RIGHT_PAREN=54, + LEFT_BRACE=55, RIGHT_BRACE=56, COLON=57, WHITESPACE=58, SINGLE_COMMENT=59; + public static final int + RULE_program = 0, RULE_proceduredef = 1, RULE_statement = 2, RULE_assignmentStatement = 3, + RULE_whileStatement = 4, RULE_ifStatement = 5, RULE_printStatement = 6, + RULE_sequenceStatement = 7, RULE_invokeStatement = 8, RULE_breakStatement = 9, + RULE_actionStatement = 10, RULE_expression = 11; + public static final String[] ruleNames = { + "program", "proceduredef", "statement", "assignmentStatement", "whileStatement", + "ifStatement", "printStatement", "sequenceStatement", "invokeStatement", + "breakStatement", "actionStatement", "expression" + }; + + private static final String[] _LITERAL_NAMES = { + null, "';'", "'null'", "'self'", "'true'", "'false'", "'sqrt'", "'sin'", + "'cos'", "'!'", "'getx'", "'gety'", "'getradius'", "'getdir'", "'getap'", + "'getmaxap'", "'gethp'", "'sameteam'", "'searchobj'", "'distance'", "'isworm'", + "'isfood'", "'isprojectile'", "'turn'", "'move'", "'jump'", "'eat'", "'fire'", + "'def'", "'if'", "'invoke'", "'then'", "'else'", "'while'", "'break'", + "'print'", "':='", "'+'", "'-'", "'*'", "'/'", "'&&'", "'||'", "'<'", + "'<='", "'>'", "'>='", "'=='", "'!='", null, null, null, null, "'('", + "')'", "'{'", "'}'", "':'" + }; + private static final String[] _SYMBOLIC_NAMES = { + null, null, "NULL", "SELF", "TRUE", "FALSE", "SQRT", "SIN", "COS", "NOT", + "GETX", "GETY", "GETRADIUS", "GETDIR", "GETAP", "GETMAXAP", "GETHP", "SAMETEAM", + "SEARCHOBJ", "DISTANCE", "ISWORM", "ISFOOD", "ISPROJECTILE", "TURN", "MOVE", + "JUMP", "EAT", "FIRE", "DEF", "IF", "INVOKE", "THEN", "ELSE", "WHILE", + "BREAK", "PRINT", "ASSIGN", "ADD", "SUB", "MUL", "DIV", "AND", "OR", "LT", + "LTE", "GT", "GTE", "EQ", "NEQ", "NUMBER", "FLOAT", "INTEGER", "IDENTIFIER", + "LEFT_PAREN", "RIGHT_PAREN", "LEFT_BRACE", "RIGHT_BRACE", "COLON", "WHITESPACE", + "SINGLE_COMMENT" + }; + public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES); + + /** + * @deprecated Use {@link #VOCABULARY} instead. + */ + @Deprecated + public static final String[] tokenNames; + static { + tokenNames = new String[_SYMBOLIC_NAMES.length]; + for (int i = 0; i < tokenNames.length; i++) { + tokenNames[i] = VOCABULARY.getLiteralName(i); + if (tokenNames[i] == null) { + tokenNames[i] = VOCABULARY.getSymbolicName(i); + } + + if (tokenNames[i] == null) { + tokenNames[i] = ""; + } + } + } + + @Override + @Deprecated + public String[] getTokenNames() { + return tokenNames; + } + + @Override + + public Vocabulary getVocabulary() { + return VOCABULARY; + } + + @Override + public String getGrammarFileName() { return "WormsProgram.g4"; } + + @Override + public String[] getRuleNames() { return ruleNames; } + + @Override + public String getSerializedATN() { return _serializedATN; } + + @Override + public ATN getATN() { return _ATN; } + + public WormsProgramParser(TokenStream input) { + super(input); + _interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache); + } + public static class ProgramContext extends ParserRuleContext { + public ProceduredefContext proceduredef; + public List procdef = new ArrayList(); + public StatementContext statement; + public List programBody = new ArrayList(); + public List proceduredef() { + return getRuleContexts(ProceduredefContext.class); + } + public ProceduredefContext proceduredef(int i) { + return getRuleContext(ProceduredefContext.class,i); + } + public List statement() { + return getRuleContexts(StatementContext.class); + } + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class,i); + } + public ProgramContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_program; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitProgram(this); + else return visitor.visitChildren(this); + } + } + + public final ProgramContext program() throws RecognitionException { + ProgramContext _localctx = new ProgramContext(_ctx, getState()); + enterRule(_localctx, 0, RULE_program); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(27); + _errHandler.sync(this); + _la = _input.LA(1); + while (_la==DEF) { + { + { + setState(24); + ((ProgramContext)_localctx).proceduredef = proceduredef(); + ((ProgramContext)_localctx).procdef.add(((ProgramContext)_localctx).proceduredef); + } + } + setState(29); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(33); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << TURN) | (1L << MOVE) | (1L << JUMP) | (1L << EAT) | (1L << FIRE) | (1L << IF) | (1L << INVOKE) | (1L << WHILE) | (1L << BREAK) | (1L << PRINT) | (1L << IDENTIFIER) | (1L << LEFT_BRACE))) != 0)) { + { + { + setState(30); + ((ProgramContext)_localctx).statement = statement(); + ((ProgramContext)_localctx).programBody.add(((ProgramContext)_localctx).statement); + } + } + setState(35); + _errHandler.sync(this); + _la = _input.LA(1); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ProceduredefContext extends ParserRuleContext { + public Token procname; + public StatementContext body; + public TerminalNode DEF() { return getToken(WormsProgramParser.DEF, 0); } + public TerminalNode IDENTIFIER() { return getToken(WormsProgramParser.IDENTIFIER, 0); } + public StatementContext statement() { + return getRuleContext(StatementContext.class,0); + } + public TerminalNode COLON() { return getToken(WormsProgramParser.COLON, 0); } + public ProceduredefContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_proceduredef; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitProceduredef(this); + else return visitor.visitChildren(this); + } + } + + public final ProceduredefContext proceduredef() throws RecognitionException { + ProceduredefContext _localctx = new ProceduredefContext(_ctx, getState()); + enterRule(_localctx, 2, RULE_proceduredef); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(36); + match(DEF); + setState(37); + ((ProceduredefContext)_localctx).procname = match(IDENTIFIER); + setState(39); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==COLON) { + { + setState(38); + match(COLON); + } + } + + setState(41); + ((ProceduredefContext)_localctx).body = statement(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class StatementContext extends ParserRuleContext { + public AssignmentStatementContext assignmentStatement() { + return getRuleContext(AssignmentStatementContext.class,0); + } + public WhileStatementContext whileStatement() { + return getRuleContext(WhileStatementContext.class,0); + } + public IfStatementContext ifStatement() { + return getRuleContext(IfStatementContext.class,0); + } + public PrintStatementContext printStatement() { + return getRuleContext(PrintStatementContext.class,0); + } + public SequenceStatementContext sequenceStatement() { + return getRuleContext(SequenceStatementContext.class,0); + } + public InvokeStatementContext invokeStatement() { + return getRuleContext(InvokeStatementContext.class,0); + } + public BreakStatementContext breakStatement() { + return getRuleContext(BreakStatementContext.class,0); + } + public ActionStatementContext actionStatement() { + return getRuleContext(ActionStatementContext.class,0); + } + public StatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_statement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitStatement(this); + else return visitor.visitChildren(this); + } + } + + public final StatementContext statement() throws RecognitionException { + StatementContext _localctx = new StatementContext(_ctx, getState()); + enterRule(_localctx, 4, RULE_statement); + try { + setState(51); + _errHandler.sync(this); + switch (_input.LA(1)) { + case IDENTIFIER: + enterOuterAlt(_localctx, 1); + { + setState(43); + assignmentStatement(); + } + break; + case WHILE: + enterOuterAlt(_localctx, 2); + { + setState(44); + whileStatement(); + } + break; + case IF: + enterOuterAlt(_localctx, 3); + { + setState(45); + ifStatement(); + } + break; + case PRINT: + enterOuterAlt(_localctx, 4); + { + setState(46); + printStatement(); + } + break; + case LEFT_BRACE: + enterOuterAlt(_localctx, 5); + { + setState(47); + sequenceStatement(); + } + break; + case INVOKE: + enterOuterAlt(_localctx, 6); + { + setState(48); + invokeStatement(); + } + break; + case BREAK: + enterOuterAlt(_localctx, 7); + { + setState(49); + breakStatement(); + } + break; + case TURN: + case MOVE: + case JUMP: + case EAT: + case FIRE: + enterOuterAlt(_localctx, 8); + { + setState(50); + actionStatement(); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class AssignmentStatementContext extends ParserRuleContext { + public Token variableName; + public ExpressionContext value; + public TerminalNode ASSIGN() { return getToken(WormsProgramParser.ASSIGN, 0); } + public TerminalNode IDENTIFIER() { return getToken(WormsProgramParser.IDENTIFIER, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public AssignmentStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_assignmentStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitAssignmentStatement(this); + else return visitor.visitChildren(this); + } + } + + public final AssignmentStatementContext assignmentStatement() throws RecognitionException { + AssignmentStatementContext _localctx = new AssignmentStatementContext(_ctx, getState()); + enterRule(_localctx, 6, RULE_assignmentStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(53); + ((AssignmentStatementContext)_localctx).variableName = match(IDENTIFIER); + setState(54); + match(ASSIGN); + setState(55); + ((AssignmentStatementContext)_localctx).value = expression(0); + setState(56); + match(T__0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class WhileStatementContext extends ParserRuleContext { + public ExpressionContext condition; + public StatementContext body; + public TerminalNode WHILE() { return getToken(WormsProgramParser.WHILE, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public StatementContext statement() { + return getRuleContext(StatementContext.class,0); + } + public TerminalNode COLON() { return getToken(WormsProgramParser.COLON, 0); } + public WhileStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_whileStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitWhileStatement(this); + else return visitor.visitChildren(this); + } + } + + public final WhileStatementContext whileStatement() throws RecognitionException { + WhileStatementContext _localctx = new WhileStatementContext(_ctx, getState()); + enterRule(_localctx, 8, RULE_whileStatement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(58); + match(WHILE); + setState(59); + ((WhileStatementContext)_localctx).condition = expression(0); + setState(61); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==COLON) { + { + setState(60); + match(COLON); + } + } + + setState(63); + ((WhileStatementContext)_localctx).body = statement(); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class IfStatementContext extends ParserRuleContext { + public ExpressionContext condition; + public StatementContext ifbody; + public StatementContext elsebody; + public TerminalNode IF() { return getToken(WormsProgramParser.IF, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public List statement() { + return getRuleContexts(StatementContext.class); + } + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class,i); + } + public List COLON() { return getTokens(WormsProgramParser.COLON); } + public TerminalNode COLON(int i) { + return getToken(WormsProgramParser.COLON, i); + } + public TerminalNode ELSE() { return getToken(WormsProgramParser.ELSE, 0); } + public IfStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_ifStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitIfStatement(this); + else return visitor.visitChildren(this); + } + } + + public final IfStatementContext ifStatement() throws RecognitionException { + IfStatementContext _localctx = new IfStatementContext(_ctx, getState()); + enterRule(_localctx, 10, RULE_ifStatement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(65); + match(IF); + setState(66); + ((IfStatementContext)_localctx).condition = expression(0); + setState(68); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==COLON) { + { + setState(67); + match(COLON); + } + } + + setState(70); + ((IfStatementContext)_localctx).ifbody = statement(); + setState(76); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,7,_ctx) ) { + case 1: + { + setState(71); + match(ELSE); + setState(73); + _errHandler.sync(this); + _la = _input.LA(1); + if (_la==COLON) { + { + setState(72); + match(COLON); + } + } + + setState(75); + ((IfStatementContext)_localctx).elsebody = statement(); + } + break; + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class PrintStatementContext extends ParserRuleContext { + public ExpressionContext value; + public TerminalNode PRINT() { return getToken(WormsProgramParser.PRINT, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public PrintStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_printStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitPrintStatement(this); + else return visitor.visitChildren(this); + } + } + + public final PrintStatementContext printStatement() throws RecognitionException { + PrintStatementContext _localctx = new PrintStatementContext(_ctx, getState()); + enterRule(_localctx, 12, RULE_printStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(78); + match(PRINT); + setState(79); + ((PrintStatementContext)_localctx).value = expression(0); + setState(80); + match(T__0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class SequenceStatementContext extends ParserRuleContext { + public StatementContext statement; + public List stmts = new ArrayList(); + public TerminalNode LEFT_BRACE() { return getToken(WormsProgramParser.LEFT_BRACE, 0); } + public TerminalNode RIGHT_BRACE() { return getToken(WormsProgramParser.RIGHT_BRACE, 0); } + public List statement() { + return getRuleContexts(StatementContext.class); + } + public StatementContext statement(int i) { + return getRuleContext(StatementContext.class,i); + } + public SequenceStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_sequenceStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSequenceStatement(this); + else return visitor.visitChildren(this); + } + } + + public final SequenceStatementContext sequenceStatement() throws RecognitionException { + SequenceStatementContext _localctx = new SequenceStatementContext(_ctx, getState()); + enterRule(_localctx, 14, RULE_sequenceStatement); + int _la; + try { + enterOuterAlt(_localctx, 1); + { + setState(82); + match(LEFT_BRACE); + setState(86); + _errHandler.sync(this); + _la = _input.LA(1); + while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << TURN) | (1L << MOVE) | (1L << JUMP) | (1L << EAT) | (1L << FIRE) | (1L << IF) | (1L << INVOKE) | (1L << WHILE) | (1L << BREAK) | (1L << PRINT) | (1L << IDENTIFIER) | (1L << LEFT_BRACE))) != 0)) { + { + { + setState(83); + ((SequenceStatementContext)_localctx).statement = statement(); + ((SequenceStatementContext)_localctx).stmts.add(((SequenceStatementContext)_localctx).statement); + } + } + setState(88); + _errHandler.sync(this); + _la = _input.LA(1); + } + setState(89); + match(RIGHT_BRACE); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class InvokeStatementContext extends ParserRuleContext { + public Token procName; + public TerminalNode INVOKE() { return getToken(WormsProgramParser.INVOKE, 0); } + public TerminalNode IDENTIFIER() { return getToken(WormsProgramParser.IDENTIFIER, 0); } + public InvokeStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_invokeStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitInvokeStatement(this); + else return visitor.visitChildren(this); + } + } + + public final InvokeStatementContext invokeStatement() throws RecognitionException { + InvokeStatementContext _localctx = new InvokeStatementContext(_ctx, getState()); + enterRule(_localctx, 16, RULE_invokeStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(91); + match(INVOKE); + setState(92); + ((InvokeStatementContext)_localctx).procName = match(IDENTIFIER); + setState(93); + match(T__0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class BreakStatementContext extends ParserRuleContext { + public TerminalNode BREAK() { return getToken(WormsProgramParser.BREAK, 0); } + public BreakStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_breakStatement; } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitBreakStatement(this); + else return visitor.visitChildren(this); + } + } + + public final BreakStatementContext breakStatement() throws RecognitionException { + BreakStatementContext _localctx = new BreakStatementContext(_ctx, getState()); + enterRule(_localctx, 18, RULE_breakStatement); + try { + enterOuterAlt(_localctx, 1); + { + setState(95); + match(BREAK); + setState(96); + match(T__0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ActionStatementContext extends ParserRuleContext { + public ActionStatementContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_actionStatement; } + + public ActionStatementContext() { } + public void copyFrom(ActionStatementContext ctx) { + super.copyFrom(ctx); + } + } + public static class MoveActionContext extends ActionStatementContext { + public TerminalNode MOVE() { return getToken(WormsProgramParser.MOVE, 0); } + public MoveActionContext(ActionStatementContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitMoveAction(this); + else return visitor.visitChildren(this); + } + } + public static class TurnActionContext extends ActionStatementContext { + public ExpressionContext angle; + public TerminalNode TURN() { return getToken(WormsProgramParser.TURN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public TurnActionContext(ActionStatementContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitTurnAction(this); + else return visitor.visitChildren(this); + } + } + public static class EatActionContext extends ActionStatementContext { + public TerminalNode EAT() { return getToken(WormsProgramParser.EAT, 0); } + public EatActionContext(ActionStatementContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitEatAction(this); + else return visitor.visitChildren(this); + } + } + public static class FireActionContext extends ActionStatementContext { + public TerminalNode FIRE() { return getToken(WormsProgramParser.FIRE, 0); } + public FireActionContext(ActionStatementContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitFireAction(this); + else return visitor.visitChildren(this); + } + } + public static class JumpActionContext extends ActionStatementContext { + public TerminalNode JUMP() { return getToken(WormsProgramParser.JUMP, 0); } + public JumpActionContext(ActionStatementContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitJumpAction(this); + else return visitor.visitChildren(this); + } + } + + public final ActionStatementContext actionStatement() throws RecognitionException { + ActionStatementContext _localctx = new ActionStatementContext(_ctx, getState()); + enterRule(_localctx, 20, RULE_actionStatement); + try { + setState(110); + _errHandler.sync(this); + switch (_input.LA(1)) { + case TURN: + _localctx = new TurnActionContext(_localctx); + enterOuterAlt(_localctx, 1); + { + setState(98); + match(TURN); + setState(99); + ((TurnActionContext)_localctx).angle = expression(0); + setState(100); + match(T__0); + } + break; + case MOVE: + _localctx = new MoveActionContext(_localctx); + enterOuterAlt(_localctx, 2); + { + setState(102); + match(MOVE); + setState(103); + match(T__0); + } + break; + case JUMP: + _localctx = new JumpActionContext(_localctx); + enterOuterAlt(_localctx, 3); + { + setState(104); + match(JUMP); + setState(105); + match(T__0); + } + break; + case EAT: + _localctx = new EatActionContext(_localctx); + enterOuterAlt(_localctx, 4); + { + setState(106); + match(EAT); + setState(107); + match(T__0); + } + break; + case FIRE: + _localctx = new FireActionContext(_localctx); + enterOuterAlt(_localctx, 5); + { + setState(108); + match(FIRE); + setState(109); + match(T__0); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + exitRule(); + } + return _localctx; + } + + public static class ExpressionContext extends ParserRuleContext { + public ExpressionContext(ParserRuleContext parent, int invokingState) { + super(parent, invokingState); + } + @Override public int getRuleIndex() { return RULE_expression; } + + public ExpressionContext() { } + public void copyFrom(ExpressionContext ctx) { + super.copyFrom(ctx); + } + } + public static class DistanceExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode DISTANCE() { return getToken(WormsProgramParser.DISTANCE, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public DistanceExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitDistanceExpression(this); + else return visitor.visitChildren(this); + } + } + public static class CosExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode COS() { return getToken(WormsProgramParser.COS, 0); } + public TerminalNode LEFT_PAREN() { return getToken(WormsProgramParser.LEFT_PAREN, 0); } + public TerminalNode RIGHT_PAREN() { return getToken(WormsProgramParser.RIGHT_PAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public CosExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitCosExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetYExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETY() { return getToken(WormsProgramParser.GETY, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetYExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetYExpression(this); + else return visitor.visitChildren(this); + } + } + public static class AndOrExpressionContext extends ExpressionContext { + public ExpressionContext left; + public Token op; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public TerminalNode AND() { return getToken(WormsProgramParser.AND, 0); } + public TerminalNode OR() { return getToken(WormsProgramParser.OR, 0); } + public AndOrExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitAndOrExpression(this); + else return visitor.visitChildren(this); + } + } + public static class IsWormExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode ISWORM() { return getToken(WormsProgramParser.ISWORM, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public IsWormExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitIsWormExpression(this); + else return visitor.visitChildren(this); + } + } + public static class NotExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode NOT() { return getToken(WormsProgramParser.NOT, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public NotExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitNotExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ComparisonExpressionContext extends ExpressionContext { + public ExpressionContext left; + public Token op; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public TerminalNode LT() { return getToken(WormsProgramParser.LT, 0); } + public TerminalNode LTE() { return getToken(WormsProgramParser.LTE, 0); } + public TerminalNode GT() { return getToken(WormsProgramParser.GT, 0); } + public TerminalNode GTE() { return getToken(WormsProgramParser.GTE, 0); } + public TerminalNode EQ() { return getToken(WormsProgramParser.EQ, 0); } + public TerminalNode NEQ() { return getToken(WormsProgramParser.NEQ, 0); } + public ComparisonExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitComparisonExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ParenExpressionContext extends ExpressionContext { + public ExpressionContext subExpr; + public TerminalNode LEFT_PAREN() { return getToken(WormsProgramParser.LEFT_PAREN, 0); } + public TerminalNode RIGHT_PAREN() { return getToken(WormsProgramParser.RIGHT_PAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public ParenExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitParenExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetRadiusExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETRADIUS() { return getToken(WormsProgramParser.GETRADIUS, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetRadiusExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetRadiusExpression(this); + else return visitor.visitChildren(this); + } + } + public static class TrueLiteralExpressionContext extends ExpressionContext { + public TerminalNode TRUE() { return getToken(WormsProgramParser.TRUE, 0); } + public TrueLiteralExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitTrueLiteralExpression(this); + else return visitor.visitChildren(this); + } + } + public static class NullExpressionContext extends ExpressionContext { + public TerminalNode NULL() { return getToken(WormsProgramParser.NULL, 0); } + public NullExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitNullExpression(this); + else return visitor.visitChildren(this); + } + } + public static class SqrtExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode SQRT() { return getToken(WormsProgramParser.SQRT, 0); } + public TerminalNode LEFT_PAREN() { return getToken(WormsProgramParser.LEFT_PAREN, 0); } + public TerminalNode RIGHT_PAREN() { return getToken(WormsProgramParser.RIGHT_PAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SqrtExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSqrtExpression(this); + else return visitor.visitChildren(this); + } + } + public static class SinExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode SIN() { return getToken(WormsProgramParser.SIN, 0); } + public TerminalNode LEFT_PAREN() { return getToken(WormsProgramParser.LEFT_PAREN, 0); } + public TerminalNode RIGHT_PAREN() { return getToken(WormsProgramParser.RIGHT_PAREN, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SinExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSinExpression(this); + else return visitor.visitChildren(this); + } + } + public static class SameTeamExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode SAMETEAM() { return getToken(WormsProgramParser.SAMETEAM, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SameTeamExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSameTeamExpression(this); + else return visitor.visitChildren(this); + } + } + public static class IsProjectileExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode ISPROJECTILE() { return getToken(WormsProgramParser.ISPROJECTILE, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public IsProjectileExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitIsProjectileExpression(this); + else return visitor.visitChildren(this); + } + } + public static class IsFoodExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode ISFOOD() { return getToken(WormsProgramParser.ISFOOD, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public IsFoodExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitIsFoodExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ConstantExpressionContext extends ExpressionContext { + public Token value; + public TerminalNode NUMBER() { return getToken(WormsProgramParser.NUMBER, 0); } + public ConstantExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitConstantExpression(this); + else return visitor.visitChildren(this); + } + } + public static class SearchObjExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode SEARCHOBJ() { return getToken(WormsProgramParser.SEARCHOBJ, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public SearchObjExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSearchObjExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetXExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETX() { return getToken(WormsProgramParser.GETX, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetXExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetXExpression(this); + else return visitor.visitChildren(this); + } + } + public static class ReadVariableExpressionContext extends ExpressionContext { + public Token variable; + public TerminalNode IDENTIFIER() { return getToken(WormsProgramParser.IDENTIFIER, 0); } + public ReadVariableExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitReadVariableExpression(this); + else return visitor.visitChildren(this); + } + } + public static class MulDivExpressionContext extends ExpressionContext { + public ExpressionContext left; + public Token op; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public TerminalNode MUL() { return getToken(WormsProgramParser.MUL, 0); } + public TerminalNode DIV() { return getToken(WormsProgramParser.DIV, 0); } + public MulDivExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitMulDivExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetDirectionExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETDIR() { return getToken(WormsProgramParser.GETDIR, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetDirectionExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetDirectionExpression(this); + else return visitor.visitChildren(this); + } + } + public static class SelfExpressionContext extends ExpressionContext { + public TerminalNode SELF() { return getToken(WormsProgramParser.SELF, 0); } + public SelfExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitSelfExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetHPExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETHP() { return getToken(WormsProgramParser.GETHP, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetHPExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetHPExpression(this); + else return visitor.visitChildren(this); + } + } + public static class AddSubExpressionContext extends ExpressionContext { + public ExpressionContext left; + public Token op; + public ExpressionContext right; + public List expression() { + return getRuleContexts(ExpressionContext.class); + } + public ExpressionContext expression(int i) { + return getRuleContext(ExpressionContext.class,i); + } + public TerminalNode ADD() { return getToken(WormsProgramParser.ADD, 0); } + public TerminalNode SUB() { return getToken(WormsProgramParser.SUB, 0); } + public AddSubExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitAddSubExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetMaxAPExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETMAXAP() { return getToken(WormsProgramParser.GETMAXAP, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetMaxAPExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetMaxAPExpression(this); + else return visitor.visitChildren(this); + } + } + public static class GetAPExpressionContext extends ExpressionContext { + public ExpressionContext expr; + public TerminalNode GETAP() { return getToken(WormsProgramParser.GETAP, 0); } + public ExpressionContext expression() { + return getRuleContext(ExpressionContext.class,0); + } + public GetAPExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitGetAPExpression(this); + else return visitor.visitChildren(this); + } + } + public static class FalseLiteralExpressionContext extends ExpressionContext { + public TerminalNode FALSE() { return getToken(WormsProgramParser.FALSE, 0); } + public FalseLiteralExpressionContext(ExpressionContext ctx) { copyFrom(ctx); } + @Override + public T accept(ParseTreeVisitor visitor) { + if ( visitor instanceof WormsProgramVisitor ) return ((WormsProgramVisitor)visitor).visitFalseLiteralExpression(this); + else return visitor.visitChildren(this); + } + } + + public final ExpressionContext expression() throws RecognitionException { + return expression(0); + } + + private ExpressionContext expression(int _p) throws RecognitionException { + ParserRuleContext _parentctx = _ctx; + int _parentState = getState(); + ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState); + ExpressionContext _prevctx = _localctx; + int _startState = 22; + enterRecursionRule(_localctx, 22, RULE_expression, _p); + int _la; + try { + int _alt; + enterOuterAlt(_localctx, 1); + { + setState(166); + _errHandler.sync(this); + switch (_input.LA(1)) { + case IDENTIFIER: + { + _localctx = new ReadVariableExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + + setState(113); + ((ReadVariableExpressionContext)_localctx).variable = match(IDENTIFIER); + } + break; + case NUMBER: + { + _localctx = new ConstantExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(114); + ((ConstantExpressionContext)_localctx).value = match(NUMBER); + } + break; + case TRUE: + { + _localctx = new TrueLiteralExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(115); + match(TRUE); + } + break; + case FALSE: + { + _localctx = new FalseLiteralExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(116); + match(FALSE); + } + break; + case NULL: + { + _localctx = new NullExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(117); + match(NULL); + } + break; + case SELF: + { + _localctx = new SelfExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(118); + match(SELF); + } + break; + case LEFT_PAREN: + { + _localctx = new ParenExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(119); + match(LEFT_PAREN); + setState(120); + ((ParenExpressionContext)_localctx).subExpr = expression(0); + setState(121); + match(RIGHT_PAREN); + } + break; + case SQRT: + { + _localctx = new SqrtExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(123); + match(SQRT); + setState(124); + match(LEFT_PAREN); + setState(125); + ((SqrtExpressionContext)_localctx).expr = expression(0); + setState(126); + match(RIGHT_PAREN); + } + break; + case SIN: + { + _localctx = new SinExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(128); + match(SIN); + setState(129); + match(LEFT_PAREN); + setState(130); + ((SinExpressionContext)_localctx).expr = expression(0); + setState(131); + match(RIGHT_PAREN); + } + break; + case COS: + { + _localctx = new CosExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(133); + match(COS); + setState(134); + match(LEFT_PAREN); + setState(135); + ((CosExpressionContext)_localctx).expr = expression(0); + setState(136); + match(RIGHT_PAREN); + } + break; + case NOT: + { + _localctx = new NotExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(138); + match(NOT); + setState(139); + ((NotExpressionContext)_localctx).expr = expression(14); + } + break; + case GETX: + { + _localctx = new GetXExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(140); + match(GETX); + setState(141); + ((GetXExpressionContext)_localctx).expr = expression(13); + } + break; + case GETY: + { + _localctx = new GetYExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(142); + match(GETY); + setState(143); + ((GetYExpressionContext)_localctx).expr = expression(12); + } + break; + case GETRADIUS: + { + _localctx = new GetRadiusExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(144); + match(GETRADIUS); + setState(145); + ((GetRadiusExpressionContext)_localctx).expr = expression(11); + } + break; + case GETDIR: + { + _localctx = new GetDirectionExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(146); + match(GETDIR); + setState(147); + ((GetDirectionExpressionContext)_localctx).expr = expression(10); + } + break; + case GETAP: + { + _localctx = new GetAPExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(148); + match(GETAP); + setState(149); + ((GetAPExpressionContext)_localctx).expr = expression(9); + } + break; + case GETMAXAP: + { + _localctx = new GetMaxAPExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(150); + match(GETMAXAP); + setState(151); + ((GetMaxAPExpressionContext)_localctx).expr = expression(8); + } + break; + case GETHP: + { + _localctx = new GetHPExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(152); + match(GETHP); + setState(153); + ((GetHPExpressionContext)_localctx).expr = expression(7); + } + break; + case SAMETEAM: + { + _localctx = new SameTeamExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(154); + match(SAMETEAM); + setState(155); + ((SameTeamExpressionContext)_localctx).expr = expression(6); + } + break; + case SEARCHOBJ: + { + _localctx = new SearchObjExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(156); + match(SEARCHOBJ); + setState(157); + ((SearchObjExpressionContext)_localctx).expr = expression(5); + } + break; + case DISTANCE: + { + _localctx = new DistanceExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(158); + match(DISTANCE); + setState(159); + ((DistanceExpressionContext)_localctx).expr = expression(4); + } + break; + case ISWORM: + { + _localctx = new IsWormExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(160); + match(ISWORM); + setState(161); + ((IsWormExpressionContext)_localctx).expr = expression(3); + } + break; + case ISFOOD: + { + _localctx = new IsFoodExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(162); + match(ISFOOD); + setState(163); + ((IsFoodExpressionContext)_localctx).expr = expression(2); + } + break; + case ISPROJECTILE: + { + _localctx = new IsProjectileExpressionContext(_localctx); + _ctx = _localctx; + _prevctx = _localctx; + setState(164); + match(ISPROJECTILE); + setState(165); + ((IsProjectileExpressionContext)_localctx).expr = expression(1); + } + break; + default: + throw new NoViableAltException(this); + } + _ctx.stop = _input.LT(-1); + setState(182); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,12,_ctx); + while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { + if ( _alt==1 ) { + if ( _parseListeners!=null ) triggerExitRuleEvent(); + _prevctx = _localctx; + { + setState(180); + _errHandler.sync(this); + switch ( getInterpreter().adaptivePredict(_input,11,_ctx) ) { + case 1: + { + _localctx = new MulDivExpressionContext(new ExpressionContext(_parentctx, _parentState)); + ((MulDivExpressionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(168); + if (!(precpred(_ctx, 21))) throw new FailedPredicateException(this, "precpred(_ctx, 21)"); + setState(169); + ((MulDivExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==MUL || _la==DIV) ) { + ((MulDivExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(170); + ((MulDivExpressionContext)_localctx).right = expression(22); + } + break; + case 2: + { + _localctx = new AddSubExpressionContext(new ExpressionContext(_parentctx, _parentState)); + ((AddSubExpressionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(171); + if (!(precpred(_ctx, 20))) throw new FailedPredicateException(this, "precpred(_ctx, 20)"); + setState(172); + ((AddSubExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==ADD || _la==SUB) ) { + ((AddSubExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(173); + ((AddSubExpressionContext)_localctx).right = expression(21); + } + break; + case 3: + { + _localctx = new ComparisonExpressionContext(new ExpressionContext(_parentctx, _parentState)); + ((ComparisonExpressionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(174); + if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)"); + setState(175); + ((ComparisonExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << LT) | (1L << LTE) | (1L << GT) | (1L << GTE) | (1L << EQ) | (1L << NEQ))) != 0)) ) { + ((ComparisonExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(176); + ((ComparisonExpressionContext)_localctx).right = expression(20); + } + break; + case 4: + { + _localctx = new AndOrExpressionContext(new ExpressionContext(_parentctx, _parentState)); + ((AndOrExpressionContext)_localctx).left = _prevctx; + pushNewRecursionContext(_localctx, _startState, RULE_expression); + setState(177); + if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)"); + setState(178); + ((AndOrExpressionContext)_localctx).op = _input.LT(1); + _la = _input.LA(1); + if ( !(_la==AND || _la==OR) ) { + ((AndOrExpressionContext)_localctx).op = (Token)_errHandler.recoverInline(this); + } + else { + if ( _input.LA(1)==Token.EOF ) matchedEOF = true; + _errHandler.reportMatch(this); + consume(); + } + setState(179); + ((AndOrExpressionContext)_localctx).right = expression(19); + } + break; + } + } + } + setState(184); + _errHandler.sync(this); + _alt = getInterpreter().adaptivePredict(_input,12,_ctx); + } + } + } + catch (RecognitionException re) { + _localctx.exception = re; + _errHandler.reportError(this, re); + _errHandler.recover(this, re); + } + finally { + unrollRecursionContexts(_parentctx); + } + return _localctx; + } + + public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) { + switch (ruleIndex) { + case 11: + return expression_sempred((ExpressionContext)_localctx, predIndex); + } + return true; + } + private boolean expression_sempred(ExpressionContext _localctx, int predIndex) { + switch (predIndex) { + case 0: + return precpred(_ctx, 21); + case 1: + return precpred(_ctx, 20); + case 2: + return precpred(_ctx, 19); + case 3: + return precpred(_ctx, 18); + } + return true; + } + + public static final String _serializedATN = + "\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\3=\u00bc\4\2\t\2\4"+ + "\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+ + "\13\4\f\t\f\4\r\t\r\3\2\7\2\34\n\2\f\2\16\2\37\13\2\3\2\7\2\"\n\2\f\2"+ + "\16\2%\13\2\3\3\3\3\3\3\5\3*\n\3\3\3\3\3\3\4\3\4\3\4\3\4\3\4\3\4\3\4\3"+ + "\4\5\4\66\n\4\3\5\3\5\3\5\3\5\3\5\3\6\3\6\3\6\5\6@\n\6\3\6\3\6\3\7\3\7"+ + "\3\7\5\7G\n\7\3\7\3\7\3\7\5\7L\n\7\3\7\5\7O\n\7\3\b\3\b\3\b\3\b\3\t\3"+ + "\t\7\tW\n\t\f\t\16\tZ\13\t\3\t\3\t\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\f"+ + "\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\3\f\5\fq\n\f\3\r\3\r\3\r\3\r"+ + "\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3"+ + "\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+ + "\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\5\r\u00a9"+ + "\n\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\7\r\u00b7\n\r\f\r"+ + "\16\r\u00ba\13\r\3\r\2\3\30\16\2\4\6\b\n\f\16\20\22\24\26\30\2\6\3\2)"+ + "*\3\2\'(\3\2-\62\3\2+,\2\u00dd\2\35\3\2\2\2\4&\3\2\2\2\6\65\3\2\2\2\b"+ + "\67\3\2\2\2\n<\3\2\2\2\fC\3\2\2\2\16P\3\2\2\2\20T\3\2\2\2\22]\3\2\2\2"+ + "\24a\3\2\2\2\26p\3\2\2\2\30\u00a8\3\2\2\2\32\34\5\4\3\2\33\32\3\2\2\2"+ + "\34\37\3\2\2\2\35\33\3\2\2\2\35\36\3\2\2\2\36#\3\2\2\2\37\35\3\2\2\2 "+ + "\"\5\6\4\2! \3\2\2\2\"%\3\2\2\2#!\3\2\2\2#$\3\2\2\2$\3\3\2\2\2%#\3\2\2"+ + "\2&\'\7\36\2\2\')\7\66\2\2(*\7;\2\2)(\3\2\2\2)*\3\2\2\2*+\3\2\2\2+,\5"+ + "\6\4\2,\5\3\2\2\2-\66\5\b\5\2.\66\5\n\6\2/\66\5\f\7\2\60\66\5\16\b\2\61"+ + "\66\5\20\t\2\62\66\5\22\n\2\63\66\5\24\13\2\64\66\5\26\f\2\65-\3\2\2\2"+ + "\65.\3\2\2\2\65/\3\2\2\2\65\60\3\2\2\2\65\61\3\2\2\2\65\62\3\2\2\2\65"+ + "\63\3\2\2\2\65\64\3\2\2\2\66\7\3\2\2\2\678\7\66\2\289\7&\2\29:\5\30\r"+ + "\2:;\7\3\2\2;\t\3\2\2\2<=\7#\2\2=?\5\30\r\2>@\7;\2\2?>\3\2\2\2?@\3\2\2"+ + "\2@A\3\2\2\2AB\5\6\4\2B\13\3\2\2\2CD\7\37\2\2DF\5\30\r\2EG\7;\2\2FE\3"+ + "\2\2\2FG\3\2\2\2GH\3\2\2\2HN\5\6\4\2IK\7\"\2\2JL\7;\2\2KJ\3\2\2\2KL\3"+ + "\2\2\2LM\3\2\2\2MO\5\6\4\2NI\3\2\2\2NO\3\2\2\2O\r\3\2\2\2PQ\7%\2\2QR\5"+ + "\30\r\2RS\7\3\2\2S\17\3\2\2\2TX\79\2\2UW\5\6\4\2VU\3\2\2\2WZ\3\2\2\2X"+ + "V\3\2\2\2XY\3\2\2\2Y[\3\2\2\2ZX\3\2\2\2[\\\7:\2\2\\\21\3\2\2\2]^\7 \2"+ + "\2^_\7\66\2\2_`\7\3\2\2`\23\3\2\2\2ab\7$\2\2bc\7\3\2\2c\25\3\2\2\2de\7"+ + "\31\2\2ef\5\30\r\2fg\7\3\2\2gq\3\2\2\2hi\7\32\2\2iq\7\3\2\2jk\7\33\2\2"+ + "kq\7\3\2\2lm\7\34\2\2mq\7\3\2\2no\7\35\2\2oq\7\3\2\2pd\3\2\2\2ph\3\2\2"+ + "\2pj\3\2\2\2pl\3\2\2\2pn\3\2\2\2q\27\3\2\2\2rs\b\r\1\2s\u00a9\7\66\2\2"+ + "t\u00a9\7\63\2\2u\u00a9\7\6\2\2v\u00a9\7\7\2\2w\u00a9\7\4\2\2x\u00a9\7"+ + "\5\2\2yz\7\67\2\2z{\5\30\r\2{|\78\2\2|\u00a9\3\2\2\2}~\7\b\2\2~\177\7"+ + "\67\2\2\177\u0080\5\30\r\2\u0080\u0081\78\2\2\u0081\u00a9\3\2\2\2\u0082"+ + "\u0083\7\t\2\2\u0083\u0084\7\67\2\2\u0084\u0085\5\30\r\2\u0085\u0086\7"+ + "8\2\2\u0086\u00a9\3\2\2\2\u0087\u0088\7\n\2\2\u0088\u0089\7\67\2\2\u0089"+ + "\u008a\5\30\r\2\u008a\u008b\78\2\2\u008b\u00a9\3\2\2\2\u008c\u008d\7\13"+ + "\2\2\u008d\u00a9\5\30\r\20\u008e\u008f\7\f\2\2\u008f\u00a9\5\30\r\17\u0090"+ + "\u0091\7\r\2\2\u0091\u00a9\5\30\r\16\u0092\u0093\7\16\2\2\u0093\u00a9"+ + "\5\30\r\r\u0094\u0095\7\17\2\2\u0095\u00a9\5\30\r\f\u0096\u0097\7\20\2"+ + "\2\u0097\u00a9\5\30\r\13\u0098\u0099\7\21\2\2\u0099\u00a9\5\30\r\n\u009a"+ + "\u009b\7\22\2\2\u009b\u00a9\5\30\r\t\u009c\u009d\7\23\2\2\u009d\u00a9"+ + "\5\30\r\b\u009e\u009f\7\24\2\2\u009f\u00a9\5\30\r\7\u00a0\u00a1\7\25\2"+ + "\2\u00a1\u00a9\5\30\r\6\u00a2\u00a3\7\26\2\2\u00a3\u00a9\5\30\r\5\u00a4"+ + "\u00a5\7\27\2\2\u00a5\u00a9\5\30\r\4\u00a6\u00a7\7\30\2\2\u00a7\u00a9"+ + "\5\30\r\3\u00a8r\3\2\2\2\u00a8t\3\2\2\2\u00a8u\3\2\2\2\u00a8v\3\2\2\2"+ + "\u00a8w\3\2\2\2\u00a8x\3\2\2\2\u00a8y\3\2\2\2\u00a8}\3\2\2\2\u00a8\u0082"+ + "\3\2\2\2\u00a8\u0087\3\2\2\2\u00a8\u008c\3\2\2\2\u00a8\u008e\3\2\2\2\u00a8"+ + "\u0090\3\2\2\2\u00a8\u0092\3\2\2\2\u00a8\u0094\3\2\2\2\u00a8\u0096\3\2"+ + "\2\2\u00a8\u0098\3\2\2\2\u00a8\u009a\3\2\2\2\u00a8\u009c\3\2\2\2\u00a8"+ + "\u009e\3\2\2\2\u00a8\u00a0\3\2\2\2\u00a8\u00a2\3\2\2\2\u00a8\u00a4\3\2"+ + "\2\2\u00a8\u00a6\3\2\2\2\u00a9\u00b8\3\2\2\2\u00aa\u00ab\f\27\2\2\u00ab"+ + "\u00ac\t\2\2\2\u00ac\u00b7\5\30\r\30\u00ad\u00ae\f\26\2\2\u00ae\u00af"+ + "\t\3\2\2\u00af\u00b7\5\30\r\27\u00b0\u00b1\f\25\2\2\u00b1\u00b2\t\4\2"+ + "\2\u00b2\u00b7\5\30\r\26\u00b3\u00b4\f\24\2\2\u00b4\u00b5\t\5\2\2\u00b5"+ + "\u00b7\5\30\r\25\u00b6\u00aa\3\2\2\2\u00b6\u00ad\3\2\2\2\u00b6\u00b0\3"+ + "\2\2\2\u00b6\u00b3\3\2\2\2\u00b7\u00ba\3\2\2\2\u00b8\u00b6\3\2\2\2\u00b8"+ + "\u00b9\3\2\2\2\u00b9\31\3\2\2\2\u00ba\u00b8\3\2\2\2\17\35#)\65?FKNXp\u00a8"+ + "\u00b6\u00b8"; + public static final ATN _ATN = + new ATNDeserializer().deserialize(_serializedATN.toCharArray()); + static { + _decisionToDFA = new DFA[_ATN.getNumberOfDecisions()]; + for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) { + _decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i); + } + } +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramVisitor.java b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramVisitor.java new file mode 100755 index 0000000..c023634 --- /dev/null +++ b/OGP1718-Worms/src-provided/worms/programs/internal/parser/generated/WormsProgramVisitor.java @@ -0,0 +1,306 @@ +// Generated from WormsProgram.g4 by ANTLR 4.7.1 + + package worms.programs.internal.parser.generated; + +import org.antlr.v4.runtime.tree.ParseTreeVisitor; + +/** + * This interface defines a complete generic visitor for a parse tree produced + * by {@link WormsProgramParser}. + * + * @param The return type of the visit operation. Use {@link Void} for + * operations with no return type. + */ +public interface WormsProgramVisitor extends ParseTreeVisitor { + /** + * Visit a parse tree produced by {@link WormsProgramParser#program}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProgram(WormsProgramParser.ProgramContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#proceduredef}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitProceduredef(WormsProgramParser.ProceduredefContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#statement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitStatement(WormsProgramParser.StatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#assignmentStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAssignmentStatement(WormsProgramParser.AssignmentStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#whileStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitWhileStatement(WormsProgramParser.WhileStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#ifStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIfStatement(WormsProgramParser.IfStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#printStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitPrintStatement(WormsProgramParser.PrintStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#sequenceStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSequenceStatement(WormsProgramParser.SequenceStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#invokeStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitInvokeStatement(WormsProgramParser.InvokeStatementContext ctx); + /** + * Visit a parse tree produced by {@link WormsProgramParser#breakStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitBreakStatement(WormsProgramParser.BreakStatementContext ctx); + /** + * Visit a parse tree produced by the {@code turnAction} + * labeled alternative in {@link WormsProgramParser#actionStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTurnAction(WormsProgramParser.TurnActionContext ctx); + /** + * Visit a parse tree produced by the {@code moveAction} + * labeled alternative in {@link WormsProgramParser#actionStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMoveAction(WormsProgramParser.MoveActionContext ctx); + /** + * Visit a parse tree produced by the {@code jumpAction} + * labeled alternative in {@link WormsProgramParser#actionStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitJumpAction(WormsProgramParser.JumpActionContext ctx); + /** + * Visit a parse tree produced by the {@code eatAction} + * labeled alternative in {@link WormsProgramParser#actionStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitEatAction(WormsProgramParser.EatActionContext ctx); + /** + * Visit a parse tree produced by the {@code fireAction} + * labeled alternative in {@link WormsProgramParser#actionStatement}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFireAction(WormsProgramParser.FireActionContext ctx); + /** + * Visit a parse tree produced by the {@code distanceExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitDistanceExpression(WormsProgramParser.DistanceExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code cosExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitCosExpression(WormsProgramParser.CosExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getYExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetYExpression(WormsProgramParser.GetYExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code andOrExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAndOrExpression(WormsProgramParser.AndOrExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code isWormExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIsWormExpression(WormsProgramParser.IsWormExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code notExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNotExpression(WormsProgramParser.NotExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code comparisonExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitComparisonExpression(WormsProgramParser.ComparisonExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code parenExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitParenExpression(WormsProgramParser.ParenExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getRadiusExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetRadiusExpression(WormsProgramParser.GetRadiusExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code trueLiteralExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitTrueLiteralExpression(WormsProgramParser.TrueLiteralExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code nullExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitNullExpression(WormsProgramParser.NullExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code sqrtExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSqrtExpression(WormsProgramParser.SqrtExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code sinExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSinExpression(WormsProgramParser.SinExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code sameTeamExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSameTeamExpression(WormsProgramParser.SameTeamExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code isProjectileExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIsProjectileExpression(WormsProgramParser.IsProjectileExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code isFoodExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitIsFoodExpression(WormsProgramParser.IsFoodExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code constantExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitConstantExpression(WormsProgramParser.ConstantExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code searchObjExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSearchObjExpression(WormsProgramParser.SearchObjExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getXExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetXExpression(WormsProgramParser.GetXExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code readVariableExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitReadVariableExpression(WormsProgramParser.ReadVariableExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code mulDivExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitMulDivExpression(WormsProgramParser.MulDivExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getDirectionExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetDirectionExpression(WormsProgramParser.GetDirectionExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code selfExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitSelfExpression(WormsProgramParser.SelfExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getHPExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetHPExpression(WormsProgramParser.GetHPExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code addSubExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitAddSubExpression(WormsProgramParser.AddSubExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getMaxAPExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetMaxAPExpression(WormsProgramParser.GetMaxAPExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code getAPExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitGetAPExpression(WormsProgramParser.GetAPExpressionContext ctx); + /** + * Visit a parse tree produced by the {@code falseLiteralExpression} + * labeled alternative in {@link WormsProgramParser#expression}. + * @param ctx the parse tree + * @return the visitor result + */ + T visitFalseLiteralExpression(WormsProgramParser.FalseLiteralExpressionContext ctx); +} \ No newline at end of file diff --git a/OGP1718-Worms/src-provided/worms/util/ModelException.java b/OGP1718-Worms/src-provided/worms/util/ModelException.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/src-provided/worms/util/MustNotImplementException.java b/OGP1718-Worms/src-provided/worms/util/MustNotImplementException.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/tests/worms/model/Part3_FullFacadeTest.java b/OGP1718-Worms/tests/worms/model/Part3_FullFacadeTest.java new file mode 100755 index 0000000..050b8d6 --- /dev/null +++ b/OGP1718-Worms/tests/worms/model/Part3_FullFacadeTest.java @@ -0,0 +1,4262 @@ +package worms.model; + +import static java.lang.Math.*; +import static org.junit.Assert.*; + +import java.util.*; +import java.util.stream.IntStream; +import java.math.BigInteger; + +import org.junit.*; + +import worms.facade.Facade; +import worms.facade.IFacade; +import worms.internal.gui.game.IActionHandler; +import worms.programs.IProgramFactory; +import worms.programs.ProgramFactory; +import worms.programs.ProgramParser; +import worms.util.*; + +public class Part3_FullFacadeTest { + + private static int max_score = 0; + private static int score = 0; + + private static final double EPS = 1e-3; + + public final static double GAME_STANDARD_ACCELERATION = 5.0; + + private final static IFacade facade = new Facade(); + private final static IActionHandler actionHandler = new SimpleActionHandler(facade); + private final static ProgramFactory programFactory = new ProgramFactory(); + + private static final double[] FIXTURE_LOCATION = new double[] { 3.0, -7.0 }; + private static final double FIXTURE_RADIUS = 0.30; + private static final String FIXTURE_NAME = "Test"; + private static final double FIXTURE_DIRECTION = 3 * PI / 7; + private static final int FIXTURE_MAX_ACTION_POINTS = referenceMaxActionPoints(FIXTURE_RADIUS); + private static Worm fixtureWorm; + private static Food fixtureFood; + + private boolean[][] map10x10, map5x5; + private static World theWorld, otherWorld; + private static Team theTeam = null; + + @Before + public void setUp() { + fixtureWorm = facade.createWorm(null, FIXTURE_LOCATION, FIXTURE_DIRECTION, FIXTURE_RADIUS, FIXTURE_NAME, null); + fixtureFood = facade.createFood(null, FIXTURE_LOCATION); + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + map5x5 = new boolean[][] { { false, false, false, false, false, }, { true, true, true, true, true, }, + { true, true, true, true, true, }, { true, true, true, true, true, }, + { true, true, true, true, true, }, }; + otherWorld = facade.createWorld(5.0, 5.0, map5x5); + try { + theTeam = facade.createTeam(theWorld, "TheTeam"); + } catch (MustNotImplementException exc) { + } + } + + @AfterClass + public static void tearDownAfterClass() { + System.out.println(); + System.out.println("==============================="); + System.out.println(); + System.out.println(" FINAL SCORE: " + score + "/" + max_score); + System.out.println(); + System.out.println(" FINAL PERCENTAGE: " + Math.round(score*100/max_score) + "%"); + System.out.println(); + } + + /********************** + * AUXILIARY METHODS + **********************/ + + private static final double DENSITY = 1062; + + private static final double referenceWormMass(double radius) { + return DENSITY * (4.0 / 3.0 * PI * pow(radius, 3)); + } + + private static int referenceMaxActionPoints(double radius) { + return (int) round(referenceWormMass(radius)); + } + + private static final double FULL_TURN_COST = 60; + + private static int referenceCostToTurn(double angle) { + return (int) ceil(FULL_TURN_COST * abs(angle) / 2 / PI); + } + + private static double referenceJumpDistance(int actionPoints, double radius, double theta) { + double v0 = referenceJumpV0(actionPoints, radius); + double d = v0 * v0 * sin(2 * theta) / GAME_STANDARD_ACCELERATION; + return d; + } + + private static double[] referenceJumpStep(double dt, double[] loc, long actionPoints, double radius, double theta) { + double v0 = referenceJumpV0(actionPoints, radius); + double v0x = v0 * cos(theta); + double v0y = v0 * sin(theta); + double x = loc[0] + v0x * dt; + double y = loc[1] + v0y * dt - GAME_STANDARD_ACCELERATION * dt * dt / 2; + return new double[] { x, y }; + } + + private static double referenceJumpTime(int actionPoints, double radius, double theta) { + double v0 = referenceJumpV0(actionPoints, radius); + double t = referenceJumpDistance(actionPoints, radius, theta) / (v0 * cos(theta)); + return t; + } + + private static double referenceJumpV0(long actionPoints, double radius) { + double force = (5 * actionPoints) + (referenceWormMass(radius) * GAME_STANDARD_ACCELERATION); + double v0 = 0.5 * force / referenceWormMass(radius); + return v0; + } + + private static double getDistance(double[] p1, double[] p2) { + double dx = p1[0]-p2[0]; + double dy = p1[1]-p2[1]; + return Math.sqrt(dx*dx + dy*dy); + } + + + /************** + * WORLD TESTS + *************/ + + @Test + public void createWorld_LegalCase() { + max_score += 10; + boolean[][] passableMap = new boolean[][] { { true, false, true, true, false }, + { false, false, true, true, true }, { true, true, true, true, false }, + { false, false, false, false, false } }; + World theWorld = facade.createWorld(5.0, 4.0, passableMap); + assertEquals(5.0, facade.getWorldWidth(theWorld), EPS); + assertEquals(4.0, facade.getWorldHeight(theWorld), EPS); + assertFalse(facade.hasActiveGame(theWorld)); + score += 1; + assertTrue(facade.isPassable(theWorld, new double[] { 0.5, 3.5 })); + assertFalse(facade.isPassable(theWorld, new double[] { 4.5, 3.5 })); + assertTrue(facade.isPassable(theWorld, new double[] { 2.5, 2.5 })); + assertTrue(facade.isPassable(theWorld, new double[] { 0.5, 3.5 })); + assertFalse(facade.isPassable(theWorld, new double[] { 0.5, 0.5 })); + assertFalse(facade.isPassable(theWorld, new double[] { 3.5, 0.5 })); + score += 7; + assertEquals(0, facade.getAllItems(theWorld).size()); + score += 1; + try { + assertEquals(0, facade.getAllTeams(theWorld).size()); + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + @Test + public void createWorld_IllegalDimension() { + max_score += 1; + boolean[][] passableMap = new boolean[][] { { true, false, true, true, false }, + { false, false, true, true, true }, { true, true, true, true, false }, + { false, false, false, false, false } }; + try { + facade.createWorld(-1.0, 4.0, passableMap); + fail(); + } catch (ModelException exc) { + } + try { + facade.createWorld(10.0, Double.NaN, passableMap); + fail(); + } catch (ModelException exc) { + } + score += 1; + } + + @Test + public void createWorld_IllegalMap() { + max_score += 5; + // No effective map. + try { + facade.createWorld(10.0, 4.0, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Map with no cells. + try { + facade.createWorld(10.0, 4.0, new boolean[0][0]); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Non-rectangular map + try { + boolean[][] passableMap = new boolean[][] { { true, false, true, true }, { false, false, true, true, true }, + { true, true, true, true, false }, { false, false, false } }; + facade.createWorld(10.0, Double.NaN, passableMap); + fail(); + } catch (ModelException exc) { + score += 3; + } + } + + @Test + public void terminateWorld_EmptyWorld() { + max_score += 1; + facade.terminate(theWorld); + assertEquals(0, facade.getAllItems(theWorld).size()); + try { + assertEquals(0, facade.getAllTeams(theWorld).size()); + } catch (MustNotImplementException exc) { + max_score -= 1; + } + score += 1; + } + + @Test + public void terminateWorld_WorldWithGameObjects() { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.5, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 6.0, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + facade.terminate(theWorld); + assertEquals(0, facade.getAllItems(theWorld).size()); + assertNull(facade.getWorld(worm1)); + assertNull(facade.getWorld(worm2)); + score += 4; + } + + @Test + public void terminateWorld_WorldWithTeams() { + max_score += 2; + try { + facade.createTeam(theWorld, "TeamA"); + facade.createTeam(theWorld, "TeamB"); + facade.terminate(theWorld); + assertEquals(0, facade.getAllTeams(theWorld).size()); + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void isPassablePoint_TrueCases() { + max_score += 2; + assertTrue(facade.isPassable(theWorld, new double[] { 4.0, 6.0 })); + assertTrue(facade.isPassable(theWorld, new double[] { 0.0, 8.99 })); + assertTrue(facade.isPassable(theWorld, new double[] { 8.99, 0.0 })); + assertTrue(facade.isPassable(theWorld, new double[] { 8.99, 8.99 })); + score += 2; + } + + @Test + public void isPassablePoint_FalseCases() { + max_score += 2; + assertFalse(facade.isPassable(theWorld, new double[] { 9.3, 9.7 })); + assertFalse(facade.isPassable(theWorld, new double[] { 9.01, 0.0 })); + assertFalse(facade.isPassable(theWorld, new double[] { 9.01, 0.0 })); + assertFalse(facade.isPassable(theWorld, new double[] { 9.01, 9.01 })); + score += 2; + } + + @Test + public void isPassablePoint_OutsideWorld() { + max_score += 2; + assertTrue(facade.isPassable(theWorld, new double[] { 10.0, 12.0 })); + assertTrue(facade.isPassable(theWorld, new double[] { Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY })); + score += 2; + } + + @Test + public void isPassableArea_TrueCases() { + max_score += 4; + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + assertTrue(facade.isPassable(theWorld, new double[] { 3.0, 7.0 }, 1.95)); + assertTrue(facade.isPassable(theWorld, new double[] { 3.0, 3.0 }, 1.95)); + assertTrue(facade.isPassable(theWorld, new double[] { 7.0, 7.0 }, 1.95)); + assertTrue(facade.isPassable(theWorld, new double[] { 7.0, 3.0 }, 1.95)); + score += 4; + } + + @Test + public void isPassableArea_FalseCases() { + max_score += 4; + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + //False cases completely in world + assertFalse(facade.isPassable(theWorld, new double[] { 3.0, 7.3 }, 1.95)); + assertFalse(facade.isPassable(theWorld, new double[] { 3.0, 2.9 }, 1.95)); + assertFalse(facade.isPassable(theWorld, new double[] { 7.1, 7.0 }, 1.95)); + assertFalse(facade.isPassable(theWorld, new double[] { 7.0, 2.9 }, 1.95)); + score += 4; + } + + @Test + public void isPassableArea_AreasNotCompleteltInWorld() { + max_score += 4; + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + assertFalse(facade.isPassable(theWorld, new double[] { 3.0, 7.3 }, 3.95)); + assertTrue(facade.isPassable(theWorld, new double[] { 20.0, -10.0 }, 1.95)); + score += 4; + } + + @Test + public void isAdjacent_TrueCases() { + max_score += 6; + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + assertTrue(facade.isAdjacent(theWorld, new double[] { 3.00, 7.95 }, 1.00)); + assertTrue(facade.isAdjacent(theWorld, new double[] { 2.05, 3.00 }, 1.00)); + assertTrue(facade.isAdjacent(theWorld, new double[] { 7.00, 2.05 }, 1.00)); + assertTrue(facade.isAdjacent(theWorld, new double[] { 3.00, 7.95 }, 1.00)); + score += 6; + } + + @Test + public void isAdjacent_FalseCases() { + max_score += 8; + map10x10 = new boolean[][] { { false, false, false, false, false, false, false, false, false, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + theWorld = facade.createWorld(10.0, 10.0, map10x10); + assertFalse(facade.isAdjacent(theWorld, new double[] { 3.00, 7.85 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 3.00, 8.05 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 2.15, 3.00 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 1.95, 3.00 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 7.00, 2.15 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 7.00, 1.95 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 3.00, 7.85 }, 1.00)); + assertFalse(facade.isAdjacent(theWorld, new double[] { 3.00, 8.05 }, 1.00)); + score += 8; + } + + @Test + public void addWorm_LegalCase() { + max_score += 5; + Worm wormToAdd = facade.createWorm(null, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + facade.addWorm(theWorld, wormToAdd); + assertEquals(theWorld, facade.getWorld(wormToAdd)); + assertTrue(facade.hasAsWorm(theWorld, wormToAdd)); + score += 5; + } + + @Test + public void addWorm_TerminatedWorld() { + max_score += 1; + Worm wormToAdd = facade.createWorm(null, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + facade.terminate(theWorld); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_WorldWithActiveGame() { + max_score += 1; + Worm wormToAdd = facade.createWorm(null, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + facade.startGame(theWorld); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_NonEffectiveWorm() { + max_score += 1; + try { + facade.addWorm(theWorld, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_TerminatedWorm() { + max_score += 1; + Worm wormToAdd = facade.createWorm(null, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + facade.terminate(wormToAdd); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_WormAlreadyInWorld() { + max_score += 1; + Worm wormToAdd = facade.createWorm(theWorld, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_WormInOtherWorld() { + max_score += 1; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm wormToAdd = facade.createWorm(theWorld, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + try { + facade.addWorm(otherWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void addWorm_NotFullyInWorld() { + max_score += 5; + Worm wormToAdd = facade.createWorm(null, new double[] { 1.8, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 5; + } + } + + @Test + public void addWorm_NotFullyOnPassableTerrain() { + max_score += 10; + Worm wormToAdd = facade.createWorm(null, new double[] { 7.5, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 10; + } + } + + @Test + public void addWorm_NotAdjacentToImpassableTerrain() { + max_score += 3; + Worm wormToAdd = facade.createWorm(null, new double[] { 3.0, 6.5 }, FIXTURE_DIRECTION, 1.95, "Addy", null); + try { + facade.addWorm(theWorld, wormToAdd); + fail(); + } catch (ModelException exc) { + score += 3; + } + } + + @Test + public void removeWorm_LegalCase() { + max_score += 5; + Worm wormToRemove = facade.createWorm(theWorld, new double[] { 3.0, 7.0 }, FIXTURE_DIRECTION, 1.95, "Addy", + null); + facade.removeWorm(theWorld, wormToRemove); + assertEquals(null, facade.getWorld(wormToRemove)); + assertFalse(facade.hasAsWorm(theWorld, wormToRemove)); + score += 5; + } + + @Test + public void removeWorm_NonEffectiveWorm() { + max_score += 1; + try { + facade.removeWorm(theWorld, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void removeWorm_WormNotInWorld() { + max_score += 1; + try { + facade.removeWorm(theWorld, fixtureWorm); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void getAllWorms_BasicCase() { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.5, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 6.0, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + List allWorms = facade.getAllWorms(theWorld); + assertEquals(2, allWorms.size()); + assertTrue(allWorms.contains(worm1)); + assertTrue(allWorms.contains(worm2)); + score += 3; + } + + @Test + public void getAllWorms_LeakTest() { + max_score += 8; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.5, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 6.0, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + List allWorms = facade.getAllWorms(theWorld); + allWorms.remove(worm2); + assertTrue(facade.hasAsWorm(theWorld, worm2)); + allWorms.add(fixtureWorm); + facade.removeWorm(theWorld, worm2); + assertEquals(1, facade.getAllWorms(theWorld).size()); + score += 8; + } + + @Test + public void addFood_LegalCase() { + max_score += 3; + Food foodToAdd = facade.createFood(null, new double[] { 8.795, 7.0 }); + facade.addFood(theWorld, foodToAdd); + assertEquals(theWorld, facade.getWorld(foodToAdd)); + assertTrue(facade.hasAsFood(theWorld, foodToAdd)); + score += 3; + } + + @Test + public void addFood_NotAdjacentToImpassableTerrain() { + max_score += 1; + Food foodToAdd = facade.createFood(null, new double[] { 6.3, 7.0 }); + try { + facade.addFood(theWorld, foodToAdd); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void removeFood_LegalCase() { + max_score += 3; + Food foodToRemove = facade.createFood(theWorld, new double[] { 3.0, 8.79 }); + facade.removeFood(theWorld, foodToRemove); + assertEquals(null, facade.getWorld(foodToRemove)); + assertFalse(facade.hasAsFood(theWorld, foodToRemove)); + score += 3; + } + + @Test + public void removeFood_FoodNotInWorld() { + max_score += 1; + try { + facade.removeFood(theWorld, fixtureFood); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void getAllItems_BasicCase() { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.5, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 6.0, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + Food food1 = facade.createFood(theWorld, new double[] { 0.22, 8.79 }); + Food food2 = facade.createFood(theWorld, new double[] { 8.79, 8.79 }); + Collection allItems = facade.getAllItems(theWorld); + assertEquals(4, allItems.size()); + assertTrue(allItems.contains(worm1)); + assertTrue(allItems.contains(worm2)); + assertTrue(allItems.contains(food1)); + assertTrue(allItems.contains(food2)); + score += 3; + } + + @Test + public void getAllItems_LeakTest() { + max_score += 6; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.5, 8.0 }, FIXTURE_DIRECTION, 0.95, "Addy", null); + facade.createFood(theWorld, new double[] { 0.22, 8.79 }); + Collection allItems = facade.getAllItems(theWorld); + allItems.remove(worm1); + assertTrue(facade.hasAsWorm(theWorld, worm1)); + allItems.add(fixtureWorm); + assertEquals(1, facade.getAllWorms(theWorld).size()); + score += 6; + } + + @Test + public void getAllTeams_BasicCase() { + max_score += 2; + try { + Team team1 = facade.createTeam(theWorld, "TeamA"); + Team team2 = facade.createTeam(theWorld, "TeamB"); + Set allTeams = facade.getAllTeams(theWorld); + assertEquals(3, allTeams.size()); + assertTrue(allTeams.contains(team1)); + assertTrue(allTeams.contains(team2)); + assertTrue(allTeams.contains(theTeam)); + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void getAllTeams_LeakTest() { + max_score += 6; + try { + Team team1 = facade.createTeam(theWorld, "TeamA"); + facade.createTeam(theWorld, "TeamB"); + Set allTeams = facade.getAllTeams(theWorld); + allTeams.remove(team1); + assertTrue(facade.getAllTeams(theWorld).contains(team1)); + Team team3 = facade.createTeam(null, "TeamC"); + allTeams.add(team3); + assertEquals(3, facade.getAllTeams(theWorld).size()); + score += 6; + } catch (MustNotImplementException exc) { + max_score -= 6; + } + } + + @Test + public void getActiveWorm_NoActiveGame() { + max_score += 1; + assertNull(facade.getActiveWorm(theWorld)); + score += 1; + } + + @Test + public void getActiveWorm_NoWormsInWorld() { + max_score += 1; + facade.startGame(theWorld); + assertNull(facade.getActiveWorm(theWorld)); + score += 1; + } + + @Test + public void getActiveWorm_WormsInWorld() { + max_score += 2; + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "WormA", null); + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "WormB", null); + facade.startGame(theWorld); + assertTrue(facade.getAllWorms(theWorld).contains(facade.getActiveWorm(theWorld))); + score += 2; + } + + @Test + public void startGame_SingleWormInWorld() { + max_score += 4; + Worm worm = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "Worm", null); + facade.decreaseNbActionPoints(worm, 20); + BigInteger nbHitPoints = facade.getNbHitPoints(worm); + facade.startGame(theWorld); + assertEquals(worm, facade.getActiveWorm(theWorld)); + assertEquals(facade.getMaxNbActionPoints(worm), facade.getNbActionPoints(worm)); + assertEquals(nbHitPoints.add(BigInteger.TEN), facade.getNbHitPoints(worm)); + score += 4; + } + + @Test + public void startGame_SeveralWormsInWorld() { + max_score += 6; + Worm wormA = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "WormA", null); + Worm wormB = facade.createWorm(theWorld, new double[] { 2.1, 6.99 }, 0.4, 2.0, "WormB", null); + Worm wormC = facade.createWorm(theWorld, new double[] { 8.48, 8.48 }, 4.5, 0.5, "WormC", null); + facade.decreaseNbActionPoints(wormA, 20); + BigInteger nbHitPointsA = facade.getNbHitPoints(wormA); + facade.decreaseNbActionPoints(wormB, 20); + BigInteger nbHitPointsB = facade.getNbHitPoints(wormB); + facade.decreaseNbActionPoints(wormC, 20); + BigInteger nbHitPointsC = facade.getNbHitPoints(wormA); + facade.startGame(theWorld); + Worm activeWorm = facade.getActiveWorm(theWorld); + assertTrue(facade.getAllWorms(theWorld).contains(activeWorm)); + if (activeWorm == wormA) { + assertEquals(facade.getMaxNbActionPoints(wormA), facade.getNbActionPoints(wormA)); + assertEquals(nbHitPointsA.add(BigInteger.TEN), facade.getNbHitPoints(wormA)); + } + if (activeWorm == wormB) { + assertEquals(facade.getMaxNbActionPoints(wormB), facade.getNbActionPoints(wormB)); + assertEquals(nbHitPointsB.add(BigInteger.TEN), facade.getNbHitPoints(wormB)); + } + if (activeWorm == wormC) { + assertEquals(facade.getMaxNbActionPoints(wormC), facade.getNbActionPoints(wormC)); + assertEquals(nbHitPointsC.add(BigInteger.TEN), facade.getNbHitPoints(wormC)); + } + score += 6; + } + + @Test + public void finishGame_RegularCase() { + max_score += 1; + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "Worm", null); + facade.startGame(theWorld); + facade.finishGame(theWorld); + assertNull(facade.getActiveWorm(theWorld)); + score += 1; + } + + @Test + public void finishGame_NoActiveGame() { + max_score += 1; + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "Worm", null); + facade.finishGame(theWorld); + assertNull(facade.getActiveWorm(theWorld)); + score += 1; + } + + @Test + public void activateNextWorm_SeveralWorms() { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Worm worm3 = facade.createWorm(theWorld, new double[] { 6.5, 7.95 }, 0.1, 1.0, "ThirdWorm", null); + facade.startGame(theWorld); + Set activatedWorms = new HashSet<>(); + activatedWorms.add(facade.getActiveWorm(theWorld)); + facade.activateNextWorm(theWorld); + activatedWorms.add(facade.getActiveWorm(theWorld)); + facade.activateNextWorm(theWorld); + activatedWorms.add(facade.getActiveWorm(theWorld)); + assertTrue(activatedWorms.contains(worm1)); + assertTrue(activatedWorms.contains(worm2)); + assertTrue(activatedWorms.contains(worm3)); + score += 2; + } + + @Test + public void activateNextWorm_WormsLeavingWorld() { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Worm worm3 = facade.createWorm(theWorld, new double[] { 6.5, 7.95 }, 0.1, 1.0, "ThirdWorm", null); + facade.startGame(theWorld); + Worm firstActivatedWorm = facade.getActiveWorm(theWorld); + if (firstActivatedWorm == worm1) { + facade.removeWorm(theWorld, worm2); + facade.activateNextWorm(theWorld); + assertEquals(worm3, facade.getActiveWorm(theWorld)); + } else if (firstActivatedWorm == worm2) { + facade.removeWorm(theWorld, worm3); + facade.activateNextWorm(theWorld); + assertEquals(worm1, facade.getActiveWorm(theWorld)); + } else { + facade.removeWorm(theWorld, worm1); + facade.activateNextWorm(theWorld); + assertEquals(worm2, facade.getActiveWorm(theWorld)); + } + score += 4; + } + + @Test + public void activateNextWorm_NoMoreActiveWorms() { + max_score += 1; + Worm worm = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "Worm", null); + facade.startGame(theWorld); + facade.removeWorm(theWorld, worm); + facade.activateNextWorm(theWorld); + assertNull(facade.getActiveWorm(theWorld)); + score += 1; + } + + @Test + public void getWinner_NoActiveGame() { + max_score += 1; + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "Worm", null); + assertNull(facade.getWinner(theWorld)); + score += 1; + } + + @Test + public void getWinner_WinningWorm() { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Worm worm3 = facade.createWorm(theWorld, new double[] { 6.5, 7.95 }, 0.1, 1.0, "ThirdWorm", null); + facade.startGame(theWorld); + facade.removeWorm(theWorld, worm3); + facade.activateNextWorm(theWorld); + facade.removeWorm(theWorld, worm2); + facade.activateNextWorm(theWorld); + facade.activateNextWorm(theWorld); + assertEquals(facade.getName(worm1), facade.getWinner(theWorld)); + score += 4; + } + + @Test + public void getWinner_WinningTeam() { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Worm worm3 = facade.createWorm(theWorld, new double[] { 6.5, 7.95 }, 0.1, 1.0, "ThirdWorm", null); + Team someTeam = facade.createTeam(theWorld, "SomeTeam"); + facade.addWormsToTeam(someTeam, worm1, worm3); + facade.startGame(theWorld); + facade.activateNextWorm(theWorld); + facade.removeWorm(theWorld, worm2); + facade.activateNextWorm(theWorld); + facade.activateNextWorm(theWorld); + assertEquals(facade.getName(someTeam), facade.getWinner(theWorld)); + score += 4; + } + + @Test + public void getWinner_WorldWithoutWorms() { + max_score += 1; + facade.startGame(theWorld); + assertNull(facade.getWinner(theWorld)); + score += 1; + } + + @Test + public void getWinner_SeveralWormsNotInTeam() { + max_score += 1; + facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + facade.startGame(theWorld); + assertNull(facade.getWinner(theWorld)); + score += 1; + } + + @Test + public void getWinner_SeveralWormsInDifferentTeams() { + max_score += 1; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + Worm worm2 = facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Team teamA = facade.createTeam(theWorld, "TeamA"); + facade.addWormsToTeam(teamA, worm1); + Team teamB = facade.createTeam(theWorld, "TeamB"); + facade.addWormsToTeam(teamB, worm2); + facade.startGame(theWorld); + assertNull(facade.getWinner(theWorld)); + score += 1; + } + + @Test + public void getWinner_IndividualWormTeamWorm() { + max_score += 1; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.95, 4.0 }, 0.1, 1.0, "FirstWorm", null); + facade.createWorm(theWorld, new double[] { 2.5, 7.95 }, 0.1, 1.0, "SecondWorm", null); + Team teamA = facade.createTeam(theWorld, "TeamA"); + facade.addWormsToTeam(teamA, worm1); + facade.startGame(theWorld); + assertNull(facade.getWinner(theWorld)); + score += 1; + } + + /************** + * WORM TESTS + *************/ + + @Test + public void createWorm_LegalCaseNoWorldNoTeam() { + max_score += 12; + double[] location = new double[] { 3.0, -7.0 }; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + Worm newWorm = facade.createWorm(null, location, direction, radius, name, null); + assertNull(facade.getWorld(newWorm)); + assertNull(facade.getTeam(newWorm)); + assertEquals(location[0], facade.getLocation(newWorm)[0], EPS); + assertEquals(location[1], facade.getLocation(newWorm)[1], EPS); + score += 2; + assertEquals(direction, facade.getOrientation(newWorm), EPS); + score += 2; + assertEquals(radius, facade.getRadius(newWorm), EPS); + score += 2; + assertEquals(Math.round(facade.getMass(newWorm)), facade.getNbActionPoints(newWorm)); + assertEquals(Math.round(facade.getMass(newWorm)), facade.getMaxNbActionPoints(newWorm)); + score += 2; + assertEquals(name, facade.getName(newWorm)); + score += 2; + assertTrue(facade.getNbHitPoints(newWorm).compareTo(BigInteger.valueOf(1000)) >= 0); + assertTrue(facade.getNbHitPoints(newWorm).compareTo(BigInteger.valueOf(2000)) <= 0); + score += 2; + } + + @Test + public void createWorm_LegalCaseInWorld() { + max_score += 6; + double[] location = new double[] { 8.68, 8.68 }; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + Worm newWorm = facade.createWorm(theWorld, location, direction, radius, name, null); + assertEquals(theWorld, facade.getWorld(newWorm)); + assertTrue(facade.hasAsWorm(theWorld, newWorm)); + score += 6; + } + + @Test + public void createWorm_LegalCaseInTeam() { + max_score += 6; + double[] location = new double[] { 8.68, 8.68 }; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + try { + Worm newWorm = facade.createWorm(theWorld, location, direction, radius, name, theTeam); + assertEquals(theTeam, facade.getTeam(newWorm)); + assertEquals(1, facade.getAllWormsOfTeam(theTeam).size()); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(newWorm)); + score += 6; + } catch (MustNotImplementException exc) { + max_score -= 6; + } + } + + @Test + public void createWorm_IllegalWorld() { + max_score += 2; + World someWorld = facade.createWorld(10.0, 20.0, map10x10); + facade.terminate(someWorld); + try { + facade.createWorm(someWorld, new double[] { 8.68, 8.68 }, 0.3, 0.3, "Worm", null); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void createWorm_InfinitePosition() { + max_score += 3; + double[] location = new double[] { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY }; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + Worm newWorm = facade.createWorm(null, location, direction, radius, name, null); + assertEquals(Double.POSITIVE_INFINITY, facade.getLocation(newWorm)[0], EPS); + assertEquals(Double.NEGATIVE_INFINITY, facade.getLocation(newWorm)[1], EPS); + score += 3; + } + + @Test + public void createWorm_IllegalLocation() { + max_score += 2; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + // Illegal x-displacement + try { + double[] location = new double[] { Double.NaN, 1.0 }; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Illegal y-displacement + try { + double[] location = new double[] { 1.0, Double.NaN }; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void createWorm_IllegalOrientation() { + max_score += 2; + double[] location = new double[] { 3.0, -7.0 }; + double radius = 0.30; + String name = "Test"; + // Negative orientation + try { + double direction = -1.0; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Orientation too large + try { + double direction = 7.0; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Infinite Orientation + try { + double direction = Double.POSITIVE_INFINITY; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Orientation not a number + try { + double direction = Double.NaN; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + score += 2; + } + + @Test + public void createWorm_IllegalRadius() { + max_score += 2; + double[] location = new double[] { 3.0, -7.0 }; + double direction = 3 * PI / 7; + String name = "Test"; + // Radius below 0.25 + try { + double radius = 0.2; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Negative radius + try { + double radius = -4.0; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Infinite Radius + try { + double radius = Double.POSITIVE_INFINITY; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + // Radius not a number + try { + double radius = Double.NaN; + facade.createWorm(null, location, direction, radius, name, null); + fail(); + } catch (ModelException exc) { + } + score += 2; + } + + @Test + public void createWorm_IllegalTeam() { + max_score += 2; + double[] location = new double[] { 3.0, -7.0 }; + double direction = 3 * PI / 7; + String name = "Test"; + // Radius below 0.25 + try { + double radius = 0.2; + facade.createWorm(null, location, direction, radius, name, theTeam); + fail(); + } catch (ModelException exc) { + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + + } + + @Test + public void terminateWorm_NoWorldNoTeam() { + max_score += 1; + Worm someWorm = facade.createWorm(null, new double[] { -4.0, 7.0 }, 0.8, 1.0, "Worm", null); + facade.terminate(someWorm); + assertTrue(facade.isTerminated(someWorm)); + score += 1; + } + + @Test + public void terminateWorm_InWorldNoTeam() { + max_score += 1; + facade.terminate(fixtureWorm); + assertTrue(facade.isTerminated(fixtureWorm)); + assertNull(facade.getWorld(fixtureWorm)); + assertFalse(facade.hasAsWorm(theWorld, fixtureWorm)); + score += 1; + } + + @Test + public void terminateWorm_InWorldInTeam() { + max_score += 1; + try { + facade.addWormsToTeam(theTeam, fixtureWorm); + facade.terminate(fixtureWorm); + assertTrue(facade.isTerminated(fixtureWorm)); + assertNull(facade.getTeam(fixtureWorm)); + assertTrue(facade.getAllWormsOfTeam(theTeam).isEmpty()); + score += 1; + } catch (MustNotImplementException exc) { + max_score = -1; + } + } + + @Test + public void setRadius_IllegalValues() { + max_score += 1; + try { + facade.setRadius(fixtureWorm, 0.2); + fail(); + } catch (ModelException exc) { + } + try { + facade.setRadius(fixtureWorm, -0.5); + fail(); + } catch (ModelException exc) { + } + try { + facade.setRadius(fixtureWorm, Double.NaN); + fail(); + } catch (ModelException exc) { + } + score += 1; + } + + @Test + public void setRadius_LargerRadiusUpdatesMass() { + max_score += 2; + double newRadius = 2.0; + facade.setRadius(fixtureWorm, newRadius); + assertEquals(newRadius, facade.getRadius(fixtureWorm), EPS); + assertEquals(referenceWormMass(newRadius), facade.getMass(fixtureWorm), EPS); + score += 2; + } + + @Test + public void setRadius_LargerRadiusUpdatesMaxActionPoints() { + max_score += 2; + double newRadius = 2.0; + facade.setRadius(fixtureWorm, newRadius); + assertEquals(newRadius, facade.getRadius(fixtureWorm), EPS); + assertEquals(referenceMaxActionPoints(newRadius), facade.getMaxNbActionPoints(fixtureWorm)); + score += 2; + } + + @Test + public void setRadius_ShrinkingRadiusReducesActionPoints() { + max_score += 5; + Worm worm = fixtureWorm; + Assume.assumeTrue(referenceMaxActionPoints(FIXTURE_RADIUS) == facade.getNbActionPoints(worm)); + try { + facade.setRadius(worm, FIXTURE_RADIUS / 2); + assertEquals(FIXTURE_RADIUS / 2, facade.getRadius(worm), EPS); + assertEquals(referenceMaxActionPoints(FIXTURE_RADIUS / 2), facade.getMaxNbActionPoints(worm)); + assertEquals(facade.getMaxNbActionPoints(worm), facade.getNbActionPoints(worm)); + } catch (ModelException e) { + // interpretation 2: new radius is invalid + // ensure that nothing has been modified + assertEquals(FIXTURE_RADIUS, facade.getRadius(worm), EPS); + assertEquals(referenceMaxActionPoints(FIXTURE_RADIUS), facade.getMaxNbActionPoints(worm)); + assertEquals(facade.getMaxNbActionPoints(worm), facade.getNbActionPoints(worm)); + } + score += 5; + } + + @Test + public void setRadius_LargerRadiusOnImpasableTerrain() { + max_score += 5; + double[] location = new double[] { 1.0, 8.68 }; + double direction = 3 * PI / 7; + double radius = 0.30; + String name = "Test"; + Worm newWorm = facade.createWorm(theWorld, location, direction, radius, name, null); + try { + facade.setRadius(newWorm, 2.0); + fail(); + } catch (ModelException exc) { + score += 5; + } + } + + @Test + public void getMass_SingleCase() { + max_score += 2; + double expectedMass = 1062.0 * (4.0 / 3.0 * PI * pow(FIXTURE_RADIUS, 3)); + assertEquals(expectedMass, facade.getMass(fixtureWorm), EPS); + score += 2; + } + + @Test + public void decreaseActionPoints_LegalCase() { + max_score += 1; + long oldNbActionPoints = facade.getNbActionPoints(fixtureWorm); + facade.decreaseNbActionPoints(fixtureWorm, 3); + assertEquals(oldNbActionPoints - 3, facade.getNbActionPoints(fixtureWorm)); + score += 1; + } + + @Test + public void decreaseActionPoints_NegativeDelta() { + max_score += 1; + facade.decreaseNbActionPoints(fixtureWorm, 5); + long oldNbActionPoints = facade.getNbActionPoints(fixtureWorm); + facade.decreaseNbActionPoints(fixtureWorm, -3); + assertEquals(oldNbActionPoints + 3, facade.getNbActionPoints(fixtureWorm)); + score += 1; + } + + @Test + public void decreaseActionPoints_DeltaTooLarge() { + max_score += 1; + long oldNbActionPoints = facade.getNbActionPoints(fixtureWorm); + facade.decreaseNbActionPoints(fixtureWorm, Integer.MAX_VALUE); + assertEquals(oldNbActionPoints, facade.getNbActionPoints(fixtureWorm)); + score += 1; + } + + @Test + public void decreaseActionPoints_DeltaTooNegative() { + max_score += 1; + long oldNbActionPoints = facade.getNbActionPoints(fixtureWorm); + long maxNbActionPoints = facade.getMaxNbActionPoints(fixtureWorm); + long delta = oldNbActionPoints - maxNbActionPoints - 10; + facade.decreaseNbActionPoints(fixtureWorm, delta); + assertEquals(oldNbActionPoints, facade.getNbActionPoints(fixtureWorm)); + score += 1; + } + + @Test + public void incrementHitPoints_LegalCase() { + max_score += 2; + BigInteger oldNbHitPoints = facade.getNbHitPoints(fixtureWorm); + facade.incrementNbHitPoints(fixtureWorm, 3); + assertEquals(oldNbHitPoints.add(BigInteger.valueOf(3)), facade.getNbHitPoints(fixtureWorm)); + score += 1; + oldNbHitPoints = facade.getNbHitPoints(fixtureWorm); + facade.incrementNbHitPoints(fixtureWorm, -100); + assertEquals(oldNbHitPoints.add(BigInteger.valueOf(-100)), facade.getNbHitPoints(fixtureWorm)); + score += 1; + } + + @Test + public void incrementHitPoints_ZeroCase() { + max_score += 2; + BigInteger oldNbHitPoints = facade.getNbHitPoints(fixtureWorm); + facade.incrementNbHitPoints(fixtureWorm, -oldNbHitPoints.longValue()); + assertEquals(BigInteger.ZERO, facade.getNbHitPoints(fixtureWorm)); + assertTrue(facade.isTerminated(fixtureWorm)); + score += 2; + } + + @Test + public void incrementHitPoints_NegativeCase() { + max_score += 2; + BigInteger oldNbHitPoints = facade.getNbHitPoints(fixtureWorm); + facade.incrementNbHitPoints(fixtureWorm, -2 * oldNbHitPoints.longValue()); + assertEquals(BigInteger.ZERO, facade.getNbHitPoints(fixtureWorm)); + assertTrue(facade.isTerminated(fixtureWorm)); + score += 2; + } + + @Test + public void rename_LegalCases() { + max_score += 3; + Worm worm = fixtureWorm; + facade.rename(worm, "John"); + assertEquals("John", facade.getName(worm)); + facade.rename(worm, "James o'Hara"); + assertEquals("James o'Hara", facade.getName(worm)); + facade.rename(worm, "J "); + assertEquals("J ", facade.getName(worm)); + facade.rename(worm, "J\""); + assertEquals("J\"", facade.getName(worm)); + facade.rename(worm, "J_a_"); + assertEquals("J_a_", facade.getName(worm)); + score += 3; + } + + @Test + public void rename_NameTooShort() { + max_score += 1; + try { + facade.rename(fixtureWorm, "J"); + fail(); + } catch (ModelException exc) { + } + try { + facade.rename(fixtureWorm, ""); + fail(); + } catch (ModelException exc) { + } + score += 1; + } + + @Test + public void rename_NameWithIllegalCharacters() { + max_score += 1; + try { + facade.rename(fixtureWorm, "John123"); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void rename_NameWithoutStartingCapital() { + max_score += 1; + try { + facade.rename(fixtureWorm, "john"); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void rename_NullName() { + max_score += 1; + try { + facade.rename(fixtureWorm, null); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void turn_HalfTurn() { + max_score += 1; + facade.turn(fixtureWorm, PI); + assertEquals(PI + FIXTURE_DIRECTION, facade.getOrientation(fixtureWorm), EPS); + assertEquals(referenceCostToTurn(PI), + facade.getMaxNbActionPoints(fixtureWorm) - facade.getNbActionPoints(fixtureWorm)); + score += 1; + } + + @Test + public void turn_QuarterTurnNegative() { + max_score += 2; + facade.turn(fixtureWorm, PI); + facade.turn(fixtureWorm, -PI / 2); + assertEquals(PI + FIXTURE_DIRECTION - PI / 2, facade.getOrientation(fixtureWorm), EPS); + assertEquals(referenceCostToTurn(PI + PI / 2), + facade.getMaxNbActionPoints(fixtureWorm) - facade.getNbActionPoints(fixtureWorm)); + score += 2; + } + + @Test + public void turn_IllegalAngles() { + max_score += 3; + try { + facade.turn(fixtureWorm, -7); + fail(); + } catch (ModelException exc) { + } + try { + facade.turn(fixtureWorm, +7); + fail(); + } catch (ModelException exc) { + } + try { + facade.turn(fixtureWorm, Double.NaN); + fail(); + } catch (ModelException exc) { + } + score += 3; + } + + @Test + public void getFurthestLocationInDirection_WormNotInWorld() { + max_score += 5; + Worm theWorm = facade.createWorm(null, new double[] { 8.0, 4.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + double[] destination = facade.getFurthestLocationInDirection(theWorm, 3 * PI / 4, 2.0); + assertEquals(8.0 - Math.sqrt(2.0), destination[0], EPS); + assertEquals(4.0 + Math.sqrt(2.0), destination[1], EPS); + score += 5; + } + + @Test + public void getFurthestLocationInDirection_NoMovePossible() { + max_score += 3; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 4.0 }, 0.0, 1.0, "Worm", null); + double[] destination = facade.getFurthestLocationInDirection(theWorm, 0.3, 5.0); + assertEquals(facade.getLocation(theWorm)[0], destination[0], EPS); + assertEquals(facade.getLocation(theWorm)[1], destination[1], EPS); + score += 3; + } + + @Test + public void getFurthestLocationInDirection_MaximalMoveWithinWorld() { + max_score += 5; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 4.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + double[] destination = facade.getFurthestLocationInDirection(theWorm, 3 * PI / 4, 2.0); + assertEquals(8.0 - Math.sqrt(2.0), destination[0], EPS); + assertEquals(4.0 + Math.sqrt(2.0), destination[1], EPS); + score += 5; + } + + @Test + public void getFurthestLocationInDirection_MaximalMoveOutsideWorld() { + max_score += 5; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 1.0 }, 5 * PI / 6.0, 1.0, "Worm", null); + double[] destination = facade.getFurthestLocationInDirection(theWorm, 5 * PI / 6, 20.0); + assertEquals(8.0 + 20 * Math.cos(5 * PI / 6), destination[0], EPS); + assertEquals(1.0 + 20 * Math.sin(5 * PI / 6), destination[1], EPS); + score += 5; + } + + @Test + public void getFurthestLocationInDirection_NonMaximalMove() { + max_score += 8; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 3.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + double[] destination = facade.getFurthestLocationInDirection(theWorm, 3 * PI / 4, 10.0); + assertEquals(8.0 - 5.0, destination[0], EPS); + assertEquals(3.0 + 5.0, destination[1], EPS); + score += 8; + } + + @Test + public void getFurthestLocationInDirection_IllegalCases() { + max_score += 6; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 4.0 }, PI, 1.0, "Worm", null); + // Negative orientation + try { + facade.getFurthestLocationInDirection(theWorm, -0.5, 3.0); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Orientation not below 2*PI + try { + facade.getFurthestLocationInDirection(theWorm, 3 * PI, 3.0); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Orientation not a number + try { + facade.getFurthestLocationInDirection(theWorm, Double.NaN, 3.0); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Negative maximum distance + try { + facade.getFurthestLocationInDirection(theWorm, 0.5, -3.0); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Infinite maximum distance + try { + facade.getFurthestLocationInDirection(theWorm, 0.5, Double.POSITIVE_INFINITY); + fail(); + } catch (ModelException exc) { + score += 1; + } + // Maximum distance not a number + try { + facade.getFurthestLocationInDirection(theWorm, 0.5, Double.NaN); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void move_ReachingImpassableTerrainInDirection() { + max_score += 15; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 7.5 }, 3 * PI / 4.0, 1.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + double[] expectedLocation = new double[] {7.5,8.0}; + assertTrue(facade.isAdjacent(theWorld, newLocation, facade.getRadius(theWorm))); + assertEquals(expectedLocation[0]+facade.getRadius(theWorm)*0.1/2.0, newLocation[0], facade.getRadius(theWorm)*0.12/2.0); + assertEquals(expectedLocation[1]-facade.getRadius(theWorm)*0.1/2.0, newLocation[1], facade.getRadius(theWorm)*0.12/2.0); + // We allow a deviation of +/-1 in calculating the action points. + assertTrue((facade.getNbActionPoints(theWorm) >= oldNbActionPoints - 4) + && (facade.getNbActionPoints(theWorm) <= oldNbActionPoints - 2)); + score += 15; + } + + @Test + public void move_OnlyPassableTerrainInDirection() { + max_score += 15; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.0, 3.0 }, PI, 2.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + assertEquals(7.0 - 2.0, newLocation[0], EPS); + assertEquals(3.0, newLocation[1], EPS); + // We allow a deviation of +/-1 in calculating the action points. + assertTrue((facade.getNbActionPoints(theWorm) >= oldNbActionPoints - 3) + && (facade.getNbActionPoints(theWorm) <= oldNbActionPoints - 1)); + score += 15; + } + + @Test + public void move_ReachingImpassableTerrainDeviatingDirectionAlmostVertical() { + max_score += 15; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 5.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + // The worm will move in an almost vertical direction, such that he is still + // adjacent to the vertical wall. + double[] expectedLocation = new double[] {8.0,6.0}; + assertTrue(facade.isAdjacent(theWorld, newLocation, facade.getRadius(theWorm))); + assertEquals(expectedLocation[0]-facade.getRadius(theWorm)*0.1/2.0, newLocation[0], facade.getRadius(theWorm)*0.12/2.0); + assertEquals(expectedLocation[1]-facade.getRadius(theWorm)*0.1/2.0, newLocation[1], facade.getRadius(theWorm)*0.12/2.0); + assertTrue((facade.getNbActionPoints(theWorm) >= oldNbActionPoints - 5) + && (facade.getNbActionPoints(theWorm) <= oldNbActionPoints - 3)); + score += 15; + } + + @Test + public void move_ReachingImpassableTerrainDeviatingDirectionDiagonalDirection() { + max_score += 15; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm theWorm = facade.createWorm(otherWorld, new double[] { 7.0, 5.0 }, PI, 2.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + // The worm will move adjacent to the cell in row 7 and column 4. + assertTrue(facade.isAdjacent(otherWorld, newLocation, 2.0)); + double distanceToEdge = Math.sqrt(Math.pow(newLocation[0] - 5.0, 2.0) + Math.pow(newLocation[1] - 2.0, 2.0)); + assertEquals(2.1, distanceToEdge, 0.2); + assertTrue((facade.getNbActionPoints(theWorm) >= oldNbActionPoints - 5) + && (facade.getNbActionPoints(theWorm) <= oldNbActionPoints - 3)); + score += 15; + } + + @Test + public void move_ReachingImpassableTerrainDeviatingDirectionSeveralDirections() { + max_score += 15; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm theWorm = facade.createWorm(otherWorld, new double[] { 7.0, 5.0 }, PI, 2.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + // The worm will move adjacent to the cell in row 1 and column 6 or adjacent to + // row 9 and column 6. + assertTrue(facade.isAdjacent(otherWorld, newLocation, 2.0)); + double distanceToEdge = Math.min( + Math.sqrt(Math.pow(newLocation[0] - 5.0, 2.0) + Math.pow(newLocation[1] - 2.0, 2.0)), + Math.sqrt(Math.pow(newLocation[0] - 5.0, 2.0) + Math.pow(newLocation[1] - 8.0, 2.0)) ); + assertEquals(2.1, distanceToEdge, 0.2); + assertTrue((facade.getNbActionPoints(theWorm) >= oldNbActionPoints - 5) + && (facade.getNbActionPoints(theWorm) <= oldNbActionPoints - 3)); + score += 15; + } + + @Test + public void move_OverlappingWormAtDestination() { + max_score += 12; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 8.0 }, PI, 1.0, "Worm", null); + Worm otherWorm = facade.createWorm(theWorld, new double[] { 4.5, 7.0 }, 3 * PI / 4.0, 2.0, "WormA", null); + long oldHitPointsTheWorm = facade.getNbHitPoints(theWorm).longValue(); + long oldHitPointsOtherWorm = facade.getNbHitPoints(otherWorm).longValue(); + facade.move(theWorm); + long newHitPointsTheWorm = facade.getNbHitPoints(theWorm).longValue(); + long newHitPointOtherWorm = facade.getNbHitPoints(otherWorm).longValue(); + long deltaTheWorm = oldHitPointsTheWorm - newHitPointsTheWorm; + long deltaOtherWorm = oldHitPointsOtherWorm - newHitPointOtherWorm; + long delta = deltaTheWorm + deltaOtherWorm; + assertTrue((delta >= 1) && (delta <= 10)); + assertEquals(deltaTheWorm, Math.round(delta / (2.0 / 3.0))); + assertEquals(deltaOtherWorm, delta - deltaTheWorm); + score += 12; + } + + @Test + public void move_OverlappingWormsAtDestination() { + max_score += 14; + Worm theWorm = facade.createWorm(theWorld, new double[] { 6.0, 6.0 }, PI, 3.0, "Worm", null); + Worm otherWorm1 = facade.createWorm(theWorld, new double[] { 1.0, 8.0 }, 3 * PI / 4.0, 1.0, "WormA", null); + Worm otherWorm2 = facade.createWorm(theWorld, new double[] { 3.5, 7.5 }, 3 * PI / 4.0, 1.5, "WormB", null); + long oldHitPointsTheWorm = facade.getNbHitPoints(theWorm).longValue(); + long oldHitPointsOtherWorm1 = facade.getNbHitPoints(otherWorm1).longValue(); + long oldHitPointsOtherWorm2 = facade.getNbHitPoints(otherWorm2).longValue(); + facade.move(theWorm); + long newHitPointsTheWorm = facade.getNbHitPoints(theWorm).longValue(); + long newHitPointOtherWorm1 = facade.getNbHitPoints(otherWorm1).longValue(); + long newHitPointOtherWorm2 = facade.getNbHitPoints(otherWorm2).longValue(); + long deltaTheWorm = oldHitPointsTheWorm - newHitPointsTheWorm; + long deltaOtherWorm1 = oldHitPointsOtherWorm1 - newHitPointOtherWorm1; + long deltaOtherWorm2 = oldHitPointsOtherWorm2 - newHitPointOtherWorm2; + assertTrue(deltaTheWorm <= 0); + assertTrue((deltaOtherWorm1 >= 1) && (deltaOtherWorm1 <= 14)); + assertTrue((deltaOtherWorm2 >= 1) && (deltaOtherWorm2 <= 15)); + // Large margin to cope with possible rounding errors. + assertEquals(deltaTheWorm, (-deltaOtherWorm1 / 4.0) + (-deltaOtherWorm2 / 3.0), 1.0); + score += 14; + } + + @Test + public void move_DestinationOutsideWorld() { + max_score += 10; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 1.2 }, 3 * PI / 2.0, 1.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.move(theWorm); + double[] newLocation = facade.getLocation(theWorm); + assertEquals(8.0 - 0.0, newLocation[0], EPS); + assertEquals(1.2 - 1.0, newLocation[1], EPS); + assertEquals(oldNbActionPoints - (1 + 1 * 3), facade.getNbActionPoints(theWorm)); + assertNull(facade.getWorld(theWorm)); + assertFalse(facade.hasAsWorm(theWorld, theWorm)); + score += 10; + } + + @Test + public void move_WormNotInWorld() { + max_score += 2; + Worm theWorm = facade.createWorm(null, new double[] { 8.0, 1.2 }, 3 * PI / 2.0, 1.0, "Worm", null); + try { + facade.move(theWorm); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void move_NotEnoughActionPoints() { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 7.5 }, 3 * PI / 4.0, 1.0, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.decreaseNbActionPoints(theWorm, oldNbActionPoints - 1); + try { + facade.move(theWorm); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void move_TerminatedWorm() { + max_score += 1; + Worm theWorm = facade.createWorm(theWorld, new double[] { 8.0, 3.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + facade.terminate(theWorm); + try { + facade.move(theWorm); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void fall_InWorldNoOverlappingWorms() { + max_score += 15; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm theWorm = facade.createWorm(otherWorld, new double[] { 4.5, 6.0 }, PI, 2.0, "Worm", null); + try { + BigInteger oldNbHitPoints = facade.getNbHitPoints(theWorm); + facade.fall(theWorm); + double[] newLocation = facade.getLocation(theWorm); + assertTrue(facade.isAdjacent(otherWorld, newLocation, facade.getRadius(theWorm))); + assertEquals(4.5, newLocation[0], EPS); + assertEquals(3.0+facade.getRadius(theWorm)*0.1/2.0, newLocation[1], facade.getRadius(theWorm)*0.12/2.0); + assertEquals(oldNbHitPoints.subtract(BigInteger.valueOf(9)),facade.getNbHitPoints(theWorm) ); + score += 15; + } catch (MustNotImplementException exc) { + max_score -= 15; + } + } + + @Test + public void fall_InWorldOverlappingWorms() { + max_score += 12; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, false, false, false, true, true, true, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm theWorm = facade.createWorm(otherWorld, new double[] { 4.5, 6.0 }, PI, 2.0, "Worm", null); + Worm worm1 = facade.createWorm(otherWorld, new double[] { 5.5, 2.0 }, PI, 1.0, "WormA", null); + Worm worm2 = facade.createWorm(otherWorld, new double[] { 3.5, 2.0 }, PI, 1.0, "WormB", null); + try { + long oldNbHitPoints_TheWorm = facade.getNbHitPoints(theWorm).longValue(); + long oldNbHitPoints_worm1 = facade.getNbHitPoints(worm1).longValue(); + long oldNbHitPoints_worm2 = facade.getNbHitPoints(worm2).longValue(); + facade.fall(theWorm); + assertEquals(oldNbHitPoints_TheWorm - 9 + oldNbHitPoints_worm1 / 2 + oldNbHitPoints_worm2 / 2, + facade.getNbHitPoints(theWorm).longValue()); + assertEquals(facade.getNbHitPoints(worm1).longValue(), oldNbHitPoints_worm1 / 2); + assertEquals(facade.getNbHitPoints(worm2).longValue(), oldNbHitPoints_worm2 / 2); + score += 12; + } catch (MustNotImplementException exc) { + max_score -= 12; + } + } + + @Test + public void fall_OutOfWorld() { + max_score += 6; + // Worm hanging on the ceiling. + Worm theWorm = facade.createWorm(theWorld, new double[] { 3.0, 8.0 }, 3 * PI / 4.0, 1.0, "Worm", null); + try { + facade.fall(theWorm); + assertFalse(facade.hasAsWorm(theWorld, theWorm)); + assertNull(facade.getWorld(theWorm)); + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + // Worm hanging on side wall. + Worm otherWorm = facade.createWorm(theWorld, new double[] { 8.0, 3.0 }, 3 * PI / 4.0, 1.0, "WormB", null); + try { + facade.fall(otherWorm); + assertFalse(facade.hasAsWorm(theWorld, otherWorm)); + assertNull(facade.getWorld(otherWorm)); + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void jumpStep_LegalCase() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 2 * PI / 3.0; + double worm_radius = 1.5; + long worm_actionPoints = referenceMaxActionPoints(worm_radius); + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] expectedLocation = referenceJumpStep(0.1, worm_location, worm_actionPoints, worm_radius, + worm_orientation); + double[] stepLocation = facade.getJumpStep(theWorm, 0.1); + assertEquals("Result must have exactly 2 coordinates", 2, stepLocation.length); + assertEquals("x coordinate must match", expectedLocation[0], stepLocation[0], EPS); + assertEquals("y coordinate must match", expectedLocation[1], stepLocation[1], EPS); + score += 4; + } + + @Test + public void jumpStep_VerticalJump() { + max_score += 2; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + long worm_actionPoints = referenceMaxActionPoints(worm_radius); + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] expectedLocation = referenceJumpStep(0.1, worm_location, worm_actionPoints, worm_radius, + worm_orientation); + double[] stepLocation = facade.getJumpStep(theWorm, 0.1); + assertEquals("Result must have exactly 2 coordinates", 2, stepLocation.length); + assertEquals("x coordinate must match", expectedLocation[0], stepLocation[0], EPS); + assertEquals("y coordinate must match", expectedLocation[1], stepLocation[1], EPS); + score += 2; + } + + @Test + public void jumpStep_HorizontalJump() { + max_score += 2; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI; + double worm_radius = 1.5; + long worm_actionPoints = referenceMaxActionPoints(worm_radius); + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] expectedLocation = referenceJumpStep(0.1, worm_location, worm_actionPoints, worm_radius, + worm_orientation); + double[] stepLocation = facade.getJumpStep(theWorm, 0.1); + assertEquals("Result must have exactly 2 coordinates", 2, stepLocation.length); + assertEquals("x coordinate must match", expectedLocation[0], stepLocation[0], EPS); + assertEquals("y coordinate must match", expectedLocation[1], stepLocation[1], EPS); + score += 2; + } + + @Test + public void jumpStep_NoActionPoints() { + max_score += 1; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI; + double worm_radius = 1.5; + long worm_actionPoints = referenceMaxActionPoints(worm_radius); + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.decreaseNbActionPoints(theWorm, worm_actionPoints); + try { + facade.getJumpStep(theWorm, 0.1); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void jumpStep_ImproperOrientation() { + max_score += 1; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 5.0 * PI / 4.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + facade.getJumpStep(theWorm, 0.1); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void jumpStep_ImproperDt() { + max_score += 1; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 5.0 * PI / 4.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + facade.getJumpStep(theWorm, Double.NaN); + fail(); + } catch (ModelException exc) { + } + try { + facade.getJumpStep(theWorm, -1.0); + fail(); + } catch (ModelException exc) { + } + score += 1; + } + + @Test + public void jumpTime_ReachingImpassableTerrain() { + max_score += 14; + double[] worm_location = new double[] { 7.5, 6.5 }; + double worm_orientation = 3 * PI / 4.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double jumpTime = facade.getJumpTime(theWorm, 0.01); + assertEquals(0.39, jumpTime, 0.05); + double[] locationAfterJump = facade.getJumpStep(theWorm, jumpTime); + assertTrue(facade.isAdjacent(theWorld, locationAfterJump, worm_radius)); + score += 14; + } + + @Test + public void jumpTime_OutsideWorld() { + max_score += 8; + double[] worm_location = new double[] { 8.5, 0.6 }; + double worm_orientation = 7.0 * PI / 8.0; + double worm_radius = 0.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + facade.getJumpTime(theWorm, 0.05); + fail(); + } catch (ModelException exc) { + score += 8; + } + } + + @Test + public void jumpTime_TooShort() { + max_score += 8; + double[] worm_location = new double[] { 7.5, 7.3 }; + double worm_orientation = 7.0 * PI / 8.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + facade.getJumpTime(theWorm, 0.05); + fail(); + } catch (ModelException exc) { + score += 8; + } + } + + @Test + public void jumpTime_WormCannotJump() { + max_score += 1; + try { + facade.getJumpTime(fixtureWorm, 0.001); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void jump_ReachingImpassableTerrain() { + max_score += 9; + double[] worm_location = new double[] { 7.5, 6.5 }; + double worm_orientation = 3 * PI / 4.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.jump(theWorm, 0.01); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), worm_radius)); + assertEquals(0, facade.getNbActionPoints(theWorm)); + score += 9; + } + + @Test + public void jump_SingleOverlappingWorm() { + max_score += 11; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + double[] worm_location = new double[] { 2.5, 3.0 }; + double worm_orientation = PI / 4.0; + double worm_radius = 2.0; + Worm theWorm = facade.createWorm(otherWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Worm worm1 = facade.createWorm(otherWorld, new double[] { 8.0, 4.0 }, 0.5, 1.0, "WormA", null); + long oldNbHitPoints_TheWorm = facade.getNbHitPoints(theWorm).longValue(); + long oldNbHitPoints_worm1 = facade.getNbHitPoints(worm1).longValue(); + facade.jump(theWorm, 0.01); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), worm_radius)); + assertEquals(0, facade.getNbActionPoints(theWorm)); + long newNbHitPoints_TheWorm = facade.getNbHitPoints(theWorm).longValue(); + long newNbHitPoints_worm1 = facade.getNbHitPoints(worm1).longValue(); + assertTrue((newNbHitPoints_TheWorm < oldNbHitPoints_TheWorm) ^ (newNbHitPoints_worm1 < oldNbHitPoints_worm1)); + assertTrue((newNbHitPoints_TheWorm == 0) || (newNbHitPoints_TheWorm >= oldNbHitPoints_TheWorm - 5)); + assertTrue((newNbHitPoints_worm1 == 0) || (newNbHitPoints_worm1 >= oldNbHitPoints_TheWorm - 40)); + score += 11; + } + + @Test + public void jump_SeveralOverlappingWorms() { + max_score += 13; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { false, false, false, false, false, false, false, false, false, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + double[] worm_location = new double[] { 2.5, 3.0 }; + double worm_orientation = PI / 4.0; + double worm_radius = 2.0; + Worm theWorm = facade.createWorm(otherWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Worm worm1 = facade.createWorm(otherWorld, new double[] { 8.0, 4.0 }, 0.5, 1.0, "WormA", null); + Worm worm2 = facade.createWorm(otherWorld, new double[] { 6.0, 4.0 }, 0.5, 3.0, "WormB", null); + long oldNbHitPoints_TheWorm = facade.getNbHitPoints(theWorm).longValue(); + long oldNbHitPoints_worm1 = facade.getNbHitPoints(worm1).longValue(); + long oldNbHitPoints_worm2 = facade.getNbHitPoints(worm2).longValue(); + facade.jump(theWorm, 0.01); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), worm_radius)); + assertEquals(0, facade.getNbActionPoints(theWorm)); + long newNbHitPoints_TheWorm = facade.getNbHitPoints(theWorm).longValue(); + long newNbHitPoints_worm1 = facade.getNbHitPoints(worm1).longValue(); + long newNbHitPoints_worm2 = facade.getNbHitPoints(worm2).longValue(); + assertTrue(((newNbHitPoints_TheWorm == oldNbHitPoints_TheWorm) && (newNbHitPoints_worm1 < oldNbHitPoints_worm1) + && (newNbHitPoints_worm2 < oldNbHitPoints_worm2)) + || ((newNbHitPoints_TheWorm < oldNbHitPoints_TheWorm) && ((newNbHitPoints_worm1 == oldNbHitPoints_worm1) + || (newNbHitPoints_worm2 == oldNbHitPoints_worm2)))); + score += 13; + } + + @Test + public void jump_NoJumpPossible() { + max_score += 3; + try { + double[] worm_location = new double[] { 7.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.jump(theWorm, 0.01); + fail(); + } catch (ModelException exc) { + score += 3; + } + } + + @Test + public void jump_DirectedDownward() { + max_score += 1; + try { + double[] worm_location = new double[] { 7.5, 6.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.jump(theWorm, 0.01); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void eat_WormNotInWorld() { + max_score += 1; + facade.eat(fixtureWorm); + assertEquals(FIXTURE_RADIUS, facade.getRadius(fixtureWorm), EPS); + assertEquals(FIXTURE_LOCATION[0], facade.getLocation(fixtureWorm)[0], EPS); + assertEquals(FIXTURE_LOCATION[1], facade.getLocation(fixtureWorm)[1], EPS); + score += 1; + } + + @Test + public void eat_NoOverlappingPortion() { + max_score += 2; + double[] worm_location = new double[] { 4.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 0.5, 8.795 }; + Food newFood = facade.createFood(theWorld, location); + facade.eat(theWorm); + assertFalse(facade.isTerminated(newFood)); + assertEquals(1.5, facade.getRadius(theWorm), EPS); + assertEquals(4.5, facade.getLocation(theWorm)[0], EPS); + assertEquals(7.5, facade.getLocation(theWorm)[1], EPS); + score += 2; + } + + @Test + public void eat_OverlapWithSingleHealthyPortion() { + max_score += 8; + double[] worm_location = new double[] { 4.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 4.5, 8.795 }; + Food newFood = facade.createFood(theWorld, location); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood)); + assertEquals(1.5 * 1.1, facade.getRadius(theWorm), EPS); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), facade.getRadius(theWorm))); + assertTrue(getDistance(worm_location,facade.getLocation(theWorm)) < facade.getRadius(theWorm)*0.2); + assertEquals(oldNbActionPoints - 8, facade.getNbActionPoints(theWorm)); + score += 8; + } + + @Test + public void eat_OverlapWithSinglePoisonousPortion() { + max_score += 8; + double[] worm_location = new double[] { 4.5, 7.49 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 4.5, 8.795 }; + Food newFood = facade.createFood(theWorld, location); + facade.poison(newFood); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood)); + assertEquals(1.5 * 0.9, facade.getRadius(theWorm), EPS); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), facade.getRadius(theWorm))); + assertTrue(getDistance(worm_location,facade.getLocation(theWorm)) < facade.getRadius(theWorm)*0.2); + long expectedNbActionPoints = Math.min(oldNbActionPoints - 8, + referenceMaxActionPoints(facade.getRadius(theWorm))); + assertEquals(expectedNbActionPoints, facade.getNbActionPoints(theWorm)); + score += 8; + } + + @Test + public void eat_SmallWormOverlapWithSinglePoisonousPortion() { + max_score += 6; + double[] worm_location = new double[] { 4.5, 8.73 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 0.26; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 4.5, 8.795 }; + Food newFood = facade.createFood(theWorld, location); + facade.poison(newFood); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood)); + assertEquals(0.25, facade.getRadius(theWorm), EPS); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), facade.getRadius(theWorm))); + assertTrue(getDistance(worm_location,facade.getLocation(theWorm)) < facade.getRadius(theWorm)*0.2); + long expectedNbActionPoints = Math.min(oldNbActionPoints - 8, + referenceMaxActionPoints(facade.getRadius(theWorm))); + assertEquals(expectedNbActionPoints, facade.getNbActionPoints(theWorm)); + score += 6; + } + + @Test + public void eat_OverlapWithSeveralHealthyPortions() { + max_score += 2; + double[] worm_location = new double[] { 4.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Food newFood1 = facade.createFood(theWorld, new double[] { 4.5, 8.795 }); + Food newFood2 = facade.createFood(theWorld, new double[] { 4.2, 8.795 }); + Food newFood3 = facade.createFood(theWorld, new double[] { 4.8, 8.795 }); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood1) ^ facade.isTerminated(newFood2) ^ facade.isTerminated(newFood3)); + assertEquals(1.5 * 1.1, facade.getRadius(theWorm), EPS); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), facade.getRadius(theWorm))); + assertTrue(getDistance(worm_location,facade.getLocation(theWorm)) < facade.getRadius(theWorm)*0.2); + assertEquals(oldNbActionPoints - 8, facade.getNbActionPoints(theWorm)); + score += 2; + } + + @Test + public void eat_WormLocatedInCorner() { + max_score += 18; + double[] worm_location = new double[] { 7.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Food newFood1 = facade.createFood(theWorld, new double[] { 7.5, 8.795 }); + Food newFood2 = facade.createFood(theWorld, new double[] { 8.795, 7.5 }); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood1) ^ facade.isTerminated(newFood2)); + assertEquals(1.5 * 1.1, facade.getRadius(theWorm), EPS); + assertTrue(facade.isAdjacent(theWorld, facade.getLocation(theWorm), facade.getRadius(theWorm))); + assertTrue(getDistance(worm_location,facade.getLocation(theWorm)) < facade.getRadius(theWorm)*0.2); + assertEquals(oldNbActionPoints - 8, facade.getNbActionPoints(theWorm)); + score += 18; + } + + @Test + public void eat_NotEnoughActionPoints() { + max_score += 2; + double[] worm_location = new double[] { 4.5, 7.5 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 4.5, 8.795 }; + Food newFood = facade.createFood(theWorld, location); + facade.decreaseNbActionPoints(theWorm, facade.getNbActionPoints(theWorm) - 7); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertFalse(facade.isTerminated(newFood)); + assertEquals(1.5, facade.getRadius(theWorm), EPS); + assertEquals(4.5, facade.getLocation(theWorm)[0], EPS); + assertEquals(7.5, facade.getLocation(theWorm)[1], EPS); + assertEquals(oldNbActionPoints, facade.getNbActionPoints(theWorm)); + score += 2; + } + + @Test + public void eat_EnlargedWormNotFullyInWorld() { + max_score += 8; + double[] worm_location = new double[] { 7.5, 1.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + double[] location = new double[] { 8.795, 1.5 }; + Food newFood = facade.createFood(theWorld, location); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.eat(theWorm); + assertTrue(facade.isTerminated(newFood)); + assertNull(facade.getWorld(theWorm)); + assertTrue(facade.getAllItems(theWorld).isEmpty()); + assertEquals(oldNbActionPoints - 8, facade.getNbActionPoints(theWorm)); + score += 8; + } + + @Test + public void eat_ExplodingWorm() { + max_score += 15; + map10x10 = new boolean[][] { { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, true, true, true, true, true, false }, + { true, true, true, true, false, false, false,false, false,false }, + { true, true, true, true, false, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, true, false }, + { false,false,false,false,false,false,false,false,false,false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + double[] worm_location = new double[] { 7.0, 3.0 }; + double worm_orientation = PI / 4.0; + double worm_radius = 2.0; + Worm theWorm = facade.createWorm(otherWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.createFood(otherWorld, new double[] { 8.79, 3.0 }); + facade.eat(theWorm); + assertTrue(facade.isTerminated(theWorm)); + assertTrue(facade.getAllItems(otherWorld).isEmpty()); + score += 15; + } + + @Test + public void fire_LegalCase() { + max_score += 12; + double[] worm_location = new double[] { 7.5, 3.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + for (int nbTries = 1; nbTries <= 10; nbTries++) { + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + Projectile projectile = facade.fire(theWorm); + assertEquals(3 * PI / 2.0, facade.getOrientation(projectile), EPS); + double[] projectileLocation = facade.getLocation(projectile); + assertEquals(7.5, projectileLocation[0], EPS); + assertEquals(3.505 - worm_radius - facade.getRadius(projectile), projectileLocation[1], EPS); + assertTrue(facade.getNbActionPoints(theWorm) < oldNbActionPoints); + } + score += 12; + } + + @Test + public void fire_WormOverlapsWithBullet() { + max_score += 12; + double[] worm_location = new double[] { 7.495, 5.8 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile = facade.fire(theWorm); + facade.jump(projectile, 0.00001); + Worm otherWorm = facade.createWorm(theWorld, new double[] { 7.495, 7.5 }, worm_orientation, worm_radius, "Worm", + null); + BigInteger oldNbHitPoints = facade.getNbHitPoints(otherWorm); + assertNull(facade.fire(otherWorm)); + assertTrue(oldNbHitPoints.compareTo(facade.getNbHitPoints(otherWorm)) > 0); + assertTrue(facade.isTerminated(projectile)); + score += 12; + } + + @Test + public void fire_BulletNotFullyInWorld() { + max_score += 7; + double[] worm_location = new double[] { 7.5, 1.50005 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + facade.fire(theWorm); + fail(); + } catch (ModelException exc) { + score += 7; + } + } + + @Test + public void fire_NotInWorld() { + max_score += 1; + try { + facade.fire(fixtureWorm); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + @Test + public void fire_NotEnoughActionPoints() { + max_score += 1; + try { + double[] worm_location = new double[] { 7.5, 1.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.decreaseNbActionPoints(theWorm, facade.getNbActionPoints(theWorm) - 20); + facade.fire(theWorm); + fail(); + } catch (ModelException exc) { + score += 1; + } + } + + /************** + * FOOD TESTS + *************/ + + @Test + public void createFood_LegalCaseNoWorld() { + max_score += 1; + double[] location = new double[] { 3.0, -7.0 }; + Food newFood = facade.createFood(null, location); + assertNull(facade.getWorld(newFood)); + assertEquals(location[0], facade.getLocation(newFood)[0], EPS); + assertEquals(location[1], facade.getLocation(newFood)[1], EPS); + assertEquals(0.2, facade.getRadius(newFood), EPS); + assertEquals(150.0 * (4.0 / 3.0 * PI * Math.pow(0.2, 3.0)), facade.getMass(newFood), EPS); + assertFalse(facade.isPoisonous(newFood)); + score += 1; + } + + @Test + public void createFood_LegalCaseinWorld() { + max_score += 1; + double[] location = new double[] { 3.0, 8.79 }; + Food newFood = facade.createFood(theWorld, location); + assertEquals(theWorld, facade.getWorld(newFood)); + assertTrue(facade.hasAsFood(theWorld, newFood)); + assertEquals(location[0], facade.getLocation(newFood)[0], EPS); + assertEquals(location[1], facade.getLocation(newFood)[1], EPS); + assertEquals(0.2, facade.getRadius(newFood), EPS); + assertEquals(150.0 * (4.0 / 3.0 * PI * Math.pow(0.2, 3.0)), facade.getMass(newFood), EPS); + assertFalse(facade.isPoisonous(newFood)); + score += 1; + } + + @Test + public void terminateFood_NoWorld() { + max_score += 1; + facade.terminate(fixtureFood); + assertTrue(facade.isTerminated(fixtureFood)); + score += 1; + } + + @Test + public void terminateFood_InWorld() { + max_score += 1; + double[] location = new double[] { 3.0, 8.79 }; + Food newFood = facade.createFood(theWorld, location); + facade.terminate(newFood); + assertTrue(facade.isTerminated(newFood)); + assertNull(facade.getWorld(newFood)); + assertFalse(facade.hasAsFood(theWorld, newFood)); + score += 1; + } + + /******************* + * PROJECTILE TESTS + *******************/ + + @Test + public void jumpStepProjectile_LegalCase() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 2 * PI / 3.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile = facade.fire(theWorm); + double[] stepLocation = facade.getJumpStep(projectile, 0.1); + double[] expectedRifleLocation = new double[] { 2.997, 9.275 }; + double[] expectedBazookaLocation = new double[] { 6.114, 3.875 }; + assertEquals("Result must have exactly 2 coordinates", 2, stepLocation.length); + assertTrue((Math.abs(stepLocation[0] - expectedRifleLocation[0]) < 0.01) + || (Math.abs(stepLocation[0] - expectedBazookaLocation[0]) < 0.01)); + assertTrue((Math.abs(stepLocation[1] - expectedRifleLocation[1]) < 0.01) + || (Math.abs(stepLocation[1] - expectedBazookaLocation[1]) < 0.01)); + score += 4; + } + + @Test + public void jumpTimeProjectile_ReachingImpassableTerrain() { + max_score += 8; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile = facade.fire(theWorm); + double jumpTime = facade.getJumpTime(projectile, 0.00001); + assertTrue((Math.abs(jumpTime - 0.08) < 0.01) || (Math.abs(jumpTime - 0.53) < 0.01)); + double[] locationAfterJump = facade.getJumpStep(projectile, jumpTime); + assertTrue(facade.isAdjacent(theWorld, locationAfterJump, facade.getRadius(projectile)) + || (!facade.isPassable(theWorld, locationAfterJump, facade.getRadius(projectile)))); + score += 8; + } + + @Test + public void jumpTimeProjectile_HittingWorm() { + max_score += 8; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + facade.createWorm(theWorld, new double[] { 7.5, 7.5 }, 0.0, 1.5, "Other", null); + Projectile projectile = facade.fire(theWorm); + double jumpTime = facade.getJumpTime(projectile, 0.00001); + assertTrue((Math.abs(jumpTime - 0.08) < 0.01) || (Math.abs(jumpTime - 0.53) < 0.01)); + double[] locationAfterJump = facade.getJumpStep(projectile, jumpTime); + assertTrue(locationAfterJump[1] >= 6.0 - facade.getRadius(projectile)); + score += 8; + } + + @Test + public void jumpTimeProjectile_OutsideWorld() { + max_score += 6; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 0.99 * PI; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + Projectile projectile = facade.fire(theWorm); + facade.getJumpTime(projectile, 0.00001); + fail(); + } catch (ModelException exc) { + score += 6; + } + } + + @Test + public void jumpProjectile_HittingSingleWorm() { + max_score += 10; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Worm hittedWorm = facade.createWorm(theWorld, new double[] { 7.5, 7.5 }, 0.0, 1.5, "Other", null); + BigInteger oldNbHitPoints = facade.getNbHitPoints(hittedWorm); + Projectile projectile = facade.fire(theWorm); + facade.jump(projectile, 0.00001); + assertTrue(oldNbHitPoints.compareTo(facade.getNbHitPoints(hittedWorm)) > 0); + assertTrue(facade.isTerminated(projectile)); + score += 10; + } + + @Test + public void jumpProjectile_HittingSeveralWorms() { + max_score += 6; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Worm hittedWorm1 = facade.createWorm(theWorld, new double[] { 7.5, 7.5 }, 0.0, 1.5, "OtherA", null); + Worm hittedWorm2 = facade.createWorm(theWorld, new double[] { 7.5, 8.0 }, 0.0, 1.0, "OtherB", null); + BigInteger oldNbHitPoints1 = facade.getNbHitPoints(hittedWorm1); + BigInteger oldNbHitPoints2 = facade.getNbHitPoints(hittedWorm2); + Projectile projectile = facade.fire(theWorm); + facade.jump(projectile, 0.00001); + assertTrue(oldNbHitPoints1.compareTo(facade.getNbHitPoints(hittedWorm1)) > 0); + assertTrue(oldNbHitPoints2.compareTo(facade.getNbHitPoints(hittedWorm2)) > 0); + assertTrue(facade.isTerminated(projectile)); + score += 6; + } + + @Test + public void jumpProjectile_OutsideWorld() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = 0.99 * PI; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + try { + Projectile projectile = facade.fire(theWorm); + facade.jump(projectile, 0.0001); + fail(); + } catch (ModelException exc) { + score += 4; + } + } + + @Test + public void jumpProjectile_ReachingImpassableTerrain() { + max_score += 6; + double[] worm_location = new double[] { 7.5, 1.5 }; + double worm_orientation = PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile = facade.fire(theWorm); + facade.jump(projectile, 0.00001); + double[] locationAfterJump = facade.getLocation(projectile); + assertTrue(facade.isAdjacent(theWorld, locationAfterJump, facade.getRadius(projectile)) + || (!facade.isPassable(theWorld, locationAfterJump, facade.getRadius(projectile)))); + assertFalse(facade.isTerminated(projectile)); + score += 6; + } + + /************** + * TEAM TESTS + *************/ + + @Test + public void createTeam_LegalCaseNoWorld() { + max_score += 2; + try { + Team theTeam = facade.createTeam(null, "Team"); + assertEquals(0, facade.getNbWormsOfTeam(theTeam)); + assertEquals("Team", facade.getName(theTeam)); + assertFalse(facade.isTerminated(theTeam)); + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void createTeam_LegalCaseInWorld() { + max_score += 4; + try { + assertEquals(0, facade.getNbWormsOfTeam(theTeam)); + assertEquals("TheTeam", facade.getName(theTeam)); + assertFalse(facade.isTerminated(theTeam)); + assertTrue(facade.getAllTeams(theWorld).contains(theTeam)); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void createTeam_IllegalName() { + max_score += 1; + try { + facade.createTeam(theWorld, "'abc"); + fail(); + } catch (ModelException exc) { + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + @Test + public void createTeam_TooManyTeams() { + max_score += 3; + try { + facade.createTeam(theWorld, "TeamB"); + score -= 3; + facade.createTeam(theWorld, "TeamC"); + facade.createTeam(theWorld, "TeamD"); + facade.createTeam(theWorld, "TeamE"); + facade.createTeam(theWorld, "TeamF"); + facade.createTeam(theWorld, "TeamG"); + facade.createTeam(theWorld, "TeamH"); + facade.createTeam(theWorld, "TeamI"); + facade.createTeam(theWorld, "TeamJ"); + // We must reach this point, otherwise we are not + // able to have 10 teams in a world. + score += 3; + facade.createTeam(theWorld, "TeamH"); + fail(); + } catch (ModelException exc) { + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void terminate_SingleCase() { + max_score += 5; + try { + Worm wormA = facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormA", + theTeam); + Worm wormB = facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormB", + theTeam); + facade.terminate(theTeam); + assertTrue(facade.isTerminated(theTeam)); + assertEquals(0, facade.getAllWormsOfTeam(theTeam).size()); + assertNull(facade.getTeam(wormA)); + assertNull(facade.getTeam(wormB)); + score += 5; + } catch (MustNotImplementException exc) { + max_score -= 5; + } + } + + @Test + public void getAllWormsOfTeam_LegalCase() { + max_score += 2; + try { + Worm wormA = facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormA", + theTeam); + Worm wormB = facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormB", + theTeam); + List members = facade.getAllWormsOfTeam(theTeam); + assertEquals(2, members.size()); + assertTrue(members.contains(wormA)); + assertTrue(members.contains(wormB)); + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void getAllWormsOfTeam_LeakTest() { + max_score += 10; + try { + facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormA", theTeam); + facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormB", theTeam); + List members = facade.getAllWormsOfTeam(theTeam); + Worm wormC = facade.createWorm(null, new double[] { 2.0, Double.POSITIVE_INFINITY }, 2.0, 12.0, "WormC", + null); + members.add(wormC); + assertEquals(2, facade.getNbWormsOfTeam(theTeam)); + assertFalse(facade.getAllWormsOfTeam(theTeam).contains(wormC)); + score += 10; + } catch (MustNotImplementException exc) { + max_score -= 10; + } + } + + @Test + public void addWormsToTeam_SeveralWormsOfSameWorld() { + max_score += 4; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + Worm wormB = facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", null); + Worm wormC = facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", null); + facade.addWormsToTeam(theTeam, wormA, wormB, wormC); + assertEquals(3, facade.getNbWormsOfTeam(theTeam)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormA)); + assertEquals(theTeam, facade.getTeam(wormA)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormB)); + assertEquals(theTeam, facade.getTeam(wormB)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormC)); + assertEquals(theTeam, facade.getTeam(wormC)); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void addWormsToTeam_WormsFromDifferentWorlds() { + max_score += 4; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + Worm wormB = facade.createWorm(otherWorld, new double[] { 2.5, 3.0 }, 2.0, 1.0, "WormB", null); + Worm wormC = facade.createWorm(null, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", null); + facade.addWormsToTeam(theTeam, wormA, wormB, wormC); + assertEquals(3, facade.getNbWormsOfTeam(theTeam)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormA)); + assertEquals(theTeam, facade.getTeam(wormA)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormB)); + assertEquals(theTeam, facade.getTeam(wormB)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormC)); + assertEquals(theTeam, facade.getTeam(wormC)); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void addWormsToTeam_NullSequenceOfWorms() { + max_score += 1; + try { + facade.addWormsToTeam(theTeam, (Worm[]) null); + fail(); + } catch (ModelException exc) { + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + @Test + public void addWormsToTeam_WormWithSameNameAlreadyInTeam() { + max_score += 3; + try { + facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormABis = facade.createWorm(otherWorld, new double[] { 2.5, 3.0 }, 2.0, 1.0, "WormA", null); + facade.addWormsToTeam(theTeam, wormABis); + fail(); + } catch (ModelException exc) { + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void addWormsToTeam_WormsWitSameName() { + max_score += 3; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + Worm wormABis = facade.createWorm(otherWorld, new double[] { 2.5, 3.0 }, 2.0, 1.0, "WormA", null); + facade.addWormsToTeam(theTeam, wormA, wormABis); + fail(); + } catch (ModelException exc) { + assertEquals(0, facade.getNbWormsOfTeam(theTeam)); + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void addWormsToTeam_SameWormSeveralTimes() { + max_score += 3; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + facade.addWormsToTeam(theTeam, wormA, wormA); + // Accepting the worm once is OK. + assertEquals(1, facade.getNbWormsOfTeam(theTeam)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormA)); + score += 3; + } catch (ModelException exc) { + // Rejecting duplicate worms is also OK. + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void addWormsToTeam_WormTooLight() { + max_score += 4; + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormB = facade.createWorm(otherWorld, new double[] { 2.5, 3.0 }, 2.0, 1.0, "WormB", null); + try { + facade.addWormsToTeam(theTeam, wormB); + fail(); + } catch (ModelException exc) { + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void addWormsToTeam_WormTooHeavy() { + max_score += 4; + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 8.0 }, 2.0, 1.0, "WormA", theTeam); + Worm wormB = facade.createWorm(otherWorld, new double[] { 2.5, 2.0 }, 2.0, 2.0, "WormB", null); + try { + facade.addWormsToTeam(theTeam, wormB); + fail(); + } catch (ModelException exc) { + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void addWormsToTeam_WormAlreadyInOtherTeam() { + max_score += 2; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Team otherTeam = facade.createTeam(null, "OtherTeam"); + facade.addWormsToTeam(otherTeam, wormA); + fail(); + } catch (ModelException exc) { + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void addWormsToTeam_TerminatedWorm() { + max_score += 2; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + facade.terminate(wormA); + facade.addWormsToTeam(theTeam, wormA); + fail(); + } catch (ModelException exc) { + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void addWormsToTeam_NonEffectiveWorm() { + max_score += 2; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", null); + Worm[] wormsToAdd = new Worm[] { wormA, null }; + facade.addWormsToTeam(theTeam, wormsToAdd); + fail(); + } catch (ModelException exc) { + score += 2; + } catch (MustNotImplementException exc) { + max_score -= 2; + } + } + + @Test + public void removeWormsFromTeam_SeveralWormsFromTeam() { + max_score += 4; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormB = facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", theTeam); + Worm wormC = facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", theTeam); + facade.removeWormsFromTeam(theTeam, wormA, wormC); + assertEquals(1, facade.getNbWormsOfTeam(theTeam)); + assertFalse(facade.getAllWormsOfTeam(theTeam).contains(wormA)); + assertNull(facade.getTeam(wormA)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormB)); + assertFalse(facade.getAllWormsOfTeam(theTeam).contains(wormC)); + assertNull(facade.getTeam(wormC)); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void removeWormsFromTeam_NoWorms() { + max_score += 1; + try { + facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", theTeam); + facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", theTeam); + facade.removeWormsFromTeam(theTeam); + assertEquals(3, facade.getNbWormsOfTeam(theTeam)); + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + @Test + public void removeWormsFromTeam_NullSequenceOfWorms() { + max_score += 1; + try { + facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + facade.removeWormsFromTeam(theTeam, (Worm[]) null); + fail(); + } catch (ModelException exc) { + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + @Test + public void removeWormsFromTeam_WormOfOtherTeam() { + max_score += 4; + Team otherTeam = null; + try { + otherTeam = facade.createTeam(null, "OtherTeam"); + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormB = facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", otherTeam); + facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", otherTeam); + facade.removeWormsFromTeam(otherTeam, wormB, wormA); + fail(); + } catch (ModelException exc) { + assertEquals(2, facade.getAllWormsOfTeam(otherTeam).size()); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void removeWormsFromTeam_NonEffectiveWorm() { + max_score += 4; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormB = facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", theTeam); + Worm wormC = facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", theTeam); + facade.removeWormsFromTeam(theTeam, new Worm[] { wormB, null, wormC }); + fail(); + } catch (ModelException exc) { + assertEquals(3, facade.getAllWormsOfTeam(theTeam).size()); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void mergeTeams_LegalCase() { + max_score += 10; + try { + Worm wormA = facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + Worm wormB = facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", theTeam); + Team otherTeam = facade.createTeam(otherWorld, "OtherTeam"); + Worm wormC = facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormC", otherTeam); + Worm wormD = facade.createWorm(otherWorld, new double[] { 2.5, 2.0 }, 2.0, 2.0, "WormD", otherTeam); + facade.mergeTeams(theTeam, otherTeam); + assertEquals(4, facade.getNbWormsOfTeam(theTeam)); + assertEquals(0, facade.getNbWormsOfTeam(otherTeam)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormC)); + assertEquals(theTeam, facade.getTeam(wormC)); + assertTrue(facade.getAllWormsOfTeam(theTeam).contains(wormD)); + assertEquals(theTeam, facade.getTeam(wormD)); + score += 10; + } catch (MustNotImplementException exc) { + max_score -= 10; + } + } + + @Test + public void mergeTeams_NameConflict() { + max_score += 6; + Team otherTeam = null; + try { + facade.createWorm(theWorld, new double[] { 2.3, 7.0 }, 2.0, 2.0, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.8, 7.0 }, 2.0, 2.0, "WormB", theTeam); + otherTeam = facade.createTeam(otherWorld, "OtherTeam"); + facade.createWorm(theWorld, new double[] { 7.0, 2.5 }, 2.0, 2.0, "WormA", otherTeam); + facade.createWorm(otherWorld, new double[] { 2.5, 2.0 }, 2.0, 2.0, "WormD", otherTeam); + facade.mergeTeams(theTeam, otherTeam); + fail(); + } catch (ModelException exc) { + assertEquals(2, facade.getAllWormsOfTeam(theTeam).size()); + assertEquals(2, facade.getAllWormsOfTeam(otherTeam).size()); + score += 6; + } catch (MustNotImplementException exc) { + max_score -= 6; + } + } + + @Test + public void mergeTeams_NonEffectiveTeam() { + max_score += 1; + try { + facade.mergeTeams(theTeam, null); + fail(); + } catch (ModelException exc) { + score += 1; + } catch (MustNotImplementException exc) { + max_score -= 1; + } + } + + /*************** + * WIZARD TESTS + **************/ + + @Test + public void castSpell_NotEnoughGameObjects() { + max_score += 2; + try { + facade.castSpell(theWorld); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void castSpell_WormsSameTeam() { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormA", theTeam); + BigInteger nbHitPoints1 = facade.getNbHitPoints(worm1); + Worm worm2 = facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", theTeam); + BigInteger nbHitPoints2 = facade.getNbHitPoints(worm2); + facade.castSpell(theWorld); + BigInteger expectedNbHitPoints = nbHitPoints1.add(nbHitPoints2).divide(BigInteger.valueOf(2)); + assertEquals(expectedNbHitPoints, facade.getNbHitPoints(worm1)); + assertEquals(expectedNbHitPoints, facade.getNbHitPoints(worm2)); + score += 4; + } + + @Test + public void castSpell_WormsDifferentTeams() { + max_score += 4; + Worm largestWorm = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormA", + theTeam); + long nbActionPointsLargest = facade.getNbActionPoints(largestWorm); + Worm smallestWorm = facade.createWorm(theWorld, new double[] { 6.0, 8.0 }, FIXTURE_DIRECTION, 1.0, "WormB", + null); + facade.decreaseNbActionPoints(smallestWorm, 10); + long nbActionPointsSmallest = facade.getNbActionPoints(smallestWorm); + facade.castSpell(theWorld); + long actionPointsToTransfer = Math.min(nbActionPointsLargest, 5); + assertEquals(nbActionPointsLargest - actionPointsToTransfer, facade.getNbActionPoints(largestWorm)); + assertEquals(nbActionPointsSmallest + actionPointsToTransfer, facade.getNbActionPoints(smallestWorm)); + score += 4; + } + + @Test + public void castSpell_WormsWithFood() { + max_score += 4; + Worm theWorm = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormA", theTeam); + double[] location = new double[] { 8.795, 1.5 }; + Food theFood = facade.createFood(theWorld, location); + facade.castSpell(theWorld); + assertEquals(1.5 * 1.1, facade.getRadius(theWorm), EPS); + assertFalse(facade.isTerminated(theFood)); + score += 4; + } + + @Test + public void castSpell_Food() { + max_score += 4; + Food food1 = facade.createFood(theWorld, new double[] { 8.795, 1.5 }); + Food food2 = facade.createFood(theWorld, new double[] { 8.795, 7.5 }); + facade.poison(food2); + facade.castSpell(theWorld); + assertTrue(facade.isPoisonous(food1)); + assertFalse(facade.isPoisonous(food2)); + score += 4; + } + + @Test + public void castSpell_WormWithProjectile() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 3.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + long oldNbActionPoints = facade.getNbActionPoints(theWorm); + facade.fire(theWorm); + facade.castSpell(theWorld); + assertTrue(facade.getNbActionPoints(theWorm) < oldNbActionPoints); + score += 4; + } + + @Test + public void castSpell_FoodWithProjectile() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 3.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile = facade.fire(theWorm); + facade.terminate(theWorm); + double[] location = new double[] { 8.795, 1.5 }; + Food theFood = facade.createFood(theWorld, location); + facade.castSpell(theWorld); + assertTrue(facade.isTerminated(theFood)); + assertTrue(facade.isTerminated(projectile)); + score += 4; + } + + @Test + public void castSpell_Projectiles() { + max_score += 4; + double[] worm_location = new double[] { 7.5, 3.505 }; + double worm_orientation = 3 * PI / 2.0; + double worm_radius = 1.5; + Worm theWorm = facade.createWorm(theWorld, worm_location, worm_orientation, worm_radius, "Worm", null); + Projectile projectile1 = facade.fire(theWorm); + int oldNbHitPoints1 = facade.getNbHitPoints(projectile1); + Projectile projectile2 = facade.fire(theWorm); + int oldNbHitPoints2 = facade.getNbHitPoints(projectile2); + facade.terminate(theWorm); + facade.castSpell(theWorld); + assertTrue((facade.getNbHitPoints(projectile1) == oldNbHitPoints1 + 2) || (oldNbHitPoints1 == 7) + || (oldNbHitPoints1 == 10)); + assertTrue((facade.getNbHitPoints(projectile2) == oldNbHitPoints2 + 2) || (oldNbHitPoints2 == 7) + || (oldNbHitPoints2 == 10)); + score += 4; + } + + /**************** + * PROGRAM TESTS + ***************/ + + @Test + public void loadProgram_ActiveGame() { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + facade.startGame(theWorld); + String code = "print 2.0;"; + Program theProgram = ProgramParser.parseProgramFromString(code, programFactory); + try { + facade.loadProgramOnWorm(theWorm, theProgram, actionHandler); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + /****************** + * STATEMENT TESTS + ******************/ + + @Test + public void testPrintStatement_LegalCase() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testSequenceStatement_EmptyBody() throws ModelException { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "{ }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + score += 3; + } + + @Test + public void testSequenceStatement_NonNestedNonInterruptable() throws ModelException { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "{ print 4.0; " + "print 12.0; }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 4.0, 12.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 3; + } + + @Test + public void testSequenceStatement_NestedNonInterruptable() throws ModelException { + max_score += 5; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 4.0; " + " { print 12.0; print 6.0; } print 15.0; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 4.0, 12.0, 6.0, 15.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 5; + } + + @Test + public void testSequenceStatement_NonNestedInterruptable() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.2, 1.5, "WormA", theTeam); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + String code = "{ print 4.0; turn 1.0; print 12.0; }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 4.0, 12.0 }; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.2, facade.getOrientation(worm1), EPS); + score += 10; + } + + @Test + public void testSequenceStatement_NestedInterruptable() throws ModelException { + max_score += 15; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.2, 1.5, "WormA", theTeam); + String code = "{ print 4.0; { print 3.0; turn 1.0; print 2.0; } turn 0.4; print 12.0; }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -10); + results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 4.0, 3.0, 2.0, 12.0 }; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.6, facade.getOrientation(worm1), EPS); + score += 15; + } + + @Test + public void testAssignmentStatement_NewVariable() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "{ varname := 7.0; print varname; }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 7.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } + + @Test + public void testAssignmentStatement_ExistingVariable() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "{ varname := 7.0; varname := 12.0; print varname; }"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 12.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } + + @Test + public void testAssignmentStatement_AssignmentToProcedureName() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: print 4.0; p := 7.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 10; + } catch (MustNotImplementException exc) { + max_score -= 10; + } + } + + @Test + public void testTurnStatement_LegalCase() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 1.0, 1.5, "WormA", theTeam); + String code = "turn 0.5; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.5, facade.getOrientation(worm1), EPS); + score += 4; + } + + @Test + public void testTurnStatement_NonDoubleAngle() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "turn null;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void testTurnStatement_AngleOutOfRange() throws ModelException { + max_score += 5; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "turn 10.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 5; + } + } + + @Test + public void testTurnStatement_NotEnoughActionPoints() throws ModelException { + max_score += 6; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + String code = "turn 1.0; print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + assertNull(results); + assertEquals(0.0, facade.getOrientation(worm1), EPS); + score += 6; + } + + @Test + public void testMoveStatement_WormMoving() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 6.0 }, PI / 4.0, 1.5, "WormA", theTeam); + String code = "move; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertNotEquals(7.5, facade.getLocation(worm1)[0], EPS); + score += 4; + } + + @Test + public void testMoveStatement_WormKeepsPosition() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 7.5 }, PI / 2.0, 1.5, "WormA", theTeam); + String code = "move; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(7.5, facade.getLocation(worm1)[0], EPS); + assertEquals(7.5, facade.getLocation(worm1)[1], EPS); + score += 4; + } + + @Test + public void testMoveStatement_NotEnoughActionPoints() throws ModelException { + max_score += 6; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 2.0 }, PI / 4.0, 1.5, "WormA", theTeam); + String code = "move; print 4.0; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + score += 6; + } + + @Test + public void testJumpStatement_WormJumping() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + String code = "jump; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertNotEquals(7.5, facade.getLocation(worm1)[0], EPS); + assertNotEquals(5.5, facade.getLocation(worm1)[1], EPS); + score += 4; + } + + @Test + public void testJumpStatement_NoActionPoints() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + String code = "jump; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + score += 4; + } + + @Test + public void testJumpStatement_OrientedDown() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 3 * PI / 2.0, 1.5, "WormA", theTeam); + String code = "jump; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 4; + } + } + + @Test + public void testEatStatement_WormEating() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + Food food = facade.createFood(theWorld, new double[] {8.795,5.5}); + String code = "eat; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertTrue(facade.getRadius(worm1) > 1.5); + assertNotEquals(7.5, facade.getLocation(worm1)[0], EPS); + assertTrue(facade.isTerminated(food)); + score += 4; + } + + @Test + public void testEatStatement_NothingToEat() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + String code = "eat; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.5,facade.getRadius(worm1),EPS); + score += 4; + } + + @Test + public void testEatStatement_NotEnoughActionPoints() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + String code = "eat; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + score += 4; + } + + @Test + public void testFireStatement_WormFiring() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, PI, 1.5, "WormA", theTeam); + String code = "fire; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = {}; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(2,facade.getAllItems(theWorld).size()); + score += 4; + } + + @Test + public void testFireStatement_NotEnoughActionPoints() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 7.5, 5.5 }, 7 * PI / 12.0, 1.5, "WormA", theTeam); + String code = "fire; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + score += 4; + } + + @Test + public void testIfStatement_NonBooleanCondition() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "if 3.0 print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 4; + } + } + + @Test + public void testIfStatement_ThenPartNonInterruptable() throws ModelException { + max_score += 6; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; if true { print 2.0; print 3.0; } print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 6; + } + + @Test + public void testIfStatement_ElsePartNonInterruptable() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; if false print 5.0; else { print 2.0; print 3.0; } print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } + + @Test + public void testIfStatement_ThenPartInterruptable() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + String code = "print 1.0; if true { print 2.0; turn 1.5; print 3.0; } print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.5, facade.getOrientation(worm1), EPS); + score += 10; + } + + @Test + public void testIfStatement_ConditionNotReEvaluated() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + String code = "v := true; print 1.0; if v { print 2.0; v := false; turn 1.5; print 3.0; } print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.5, facade.getOrientation(worm1), EPS); + score += 10; + } + + @Test + public void testIfStatement_ElsePartInterruptable() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + String code = "v := false; print 1.0; if v print 22.0; { print 2.0; v := true; turn 1.5; print 3.0; } print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0 }; + assertArrayEquals(expecteds, results.toArray()); + assertEquals(1.5, facade.getOrientation(worm1), EPS); + score += 10; + } + + @Test + public void testWhileStatement_NonBooleanCondition() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "while 3.0 print 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 4; + } + } + + @Test + public void testWhileStatement_ConditionTypeChanges() throws ModelException { + max_score += 8; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "v := true; while v v := null;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 8; + } + } + + @Test + public void testWhileSatement_BodyNonInterruptable() throws ModelException { + max_score += 18; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; v := 1.0; while v < 8.5 { v := v + 1.0; print v; } print 10.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 18; + } + + @Test + public void testWhileSatement_BodyInterruptable() throws ModelException { + max_score += 25; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; v := 0.0; while v < 0.45 { v := v + 0.1; print v; turn v; } print 1.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + List results = facade.executeProgram(worm1); + assertNull(results); + // Finishing the first two iterations. + facade.decreaseNbActionPoints(worm1, -3); + results = facade.executeProgram(worm1); + assertNull(results); + // Finishing the next two iterations. + facade.decreaseNbActionPoints(worm1, -7); + results = facade.executeProgram(worm1); + assertNull(results); + // Finishing program execution. + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + List finalResults = facade.executeProgram(worm1); + double[] expecteds = { 1.0, 0.1, 0.2, 0.3, 0.4, 0.5, 1.0 }; + IntStream.range(0, expecteds.length) + .forEach(i -> org.junit.Assert.assertEquals(expecteds[i], (Double) finalResults.get(i), EPS)); + score += 25; + } + + @Test + public void testBreakSatement_DirectlyInWhileBody() throws ModelException { + max_score += 14; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; v := 1.0; while true { v := v + 1.0; print v; if 4.5 < v break; } print 10.0;"; + try { + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 3.0, 4.0, 5.0, 10.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 14; + } catch (MustNotImplementException exc) { + max_score -= 14; + } + } + + @Test + public void testBreakSatement_IndirectlyInWhileBody() throws ModelException { + max_score += 20; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print 1.0; v := 1.0; while true { v := v + 1.0; { print v; if 4.5 < v break; print 0.0;} } print 10.0;"; + try { + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 2.0, 0.0, 3.0, 0.0, 4.0, 0.0, 5.0, 10.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 20; + } catch (MustNotImplementException exc) { + max_score -= 20; + } + } + + @Test + public void testBreakStatement_OutOfScope() throws ModelException { + max_score += 8; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "v := true; while v {print v; v := false; } break;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 8; + } + } + + @Test + public void testBreakStatement_DirectlyInProcedure() throws ModelException { + max_score += 12; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: { print 10.0; break; print 15.0; } print 0.0; invoke p; print 20.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 0.0, 10.0, 20.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 12; + } catch (MustNotImplementException exc) { + max_score -= 12; + } + } + + @Test + public void testBreakStatement_NestedBreaks() throws ModelException { + max_score += 20; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: { print 1.0; while true { print 2.0; break; } print 3.0; break; print 4.0;} def g: { print 10.0; invoke p; print 20.0; break; print 30.0; } print 0.0; invoke g; print 100.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 0.0, 10.0, 1.0, 2.0, 3.0, 20.0, 100.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 20; + } catch (MustNotImplementException exc) { + max_score -= 20; + } + } + + @Test + public void testInvokeStatement_UndefinedProcedure() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "invoke p;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void testInvokeStatement_SimpleProcedure() throws ModelException { + max_score += 6; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: print 4.0; print 1.0; invoke p; print 7.0; invoke p; print 10.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 4.0, 7.0, 4.0, 10.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 6; + } catch (MustNotImplementException exc) { + max_score -= 6; + } + } + + @Test + public void testInvokeStatement_SeveralDefsOfProcedure() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: print 4.0; def p: print 8.0; print 1.0; invoke p; print 7.0; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0, 8.0, 7.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void testInvokeStatement_ProcedureIntroduingGlobalVariable() throws ModelException { + max_score += 8; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: a := 10; invoke p; print a;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 10.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 8; + } catch (MustNotImplementException exc) { + max_score -= 8; + } + } + + @Test + public void testInvokeStatement_ProcedureChangingGlobalVariable() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: a := a + 10.0; a := 3; invoke p; print a;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 13.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 10; + } catch (MustNotImplementException exc) { + max_score -= 10; + } + } + + @Test + public void testInvokeStatement_ProcedureInvokingOtherProcedure() throws ModelException { + max_score += 10; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: print 1.0; def g: { print 2.0; invoke p; print 3.0; } invoke g; "; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 2.0, 1.0, 3.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 10; + } catch (MustNotImplementException exc) { + max_score -= 10; + } + } + + @Test + public void testInvokeStatement_RecursiveProcedure() throws ModelException { + max_score += 35; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: { print a; if a < 5.5 { a := a + 1.0; invoke p; } } a := 0.0; invoke p; print a + 1.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 35; + } catch (MustNotImplementException exc) { + max_score -= 35; + } + } + + @Test + public void testInvokeStatement_Interrupted() throws ModelException { + max_score += 25; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "def p: { print a; a := a + 5.0; jump; print a; } a := 10.0; invoke p; print a + 1.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + facade.decreaseNbActionPoints(worm1, facade.getNbActionPoints(worm1)); + try { + List results = facade.executeProgram(worm1); + assertNull(results); + facade.decreaseNbActionPoints(worm1, -facade.getMaxNbActionPoints(worm1)); + results = facade.executeProgram(worm1); + Object[] expecteds = { 10.0, 15.0, 16.0}; + assertArrayEquals(expecteds, results.toArray()); + score += 25; + } catch (MustNotImplementException exc) { + max_score -= 25; + } + } + + // break statement + // nested break statements + + // Assignment: assignment to variable with same name as procedure. + + /******************* + * EXPRESSION TESTS + *******************/ + + @Test + public void testReadVariable_LegalCase() throws ModelException { + max_score += 10; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "v := 7.0; print v;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { 7.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 10; + } + + @Test + public void testReadVariable_IllegalCase() throws ModelException { + max_score += 10; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print v;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + try { + facade.executeProgram(theWorm); + fail(); + } catch (ModelException exc) { + score += 10; + } + } + + @Test + public void testBooleanLiteral() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print true;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { true }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testNull() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print null;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { null }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testSelf() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print self;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { theWorm }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testAddition_LegalCase() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 2.0 + 4.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { 6.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testAddition_IllegalCase() throws ModelException { + max_score += 6; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 2.0 + self;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + try { + facade.executeProgram(theWorm); + fail(); + } catch (ModelException exc) { + score += 6; + } + } + + @Test + public void testConjunction_LegalCase() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print true && false;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testNegation_LegalCase() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print ! true;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testEquality_OperandsOfSameType() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 2.0 == 2.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { true }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testEquality_OperandsOfDifferentType() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print true == self;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testEquality_LeftOperandNull() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print null == self;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testInEquality_OperandsOfProperType() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 2.0 < 1.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testInEquality_IllegalCase() throws ModelException { + max_score += 2; + Worm theWorm = facade.createWorm(theWorld, new double[] { 7.5, 3.505 }, 3 * PI / 2.0, 1.5, "Worm", null); + String code = "print 2.0 < self;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + try { + facade.executeProgram(theWorm); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void testSearchObject_SingleObject() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", null); + Food foodToSearch = facade.createFood(theWorld, new double[] { 8.795, 7.5 }); + String code = "print searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { foodToSearch }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } + + @Test + public void testSearchObject_SeveralCandidateObjects() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", null); + Worm wormToSearch = facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", + null); + facade.createFood(theWorld, new double[] { 8.795, 7.5 }); + String code = "print searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { wormToSearch }; + assertArrayEquals(expecteds, results.toArray()); + score += 4; + } + + @Test + public void testSearchObject_NoObject() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 3 * PI / 2.0, 1.5, "WormA", null); + facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", null); + String code = "print searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { null }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testSearchObject_ObjectBehindImpassableTerrain() { + max_score += 5; + map10x10 = new boolean[][] { { false, true, true, true, true, true, true, true, true, false }, + { true, false, true, true, false, false, true, true, true, false }, + { true, true, false, true, true, true, true, true, true, false }, + { true, true, true, false, true, true, true, true, true, false }, + { true, true, true, true, false, true, true, true, false, false }, + { true, true, true, true, true, false, true, true, true, false }, + { true, true, true, true, true, true, false, true, true, false }, + { true, true, true, true, true, true, true, false, true, false }, + { false, true, true, true, true, true, true, true, false, false }, + { false, false, true, true, true, true, true, true, true, false }, }; + World otherWorld = facade.createWorld(10.0, 10.0, map10x10); + Worm theWorm = facade.createWorm(otherWorld, new double[] { 2.0, 2.0 }, PI / 4.0, 1.0, "WormA", null); + Worm wormToSearch = facade.createWorm(otherWorld, new double[] { 8.0, 8.0 }, 0.0, 1.0, "WormB", null); + String code = "print searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(theWorm, program, actionHandler); + List results = facade.executeProgram(theWorm); + Object[] expecteds = { wormToSearch }; + assertArrayEquals(expecteds, results.toArray()); + score += 5; + } + + @Test + public void testSameTeam_TrueCase() throws ModelException { + max_score += 5; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", theTeam); + String code = "print sameteam searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { true }; + assertArrayEquals(expecteds, results.toArray()); + score += 5; + } catch (MustNotImplementException exc) { + max_score -= 5; + } + } + + @Test + public void testSameTeam_FalseCase() throws ModelException { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", null); + String code = "print sameteam searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void testSameTeam_NullCase() throws ModelException { + max_score += 3; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print sameteam null;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + List results = facade.executeProgram(worm1); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 3; + } catch (MustNotImplementException exc) { + max_score -= 3; + } + } + + @Test + public void testSameTeam_IllegalCase() throws ModelException { + max_score += 4; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", null); + facade.createFood(theWorld, new double[] { 8.795, 7.5 }); + String code = "print sameteam searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 4; + } catch (MustNotImplementException exc) { + max_score -= 4; + } + } + + @Test + public void testDistance_LegalCase() throws ModelException { + max_score += 5; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", theTeam); + String code = "print distance searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { 1.0 }; + assertArrayEquals(expecteds, results.toArray()); + score += 5; + } + + @Test + public void testDistance_NullCase() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print distance null;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void testDistance_IllegalCase() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print distance 3.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + try { + facade.executeProgram(worm1); + fail(); + } catch (ModelException exc) { + score += 2; + } + } + + @Test + public void testIsWorm_TrueCase() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + facade.createWorm(theWorld, new double[] { 6.0, 7.5 }, FIXTURE_DIRECTION, 1.5, "WormB", null); + String code = "print isworm searchobj 0.0;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { true }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + + @Test + public void testIsWorm_FalseCase() throws ModelException { + max_score += 2; + Worm worm1 = facade.createWorm(theWorld, new double[] { 2.0, 7.5 }, 0.0, 1.5, "WormA", theTeam); + String code = "print isworm 3.14;"; + Program program = ProgramParser.parseProgramFromString(code, programFactory); + facade.loadProgramOnWorm(worm1, program, actionHandler); + List results = facade.executeProgram(worm1); + Object[] expecteds = { false }; + assertArrayEquals(expecteds, results.toArray()); + score += 2; + } + +} diff --git a/OGP1718-Worms/tests/worms/model/PartialPart2FacadeTest.java b/OGP1718-Worms/tests/worms/model/PartialPart2FacadeTest.java old mode 100644 new mode 100755 diff --git a/OGP1718-Worms/tests/worms/model/SimpleActionHandler.java b/OGP1718-Worms/tests/worms/model/SimpleActionHandler.java new file mode 100755 index 0000000..cb384af --- /dev/null +++ b/OGP1718-Worms/tests/worms/model/SimpleActionHandler.java @@ -0,0 +1,95 @@ +package worms.model; + +import worms.facade.IFacade; +import worms.internal.gui.GUIConstants; +import worms.internal.gui.game.IActionHandler; +import worms.util.ModelException; + +/** + * A simple action handler that just calls the necessary methods on the facade. + * Useful for writing tests; there's no other reason to use this. + */ +public class SimpleActionHandler implements IActionHandler { + + private final IFacade facade; + + public SimpleActionHandler(IFacade facade) { + this.facade = facade; + } + + @Override + public boolean turn(Worm worm, double angle) { + try { + facade.turn(worm, angle); + return true; + } catch (ModelException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw e; + } + } + + @Override + public void print(String message) { + System.out.println(message); + } + + @Override + public boolean move(Worm worm) { + try { + facade.move(worm); + if (facade.canFall(worm)) { + facade.fall(worm); + } + return true; + } catch (ModelException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw e; + } + } + + @Override + public boolean jump(Worm worm) { + try { + facade.jump(worm, GUIConstants.JUMP_TIME_STEP); + if (facade.canFall(worm)) { + facade.fall(worm); + } + return true; + } catch (ModelException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw e; + } + } + + @Override + public boolean fire(Worm worm) { + try { + facade.fire(worm); + return true; + } catch (ModelException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw e; + } + } + + @Override + public boolean eat(Worm worm) { + try { + facade.eat(worm); + return true; + } catch (ModelException e) { + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } + throw e; + } + } +} \ No newline at end of file