Gjør den del nødvendige forandringer for å kunne tegne det nye brettet

Oppdaterer IDrawableObject og IDrawableGame og implementerende klasser
Legger til en utility klasse for input og output
Legger til manglende metoder i TextureConverterUtil
Oppdaterer noen tester med nye datatyper
This commit is contained in:
Kristian Knarvik 2020-02-24 18:07:26 +01:00
parent 354542414a
commit f731ebe5cf
12 changed files with 311 additions and 73 deletions

View File

@ -7,10 +7,12 @@ import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.element_properties.GameTexture;
import inf112.fiasko.roborally.game.Game; import inf112.fiasko.roborally.game.Game;
import inf112.fiasko.roborally.game.IDrawableGame; import inf112.fiasko.roborally.game.IDrawableGame;
import inf112.fiasko.roborally.objects.IDrawableObject; import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.utility.IOUtil;
import java.util.List;
/** /**
* This class renders a game using libgdx * This class renders a game using libgdx
@ -23,6 +25,8 @@ public class GameLauncher extends ApplicationAdapter {
private Texture robotTexture; private Texture robotTexture;
private Texture textureSheet; private Texture textureSheet;
private final int tileDimensions = 64;
@Override @Override
public void create() { public void create() {
//Loads some textures //Loads some textures
@ -31,8 +35,11 @@ public class GameLauncher extends ApplicationAdapter {
game = new Game(); game = new Game();
camera = new OrthographicCamera(); camera = new OrthographicCamera();
camera.setToOrtho(false, game.getWidth(), game.getHeight()); camera.setToOrtho(false, game.getWidth() * tileDimensions,
game.getHeight() * tileDimensions);
batch = new SpriteBatch(); batch = new SpriteBatch();
/*MyTextInputListener listener = new MyTextInputListener();
Gdx.input.getTextInput(listener, "Input name", "", "Name");*/
} }
/** /**
@ -45,8 +52,12 @@ public class GameLauncher extends ApplicationAdapter {
batch.setProjectionMatrix(camera.combined); batch.setProjectionMatrix(camera.combined);
batch.begin(); batch.begin();
//Draws all elements the game wants to draw //Draws all elements the game wants to draw
for (IDrawableObject object : game.getObjectsToDraw()) { List<IDrawableObject> elementsToDraw = IOUtil.getDrawableObjectsFromGame(game, tileDimensions, tileDimensions);
TextureRegion objectTextureRegion = gameTextureToTextureRegion(object.getTexture()); for (IDrawableObject object : elementsToDraw) {
TextureRegion objectTextureRegion = object.getTexture();
/*System.out.println(object.getTexture() + " " + object.getXPosition() + " " + object.getYPosition() + " " + object.getWidth() + " " +
object.getHeight() + " " + object.getRotation() + " " + objectTextureRegion.getRegionX() + " " +
objectTextureRegion.getRegionY() + " " + objectTextureRegion.getRegionWidth() + " " + objectTextureRegion.getRegionHeight());*/
batch.draw(objectTextureRegion.getTexture(), object.getXPosition(), object.getYPosition(), batch.draw(objectTextureRegion.getTexture(), object.getXPosition(), object.getYPosition(),
(float)object.getWidth()/2, (float)object.getHeight()/2, (float)object.getWidth()/2, (float)object.getHeight()/2,
object.getWidth(), object.getHeight(), 1, 1, object.getRotation(), object.getWidth(), object.getHeight(), 1, 1, object.getRotation(),
@ -64,22 +75,14 @@ public class GameLauncher extends ApplicationAdapter {
batch.dispose(); batch.dispose();
} }
/** /*public static class MyTextInputListener implements Input.TextInputListener {
* Turns a GameTexture element into a TextureRegion element @Override
* public void input (String text) {
* This is necessary to keep all libgdx logic in this class only. Otherwise, testing would be painful. System.out.println(text);
*
* @param gameTexture A GameTexture enum
* @return A Gdx TextureRegion
*/
private TextureRegion gameTextureToTextureRegion(GameTexture gameTexture) {
switch (gameTexture) {
case ROBOT:
return new TextureRegion(robotTexture, 0, 0, 64, 64);
case TILE:
return new TextureRegion(textureSheet, 4*300, 0, 300, 300);
default:
throw new IllegalArgumentException("Non existing texture encountered.");
} }
@Override
public void canceled () {
} }
}*/
} }

View File

@ -1,9 +0,0 @@
package inf112.fiasko.roborally.element_properties;
/**
* This enum represents a drawable texture
*/
public enum GameTexture {
ROBOT,
TILE
}

View File

@ -1,53 +1,77 @@
package inf112.fiasko.roborally.game; package inf112.fiasko.roborally.game;
import inf112.fiasko.roborally.element_properties.GameTexture; import inf112.fiasko.roborally.element_properties.Direction;
import inf112.fiasko.roborally.element_properties.Position;
import inf112.fiasko.roborally.element_properties.RobotID;
import inf112.fiasko.roborally.objects.Board; import inf112.fiasko.roborally.objects.Board;
import inf112.fiasko.roborally.objects.DrawableObject;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.objects.Robot; import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import inf112.fiasko.roborally.utility.BoardLoaderUtil; import inf112.fiasko.roborally.utility.BoardLoaderUtil;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.TimeUnit;
/** /**
* This class represent a game which is drawable using libgdx * This class represent a game which is drawable using libgdx
*/ */
public class Game implements IDrawableGame { public class Game implements IDrawableGame {
private final int TILE_SIZE = 64;
private Board gameBoard; private Board gameBoard;
public Game() { public Game() {
try { try {
List<Robot> robots = new ArrayList<>(); List<Robot> robots = new ArrayList<>();
robots.add(new Robot(RobotID.ROBOT_1, new Position(1, 1)));
gameBoard = BoardLoaderUtil.loadBoard("boards/Checkmate.txt", robots); gameBoard = BoardLoaderUtil.loadBoard("boards/Checkmate.txt", robots);
new Thread(() -> {
try {
runGameLoop();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
} }
private void runGameLoop() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.NORTH);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.EAST);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.NORTH);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.WEST);
TimeUnit.SECONDS.sleep(1);
gameBoard.moveRobot(RobotID.ROBOT_1, Direction.WEST);
}
@Override @Override
public int getWidth() { public int getWidth() {
return gameBoard.getBoardWidth() * TILE_SIZE; return gameBoard.getBoardWidth();
} }
@Override @Override
public int getHeight() { public int getHeight() {
return gameBoard.getBoardHeight() * TILE_SIZE; return gameBoard.getBoardHeight();
} }
@Override @Override
public List<IDrawableObject> getObjectsToDraw() { public List<Tile> getTilesToDraw() {
List<IDrawableObject> list = new ArrayList<>(); return gameBoard.getTiles();
for (int i = 0; i < gameBoard.getBoardWidth(); i++) { }
for (int j = 0; j < gameBoard.getBoardHeight(); j++) {
DrawableObject tile = new DrawableObject(GameTexture.TILE, i * TILE_SIZE, j * TILE_SIZE); @Override
list.add(tile); public List<Wall> getWallsToDraw() {
} return gameBoard.getWalls();
} }
DrawableObject robot = new DrawableObject(GameTexture.ROBOT, TILE_SIZE, TILE_SIZE);
list.add(robot); @Override
return list; public List<Robot> getRobotsToDraw() {
return gameBoard.getAliveRobots();
} }
} }

View File

@ -1,6 +1,8 @@
package inf112.fiasko.roborally.game; package inf112.fiasko.roborally.game;
import inf112.fiasko.roborally.objects.IDrawableObject; import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import java.util.List; import java.util.List;
@ -10,21 +12,41 @@ import java.util.List;
public interface IDrawableGame { public interface IDrawableGame {
/** /**
* Gets the screen width of the game * Gets the number of tiles in the x direction
* @return A positive integer * @return A positive integer
*/ */
int getWidth(); int getWidth();
/** /**
* Gets the screen height of the game * Gets the number of tiles in the y direction
* @return A positive integer * @return A positive integer
*/ */
int getHeight(); int getHeight();
/** /**
* Gets a list of objects which are to be drawn * Gets a list of all the tiles to be drawn
* @return A list of drawable objects in the order they are to be drawn *
* Should return a list readable from top-left to top-right and so on. In other words, the first getWidth() tiles
* should be drawn on the top row from left to right.
*
* @return A list of tiles
*/ */
List<IDrawableObject> getObjectsToDraw(); List<Tile> getTilesToDraw();
/**
* Gets a list of all the walls to be drawn
*
* Should return a list readable from top-left to top-right and so on. In other words, the first getWidth() walls
* should be drawn on the top row from left to right.
*
* @return A list of walls
*/
List<Wall> getWallsToDraw();
/**
* Gets a list of all robots to draw
* @return A list of all robots to draw
*/
List<Robot> getRobotsToDraw();
} }

View File

@ -81,6 +81,22 @@ public class Board {
return new ArrayList<>(robots.values()); return new ArrayList<>(robots.values());
} }
/**
* Gets all the tiles from the board
* @return A list of all tiles on the board
*/
public List<Tile> getTiles() {
return getAllElementsFromGrid(tiles);
}
/**
* Gets all the walls from the board
* @return A list of all the walls on the board
*/
public List<Wall> getWalls() {
return getAllElementsFromGrid(walls);
}
/** /**
* Removes a dead robot from the board over to the dead robot list * Removes a dead robot from the board over to the dead robot list
* @param robot the dead robot * @param robot the dead robot
@ -265,4 +281,20 @@ public class Board {
throw new IllegalArgumentException("It's not possible to move in that direction."); throw new IllegalArgumentException("It's not possible to move in that direction.");
} }
} }
/**
* Gets all elements on a grid
* @param grid The grid to get elements from
* @param <K> The type of the elements int the grid
* @return A list containing all the elements in the grid
*/
private <K> List<K> getAllElementsFromGrid(IGrid<K> grid) {
List<K> elements = new ArrayList<>();
for (int x = grid.getWidth() - 1; x >= 0; x--) {
for (int y = 0; y < grid.getHeight(); y++) {
elements.add(grid.getElement(x, y));
}
}
return elements;
}
} }

View File

@ -1,12 +1,12 @@
package inf112.fiasko.roborally.objects; package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture; import com.badlogic.gdx.graphics.g2d.TextureRegion;
/** /**
* This class represents an object that can be drawn using libgdx * This class represents an object that can be drawn using libgdx
*/ */
public class DrawableObject implements IDrawableObject { public class DrawableObject implements IDrawableObject {
private final GameTexture texture; private final TextureRegion texture;
private final int xPos; private final int xPos;
private final int yPos; private final int yPos;
private int width = 64; private int width = 64;
@ -26,7 +26,7 @@ public class DrawableObject implements IDrawableObject {
* @param flipX Whether to flip/mirror the element over the x axis * @param flipX Whether to flip/mirror the element over the x axis
* @param flipY Whether to flip/mirror the element over the y axis * @param flipY Whether to flip/mirror the element over the y axis
*/ */
public DrawableObject(GameTexture texture, int xPos, int yPos, int width, int height, int rotation, boolean flipX, public DrawableObject(TextureRegion texture, int xPos, int yPos, int width, int height, int rotation, boolean flipX,
boolean flipY) { boolean flipY) {
this.xPos = xPos; this.xPos = xPos;
this.yPos = yPos; this.yPos = yPos;
@ -38,20 +38,38 @@ public class DrawableObject implements IDrawableObject {
this.flipY = flipY; this.flipY = flipY;
} }
/**
* Initializes a drawable object
* @param texture The texture to use for drawing the element
* @param xPos The pixel to start drawing on for the x axis
* @param yPos The pixel to start drawing on for the y axis
* @param width The width of the element
* @param height The height of the element
* @param rotation The amount of degrees to rotate the element counterclockwise
*/
public DrawableObject(TextureRegion texture, int xPos, int yPos, int width, int height, int rotation) {
this.xPos = xPos;
this.yPos = yPos;
this.rotation = rotation;
this.texture = texture;
this.width = width;
this.height = height;
}
/** /**
* Initializes a new drawable object * Initializes a new drawable object
* @param texture The texture to use for drawing the element * @param texture The texture to use for drawing the element
* @param xPos The pixel to start drawing on for the x axis * @param xPos The pixel to start drawing on for the x axis
* @param yPos The pixel to start drawing on for the y axis * @param yPos The pixel to start drawing on for the y axis
*/ */
public DrawableObject(GameTexture texture, int xPos, int yPos) { public DrawableObject(TextureRegion texture, int xPos, int yPos) {
this.xPos = xPos; this.xPos = xPos;
this.yPos = yPos; this.yPos = yPos;
this.texture = texture; this.texture = texture;
} }
@Override @Override
public GameTexture getTexture() { public TextureRegion getTexture() {
return texture; return texture;
} }

View File

@ -77,7 +77,7 @@ public class Grid<K> implements IGrid<K> {
*/ */
private void makeSureCoordinatesAreWithinBounds(int x, int y) { private void makeSureCoordinatesAreWithinBounds(int x, int y) {
if (x < 0 || x >= width || y < 0 || y >= height) { if (x < 0 || x >= width || y < 0 || y >= height) {
throw new IllegalArgumentException(); throw new IllegalArgumentException("Coordinates are outside the bounds of the board.");
} }
} }
} }

View File

@ -1,6 +1,6 @@
package inf112.fiasko.roborally.objects; package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture; import com.badlogic.gdx.graphics.g2d.TextureRegion;
/** /**
* This interface describes an object drawable using libgdx * This interface describes an object drawable using libgdx
@ -11,7 +11,7 @@ public interface IDrawableObject {
* Gets the texture to use for drawing the object * Gets the texture to use for drawing the object
* @return The texture of the object * @return The texture of the object
*/ */
GameTexture getTexture(); TextureRegion getTexture();
/** /**
* Gets the x position the object should be drawn on * Gets the x position the object should be drawn on

View File

@ -0,0 +1,129 @@
package inf112.fiasko.roborally.utility;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.element_properties.Direction;
import inf112.fiasko.roborally.element_properties.Position;
import inf112.fiasko.roborally.game.IDrawableGame;
import inf112.fiasko.roborally.objects.DrawableObject;
import inf112.fiasko.roborally.objects.IDrawableObject;
import inf112.fiasko.roborally.objects.Robot;
import inf112.fiasko.roborally.objects.Tile;
import inf112.fiasko.roborally.objects.Wall;
import java.util.ArrayList;
import java.util.List;
public class IOUtil {
private IOUtil() {}
/**
* Gets a list of all elements which should be drawn from the game provided
* @param game A game implementing IDrawableGame
* @param tileWidth The with of all tiles to be drawn
* @param tileHeight The height of all tiles to be drawn
* @return A list of drawable objects
*/
public static List<IDrawableObject> getDrawableObjectsFromGame(IDrawableGame game, int tileWidth, int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
List<Tile> tilesToDraw = game.getTilesToDraw();
List<Wall> wallsToDraw = game.getWallsToDraw();
List<Robot> robotsToDraw = game.getRobotsToDraw();
int gameWidth = game.getWidth();
int gameHeight = game.getHeight();
drawableObjects.addAll(getDrawableObjectsFromElementList(tilesToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
drawableObjects.addAll(getDrawableObjectsFromElementList(wallsToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
drawableObjects.addAll(getDrawableRobots(robotsToDraw, gameWidth, gameHeight, tileWidth, tileHeight));
return drawableObjects;
}
private static List<IDrawableObject> getDrawableRobots(List<Robot> robots, int gameWidth, int gameHeight, int tileWidth, int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
for (Robot robot : robots) {
TextureRegion region = TextureConverterUtil.convertElement(robot);
Position robotPosition = robot.getPosition();
int rotation = getElementRotation(robot);
IDrawableObject drawableObject = new DrawableObject(region, robotPosition.getXCoordinate() * tileWidth,
(-robotPosition.getYCoordinate() + gameHeight - 1) * tileHeight, tileWidth, tileHeight, rotation);
drawableObjects.add(drawableObject);
}
return drawableObjects;
}
/**
* Gets a list of drawable objects with correct positions from a list of elements
* @param elementsToDraw A list of elements to draw
* @param gameWidth The width of the game board in tiles
* @param gameHeight The height of the game board in tiles
* @param tileWidth The width of a tile
* @param tileHeight The height of a tile
* @param <K> Should be type Robot, Tile or Wall
* @return A list of drawable objects
*/
private static <K> List<IDrawableObject> getDrawableObjectsFromElementList(List<K> elementsToDraw, int gameWidth,
int gameHeight, int tileWidth,
int tileHeight) {
List<IDrawableObject> drawableObjects = new ArrayList<>();
for (int j = 0; j < gameHeight; j++) {
for (int i = j * gameWidth; i < (j + 1) * gameWidth; i++) {
K currentElement = elementsToDraw.get(i);
if (currentElement == null) {
continue;
}
TextureRegion region;
if (currentElement.getClass().isAssignableFrom(Tile.class)) {
Tile tile = (Tile) currentElement;
region = TextureConverterUtil.convertElement(tile);
} else if (currentElement.getClass().isAssignableFrom(Wall.class)) {
Wall wall = (Wall) currentElement;
region = TextureConverterUtil.convertElement(wall);
} else {
throw new IllegalArgumentException("Unknown element type passed to function.");
}
int rotation = getElementRotation(currentElement);
IDrawableObject drawableObject = new DrawableObject(region,
(i % gameWidth) * tileWidth, j * tileHeight, tileWidth, tileHeight, rotation);
drawableObjects.add(drawableObject);
}
}
return drawableObjects;
}
private static <K> int getElementRotation(K element) {
boolean hasRotatedTexture;
Direction direction;
if (element.getClass().isAssignableFrom(Robot.class)) {
Robot robot = (Robot) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(robot);
direction = robot.getFacingDirection();
} else if (element.getClass().isAssignableFrom(Tile.class)) {
Tile tile = (Tile) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(tile);
direction = tile.getDirection();
} else if (element.getClass().isAssignableFrom(Wall.class)) {
Wall wall = (Wall) element;
hasRotatedTexture = TextureConverterUtil.hasRotatedTexture(wall);
direction = wall.getDirection();
} else {
throw new IllegalArgumentException("Unknown element type passed to function.");
}
if (hasRotatedTexture) {
return 0;
}
switch (direction) {
case NORTH:
case NORTH_EAST:
return 0;
case WEST:
case NORTH_WEST:
return 90;
case SOUTH:
case SOUTH_WEST:
return 180;
case EAST:
case SOUTH_EAST:
return 270;
default:
throw new IllegalArgumentException("Invalid element direction encountered.");
}
}
}

View File

@ -67,6 +67,9 @@ public final class TextureConverterUtil {
e.printStackTrace(); e.printStackTrace();
} }
} }
if (wall == null) {
return null;
}
Direction direction = wall.getDirection(); Direction direction = wall.getDirection();
TextureConverterContainer converterContainer = tileSheetWallTextureMappings.get(wall.getWallType()); TextureConverterContainer converterContainer = tileSheetWallTextureMappings.get(wall.getWallType());
if (converterContainer != null) { if (converterContainer != null) {
@ -104,6 +107,24 @@ public final class TextureConverterUtil {
return tileSheetTileHasRotatedTextureMappings.get(tile.getTileType()); return tileSheetTileHasRotatedTextureMappings.get(tile.getTileType());
} }
/**
* Checks whether a wall has textures for different rotations
* @param wall The wall to check
* @return True if rotated versions of the texture exists. False otherwise
*/
public static boolean hasRotatedTexture(Wall wall) {
return true;
}
/**
* Checks whether a robot has textures for different rotations
* @param robot The robot to check
* @return True if rotated versions of the texture exists. False otherwise
*/
public static boolean hasRotatedTexture(Robot robot) {
return false;
}
/** /**
* Loads mappings between a tile and texture * Loads mappings between a tile and texture
* *

View File

@ -1,10 +1,6 @@
package inf112.fiasko.roborally.game; package inf112.fiasko.roborally.game;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import inf112.fiasko.roborally.game.Game;
import inf112.fiasko.roborally.game.IDrawableGame;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -35,9 +31,4 @@ public class GameTest {
public void gameHeightIsMaximumFullHD() { public void gameHeightIsMaximumFullHD() {
assertTrue(game.getHeight() <= 1080); assertTrue(game.getHeight() <= 1080);
} }
@Test
public void getObjectsToDrawReturnsNonemptyList() {
assertFalse(game.getObjectsToDraw().isEmpty());
}
} }

View File

@ -1,17 +1,24 @@
package inf112.fiasko.roborally.objects; package inf112.fiasko.roborally.objects;
import inf112.fiasko.roborally.element_properties.GameTexture; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import inf112.fiasko.roborally.GdxTestRunner;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame; import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
@RunWith(GdxTestRunner.class)
public class DrawableObjectTest { public class DrawableObjectTest {
public static final GameTexture TEXTURE_MIN_ARG = GameTexture.TILE; private static final Texture textureSheet = new Texture(Gdx.files.internal("assets/tiles.png"));
public static final GameTexture TEXTURE_MAX_ARG = GameTexture.ROBOT; private static final Texture robotTexture = new Texture(Gdx.files.internal("assets/Robot.png"));
public static final TextureRegion TEXTURE_MIN_ARG = new TextureRegion(textureSheet, 4*300, 0, 300, 300);
public static final TextureRegion TEXTURE_MAX_ARG = new TextureRegion(robotTexture, 0, 0, 64, 64);
public static final int X_POSITION_MIN_ARG = 5; public static final int X_POSITION_MIN_ARG = 5;
public static final int Y_POSITION_MIN_ARG = 8; public static final int Y_POSITION_MIN_ARG = 8;
public static final int X_POSITION_MAX_ARG = 6; public static final int X_POSITION_MAX_ARG = 6;