From c6c2e448cc4f22a0eec373adb7224799bea2dab8 Mon Sep 17 00:00:00 2001 From: Ahmed Abdel Samea Khalifa Date: Sun, 26 Mar 2017 18:37:58 -0400 Subject: [PATCH] Fool Proofing GVG-AI using Logger system --- src/core/game/Game.java | 2946 +++++++++-------- src/core/game/SLDescription.java | 40 +- src/core/logging/Logger.java | 4 +- src/core/logging/Message.java | 8 + src/ontology/effects/binary/Align.java | 6 + src/ontology/effects/binary/PullWithIt.java | 6 + .../effects/binary/TeleportToExit.java | 11 +- 7 files changed, 1571 insertions(+), 1450 deletions(-) diff --git a/src/core/game/Game.java b/src/core/game/Game.java index bf707eee..4ac49401 100755 --- a/src/core/game/Game.java +++ b/src/core/game/Game.java @@ -33,16 +33,11 @@ import tools.pathfinder.Node; import tools.pathfinder.PathFinder; - /** - * Created with IntelliJ IDEA. - * User: Diego - * Date: 17/10/13 - * Time: 13:42 - * This is a Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl + * Created with IntelliJ IDEA. User: Diego Date: 17/10/13 Time: 13:42 This is a + * Java port from Tom Schaul's VGDL - https://github.com/schaul/py-vgdl */ -public abstract class Game -{ +public abstract class Game { /** * z-level of sprite types (in case of overlap) @@ -55,46 +50,43 @@ public abstract class Game protected boolean[] singletons; /** - * Content objects for the different sprite types.. - * The index is the type of object - * Content encloses information about the class of the object and its parameters. + * Content objects for the different sprite types.. The index is the type of + * object Content encloses information about the class of the object and its + * parameters. */ protected Content[] classConst; - /** * Parameters for a Game Space. Unused in normal games. */ public HashMap parameters; - + /** - * List of template sprites, one for each object in the above - * "classConst" array. + * List of template sprites, one for each object in the above "classConst" + * array. */ protected VGDLSprite[] templateSprites; /** - * Groups of sprites in the level. Each element of the array is a - * collection of sprites of a given type, which is also the index - * of the array. + * Groups of sprites in the level. Each element of the array is a collection + * of sprites of a given type, which is also the index of the array. */ protected SpriteGroup[] spriteGroups; /** - * Relationships for collisions: double array of (list of) effects. Interaction between - * two sprites can trigger more than one effect. - * collisionEffects[] -> int id of the FIRST element taking part on the effects. - * collisionEffects[][] -> int id of the SECOND element taking part on the effects. + * Relationships for collisions: double array of (list of) effects. + * Interaction between two sprites can trigger more than one effect. + * collisionEffects[] -> int id of the FIRST element taking part on the + * effects. collisionEffects[][] -> int id of the SECOND element taking part + * on the effects. * */ protected ArrayList[][] collisionEffects; - /** * Pairs of all defined effects in the game. */ - protected ArrayList> definedEffects; - + protected ArrayList> definedEffects; /** * List of EOS effects @@ -106,32 +98,28 @@ public abstract class Game */ protected TreeSet timeEffects; - /** * List of types that can trigger an EOS effect. */ protected ArrayList definedEOSEffects; /** - * Historic of events related to the avatar happened during the game. - * The entries are ordered asc. by game step. + * Historic of events related to the avatar happened during the game. The + * entries are ordered asc. by game step. */ protected TreeSet historicEvents; - /** - * For each entry, int identifier of sprite type, a list with all the itypes this - * sprite belongs to. + * For each entry, int identifier of sprite type, a list with all the itypes + * this sprite belongs to. */ protected ArrayList[] iSubTypes; - /** - * For each entry, int identifier of sprite type, a list with all the itypes this - * sprite belongs to. + * For each entry, int identifier of sprite type, a list with all the itypes + * this sprite belongs to. */ - protected ArrayList>[] shieldedEffects; - + protected ArrayList>[] shieldedEffects; /** * Arraylist to hold collisions between objects in every frame @@ -141,8 +129,7 @@ public abstract class Game /** * Mapping between characters in the level and the entities they represent. */ - protected HashMap> charMapping; - + protected HashMap> charMapping; /** * Termination set conditions to finish the game. @@ -193,7 +180,7 @@ public abstract class Game * Handling when the window is closed */ public static WindowInput wi = new WindowInput(); - + /** * Size of the block in pixels. */ @@ -220,7 +207,8 @@ public abstract class Game protected static int MAX_SPRITES; /** - * Random number generator for this game. It can only be received when the game is started. + * Random number generator for this game. It can only be received when the + * game is started. */ private Random random; @@ -235,8 +223,8 @@ public abstract class Game private int wallId; /** - * Flag that can only be set to true externally. If true, - * the agent is disqualified. + * Flag that can only be set to true externally. If true, the agent is + * disqualified. */ private boolean disqualified; @@ -245,29 +233,26 @@ public abstract class Game */ protected int nextSpriteID; - /** - * Key Handler for human play. The default is CompetitionParameters.KEY_INPUT + * Key Handler for human play. The default is + * CompetitionParameters.KEY_INPUT */ public String key_handler; - /** * Pathfinder. */ protected PathFinder pathf; - /** - * Avatars last actions. - * Array for all avatars in the game. - * Index in array corresponds to playerID. + * Avatars last actions. Array for all avatars in the game. Index in array + * corresponds to playerID. */ protected Types.ACTIONS[] avatarLastAction; - public int no_players = 1; //default to single player + public int no_players = 1; // default to single player - public int no_counters = 0; //default no counters + public int no_counters = 0; // default no counters public int[] counter; public static KeyHandler ki; @@ -275,739 +260,764 @@ public abstract class Game /** * Default constructor. */ - public Game() - { - //data structures to hold the game definition. - definedEffects = new ArrayList>(); - definedEOSEffects = new ArrayList(); - charMapping = new HashMap>(); - terminations = new ArrayList(); - historicEvents = new TreeSet(); - timeEffects = new TreeSet(); + public Game() { + // data structures to hold the game definition. + definedEffects = new ArrayList>(); + definedEOSEffects = new ArrayList(); + charMapping = new HashMap>(); + terminations = new ArrayList(); + historicEvents = new TreeSet(); + timeEffects = new TreeSet(); - //Game attributes: - size = new Dimension(); - is_stochastic = false; - disqualified = false; - num_sprites = 0; - nextSpriteID = 0; + // Game attributes: + size = new Dimension(); + is_stochastic = false; + disqualified = false; + num_sprites = 0; + nextSpriteID = 0; - loadDefaultConstr(); + loadDefaultConstr(); } /** * Loads the constructor information for default objects (walls, avatar). */ - private void loadDefaultConstr() - { - //If more elements are added here, initSprites() must be modified accordingly! - VGDLRegistry.GetInstance().registerSprite("wall"); - VGDLRegistry.GetInstance().registerSprite("avatar"); + private void loadDefaultConstr() { + // If more elements are added here, initSprites() must be modified + // accordingly! + VGDLRegistry.GetInstance().registerSprite("wall"); + VGDLRegistry.GetInstance().registerSprite("avatar"); } /** * Initialisation after the game is parsed. */ public void initMulti() { - avatars = new MovingAvatar[no_players]; - avatarLastAction = new Types.ACTIONS[no_players]; - for (int i = 0; i < no_players; i++) - avatarLastAction[i] = Types.ACTIONS.ACTION_NIL; + avatars = new MovingAvatar[no_players]; + avatarLastAction = new Types.ACTIONS[no_players]; + for (int i = 0; i < no_players; i++) + avatarLastAction[i] = Types.ACTIONS.ACTION_NIL; - counter = new int[no_counters]; + counter = new int[no_counters]; } /** * Initializes the sprite structures that hold the game. - * @param spOrder order of sprite types to be drawn on the screen. - * @param sings sprites that are marked as singletons. - * @param constructors map of sprite constructor's information. + * + * @param spOrder + * order of sprite types to be drawn on the screen. + * @param sings + * sprites that are marked as singletons. + * @param constructors + * map of sprite constructor's information. */ public void initSprites(ArrayList spOrder, ArrayList sings, - HashMap constructors) - { - ArrayList resources = new ArrayList(); - spriteOrder = new int[spOrder.size()]; - - //We need here the default 2 sprites: - avatarId = VGDLRegistry.GetInstance().getRegisteredSpriteValue("avatar"); - wallId = VGDLRegistry.GetInstance().getRegisteredSpriteValue("wall"); - - //1. "avatar" ALWAYS at the end of the array. - for (int i = 0; i < no_players; i++) { - spriteOrder[spriteOrder.length - 1 - i] = avatarId; - } - - //2. Other sprite types are sorted using spOrder - int i = 0; - for(Integer intId : spOrder) - { - if(intId != avatarId) - { - spriteOrder[i++] = intId; - } - } - - //Singletons - singletons = new boolean[VGDLRegistry.GetInstance().numSpriteTypes()]; - for(Integer intId : sings) - { - singletons[intId] = true; - } - - //Constructors, as many as number of sprite types, so they are accessed by its id: - classConst = new Content[VGDLRegistry.GetInstance().numSpriteTypes()]; - templateSprites = new VGDLSprite[classConst.length]; - - //By default, we have 2 constructors: - Content wallConst = new SpriteContent("wall", "Immovable"); - wallConst.parameters.put("color","DARKGRAY"); - ((SpriteContent)wallConst).itypes.add(wallId); - classConst[wallId] = wallConst; - - Content avatarConst = new SpriteContent("avatar", "MovingAvatar"); - ((SpriteContent)avatarConst).itypes.add(avatarId); - classConst[avatarId] = avatarConst; - - //Now, the other constructors. - Set> entries = constructors.entrySet(); - for(Map.Entry entry : entries) - { - classConst[entry.getKey()] = entry.getValue(); - - //Special case: we create a dummy Resource sprite of each resource type. - String refClass = entry.getValue().referenceClass; - if(refClass != null && refClass.equals("Resource")) - { - VGDLSprite resourceTest = VGDLFactory.GetInstance(). - createSprite(this, entry.getValue(), new Vector2d(0,0), new Dimension(1,1)); - resources.add((Resource)resourceTest); - } - } - - //Structures to hold game sprites, as many as number of sprite types, so they are accessed by its id: - spriteGroups = new SpriteGroup[classConst.length]; - shieldedEffects = new ArrayList[classConst.length]; - collisionEffects = new ArrayList[classConst.length][classConst.length]; - eosEffects = new ArrayList[classConst.length]; - iSubTypes = new ArrayList[classConst.length]; - bucketList = new Bucket[classConst.length]; - resources_limits = new int[classConst.length]; - resources_colors = new Color[classConst.length]; - - //For each sprite type... - for(int j = 0; j < spriteGroups.length; ++j) - { - //Create the space for the sprites and effects of this type. - spriteGroups[j] = new SpriteGroup(j); - shieldedEffects[j] = new ArrayList<>(); - eosEffects[j] = new ArrayList(); - timeEffects = new TreeSet(); - bucketList[j] = new Bucket(); - - //Declare the extended types list of this sprite type. - iSubTypes[j] = (ArrayList) ((SpriteContent)classConst[j]).subtypes.clone(); - - for(int k = 0; k < spriteGroups.length; ++k) - { - //Create the array list of collision effects for each pair of sprite types. - collisionEffects[j][k] = new ArrayList(); - } - - } - - //Add walls and avatars to the subtypes list. - if(!iSubTypes[wallId].contains(wallId)) - iSubTypes[wallId].add(wallId); - - if(!iSubTypes[avatarId].contains(avatarId)) - iSubTypes[avatarId].add(avatarId); - - //Resources: use the list of resources created before to store limit and color of each resource. - for(i = 0; i < resources.size(); ++i) - { - Resource r = resources.get(i); - resources_limits[r.resource_type] = r.limit; - resources_colors[r.resource_type] = r.color; - } - } - + HashMap constructors) { + ArrayList resources = new ArrayList(); + spriteOrder = new int[spOrder.size()]; + + // We need here the default 2 sprites: + avatarId = VGDLRegistry.GetInstance().getRegisteredSpriteValue("avatar"); + wallId = VGDLRegistry.GetInstance().getRegisteredSpriteValue("wall"); + + // 1. "avatar" ALWAYS at the end of the array. + for (int i = 0; i < no_players; i++) { + spriteOrder[spriteOrder.length - 1 - i] = avatarId; + } + + // 2. Other sprite types are sorted using spOrder + int i = 0; + for (Integer intId : spOrder) { + if (intId != avatarId) { + spriteOrder[i++] = intId; + } + } + + // Singletons + singletons = new boolean[VGDLRegistry.GetInstance().numSpriteTypes()]; + for (Integer intId : sings) { + singletons[intId] = true; + } + + // Constructors, as many as number of sprite types, so they are accessed + // by its id: + classConst = new Content[VGDLRegistry.GetInstance().numSpriteTypes()]; + templateSprites = new VGDLSprite[classConst.length]; + + // By default, we have 2 constructors: + Content wallConst = new SpriteContent("wall", "Immovable"); + wallConst.parameters.put("color", "DARKGRAY"); + ((SpriteContent) wallConst).itypes.add(wallId); + classConst[wallId] = wallConst; + + Content avatarConst = new SpriteContent("avatar", "MovingAvatar"); + ((SpriteContent) avatarConst).itypes.add(avatarId); + classConst[avatarId] = avatarConst; + + // Now, the other constructors. + Set> entries = constructors.entrySet(); + for (Map.Entry entry : entries) { + classConst[entry.getKey()] = entry.getValue(); + + // Special case: we create a dummy Resource sprite of each resource + // type. + String refClass = entry.getValue().referenceClass; + if (refClass != null && refClass.equals("Resource")) { + VGDLSprite resourceTest = VGDLFactory.GetInstance().createSprite(this, entry.getValue(), + new Vector2d(0, 0), new Dimension(1, 1)); + resources.add((Resource) resourceTest); + } + } + + // Structures to hold game sprites, as many as number of sprite types, + // so they are accessed by its id: + spriteGroups = new SpriteGroup[classConst.length]; + shieldedEffects = new ArrayList[classConst.length]; + collisionEffects = new ArrayList[classConst.length][classConst.length]; + eosEffects = new ArrayList[classConst.length]; + iSubTypes = new ArrayList[classConst.length]; + bucketList = new Bucket[classConst.length]; + resources_limits = new int[classConst.length]; + resources_colors = new Color[classConst.length]; + + // For each sprite type... + for (int j = 0; j < spriteGroups.length; ++j) { + // Create the space for the sprites and effects of this type. + spriteGroups[j] = new SpriteGroup(j); + shieldedEffects[j] = new ArrayList<>(); + eosEffects[j] = new ArrayList(); + timeEffects = new TreeSet(); + bucketList[j] = new Bucket(); + + // Declare the extended types list of this sprite type. + iSubTypes[j] = (ArrayList) ((SpriteContent) classConst[j]).subtypes.clone(); + + for (int k = 0; k < spriteGroups.length; ++k) { + // Create the array list of collision effects for each pair of + // sprite types. + collisionEffects[j][k] = new ArrayList(); + } + + } + + // Add walls and avatars to the subtypes list. + if (!iSubTypes[wallId].contains(wallId)) + iSubTypes[wallId].add(wallId); + + if (!iSubTypes[avatarId].contains(avatarId)) + iSubTypes[avatarId].add(avatarId); + + // Resources: use the list of resources created before to store limit + // and color of each resource. + for (i = 0; i < resources.size(); ++i) { + Resource r = resources.get(i); + resources_limits[r.resource_type] = r.limit; + resources_colors[r.resource_type] = r.color; + } + } + /** * Check if the current itype has no children nodes - * @param itype sprite index - * @return true if its lead node, false otherwise + * + * @param itype + * sprite index + * @return true if its lead node, false otherwise */ - private boolean isLeafNode(int itype){ - SpriteContent sc = (SpriteContent)classConst[itype]; - - return sc.subtypes.size() <= 1 || - sc.subtypes.get(sc.subtypes.size() - 1) == itype; + private boolean isLeafNode(int itype) { + SpriteContent sc = (SpriteContent) classConst[itype]; + + return sc.subtypes.size() <= 1 || sc.subtypes.get(sc.subtypes.size() - 1) == itype; } - + /** * Get all parent sprites for a certain sprite - * @param itype id for the current node + * + * @param itype + * id for the current node * @return a list of all parent nodes' ids */ - private ArrayList parentNodes(int itype){ - SpriteContent sc = (SpriteContent)classConst[itype]; - - ArrayList parents = new ArrayList(); - parents.addAll(sc.itypes); - parents.remove(parents.size() - 1); - - return parents; + private ArrayList parentNodes(int itype) { + SpriteContent sc = (SpriteContent) classConst[itype]; + + ArrayList parents = new ArrayList(); + parents.addAll(sc.itypes); + parents.remove(parents.size() - 1); + + return parents; } - + /** * Expand a non leaf node using its children - * @param itype sprite index - * @return a list of all leaf children under the hierarchy of itype sprite - */ - private ArrayList expandNonLeafNode(int itype){ - ArrayList result = new ArrayList(); - boolean[] visited = new boolean[classConst.length]; - ArrayList queue = new ArrayList(); - queue.add(itype); - - while(!queue.isEmpty()){ - int current = queue.remove(0); - if(visited[current]){ - continue; - } - - if(isLeafNode(current)){ - result.add(VGDLRegistry.GetInstance().getRegisteredSpriteKey(current)); - } - else{ - SpriteContent sc = (SpriteContent)classConst[current]; - queue.addAll(sc.subtypes); - } - visited[current] = true; - } - - return result; + * + * @param itype + * sprite index + * @return a list of all leaf children under the hierarchy of itype sprite + */ + private ArrayList expandNonLeafNode(int itype) { + ArrayList result = new ArrayList(); + boolean[] visited = new boolean[classConst.length]; + ArrayList queue = new ArrayList(); + queue.add(itype); + + while (!queue.isEmpty()) { + int current = queue.remove(0); + if (visited[current]) { + continue; + } + + if (isLeafNode(current)) { + result.add(VGDLRegistry.GetInstance().getRegisteredSpriteKey(current)); + } else { + SpriteContent sc = (SpriteContent) classConst[current]; + queue.addAll(sc.subtypes); + } + visited[current] = true; + } + + return result; } /** * Method used to access the number of players in a game. + * * @return number of players. */ - public int getNoPlayers() { return no_players; } + public int getNoPlayers() { + return no_players; + } - public int getNoCounters() {return no_counters;} + public int getNoCounters() { + return no_counters; + } - public int getValueCounter(int idx) {return counter[idx];} + public int getValueCounter(int idx) { + return counter[idx]; + } /** * return sprite type of certain sprite - * @param sp sprite object - * @return sprite type (avatar, resource, portal, npc, static, moving) + * + * @param sp + * sprite object + * @return sprite type (avatar, resource, portal, npc, static, moving) */ - private int getSpriteCategory(VGDLSprite sp) - { - if(sp.is_avatar) - return Types.TYPE_AVATAR; + private int getSpriteCategory(VGDLSprite sp) { + if (sp.is_avatar) + return Types.TYPE_AVATAR; - //Is it a resource? - if(sp.is_resource) - return Types.TYPE_RESOURCE; + // Is it a resource? + if (sp.is_resource) + return Types.TYPE_RESOURCE; - //Is it a portal? - if(sp.portal) - return Types.TYPE_PORTAL; + // Is it a portal? + if (sp.portal) + return Types.TYPE_PORTAL; - //Is it npc? - if(sp.is_npc) - return Types.TYPE_NPC; + // Is it npc? + if (sp.is_npc) + return Types.TYPE_NPC; - //Is it immovable? - if(sp.is_static) - return Types.TYPE_STATIC; + // Is it immovable? + if (sp.is_static) + return Types.TYPE_STATIC; - //is it created by the avatar? - if(sp.is_from_avatar) - return Types.TYPE_FROMAVATAR; + // is it created by the avatar? + if (sp.is_from_avatar) + return Types.TYPE_FROMAVATAR; - return Types.TYPE_MOVABLE; + return Types.TYPE_MOVABLE; } - + /** * Convert a sprite content object to Sprite Data object - * @param sc sprite content object for a certain sprite - * @return sprite data object for the current sprite content - */ - private SpriteData initializeSpriteData(SpriteContent sc){ - SpriteData data = new SpriteData(); - data.name = sc.identifier; - data.type = sc.referenceClass; - - VGDLSprite sprite = VGDLFactory.GetInstance().createSprite(this, sc, new Vector2d(), new Dimension(1, 1)); - switch(getSpriteCategory(sprite)){ - case Types.TYPE_NPC: - data.isNPC = true; - break; - case Types.TYPE_AVATAR: - data.isAvatar = true; - break; - case Types.TYPE_PORTAL: - data.isPortal = true; - break; - case Types.TYPE_RESOURCE: - data.isResource = true; - break; - case Types.TYPE_STATIC: - data.isStatic = true; - break; - } - - ArrayList dependentSprites = sprite.getDependentSprites(); - for(String s:dependentSprites){ - ArrayList expandedSprites = expandNonLeafNode(VGDLRegistry.GetInstance().getRegisteredSpriteValue(s)); - data.sprites.addAll(expandedSprites); - } - - return data; - } - + * + * @param sc + * sprite content object for a certain sprite + * @return sprite data object for the current sprite content + */ + private SpriteData initializeSpriteData(SpriteContent sc) { + SpriteData data = new SpriteData(); + data.name = sc.identifier; + data.type = sc.referenceClass; + + VGDLSprite sprite = VGDLFactory.GetInstance().createSprite(this, sc, new Vector2d(), new Dimension(1, 1)); + switch (getSpriteCategory(sprite)) { + case Types.TYPE_NPC: + data.isNPC = true; + break; + case Types.TYPE_AVATAR: + data.isAvatar = true; + break; + case Types.TYPE_PORTAL: + data.isPortal = true; + break; + case Types.TYPE_RESOURCE: + data.isResource = true; + break; + case Types.TYPE_STATIC: + data.isStatic = true; + break; + } + + ArrayList dependentSprites = sprite.getDependentSprites(); + for (String s : dependentSprites) { + ArrayList expandedSprites = expandNonLeafNode( + VGDLRegistry.GetInstance().getRegisteredSpriteValue(s)); + data.sprites.addAll(expandedSprites); + } + + return data; + } + /** * Get an array of sprite data objects for all leaf sprite nodes. - * @return Array of sprite data - */ - public ArrayList getSpriteData(){ - ArrayList result = new ArrayList(); - - for(int i = 0; i < classConst.length; i++){ - SpriteContent sc = (SpriteContent)classConst[i]; - if(isLeafNode(i)){ - result.add(initializeSpriteData(sc)); - } - } - - return result; - } - + * + * @return Array of sprite data + */ + public ArrayList getSpriteData() { + ArrayList result = new ArrayList(); + + for (int i = 0; i < classConst.length; i++) { + SpriteContent sc = (SpriteContent) classConst[i]; + if (isLeafNode(i)) { + result.add(initializeSpriteData(sc)); + } + } + + return result; + } + /** * Construct and return a temporary avatar sprite + * * @return a temproary avatar sprite */ - public VGDLSprite getTempAvatar(SpriteData sprite){ - avatarId = VGDLRegistry.GetInstance().getRegisteredSpriteValue(sprite.name); - if(((SpriteContent)classConst[avatarId]).referenceClass != null){ - VGDLSprite result = VGDLFactory.GetInstance().createSprite(this, (SpriteContent) classConst[avatarId], - new Vector2d(), new Dimension(1, 1)); - if(result != null){ - return result; - } - } - - return null; - } - - /** - * Return an array of termination data objects. These objects represents - * the termination conditions for the game + public VGDLSprite getTempAvatar(SpriteData sprite) { + avatarId = VGDLRegistry.GetInstance().getRegisteredSpriteValue(sprite.name); + if (((SpriteContent) classConst[avatarId]).referenceClass != null) { + VGDLSprite result = VGDLFactory.GetInstance().createSprite(this, (SpriteContent) classConst[avatarId], + new Vector2d(), new Dimension(1, 1)); + if (result != null) { + return result; + } + } + + return null; + } + + /** + * Return an array of termination data objects. These objects represents the + * termination conditions for the game + * * @return array of Termination Data objects */ - public ArrayList getTerminationData(){ - ArrayList result = new ArrayList(); - - TerminationData td; - for(Termination tr:terminations){ - td = new TerminationData(); - int lastDot = tr.getClass().getName().lastIndexOf('.'); - td.type = tr.getClass().getName().substring(lastDot + 1); - td.limit = tr.limit; - td.win = tr.win; - - ArrayList sprites = tr.getTerminationSprites(); - for(String s:sprites){ - int itype = VGDLRegistry.GetInstance().getRegisteredSpriteValue(s); - if(isLeafNode(itype)){ - td.sprites.add(s); - } - else{ - td.sprites.addAll(expandNonLeafNode(itype)); - } - } - - result.add(td); - } - - return result; - } - - /** - * Get a list of interaction data objects between two sprite types. - * These objects represents the effect happened to the first sprite type. - * @param itype1 The first sprite type object - * @param itype2 The second sprite type object - * @return array of interaction data objects. - */ - public ArrayList getInteractionData(int itype1, int itype2){ - ArrayList results = new ArrayList(); - - ArrayList parent1 = new ArrayList(); - ArrayList parent2 = new ArrayList(); - - if(itype1 != -1){ - parent1.addAll(parentNodes(itype1)); - parent1.add(itype1); - } - - if(itype2 != -1){ - parent2.addAll(parentNodes(itype2)); - parent2.add(itype2); - } - - ArrayList effects = new ArrayList(); - if(parent1.size() > 0 && parent2.size() > 0){ - for(int p1:parent1){ - for(int p2:parent2){ - effects.addAll(getCollisionEffects(p1, p2)); - } - } - } - else if(parent1.size() > 0){ - for(int p1:parent1){ - effects.addAll(getEosEffects(p1)); - - } - } - else if(parent2.size() > 0){ - for(int p2:parent2){ - effects.addAll(getEosEffects(p2)); - } - } - - InteractionData temp; - for(Effect e:effects){ - temp = new InteractionData(); - temp.type = e.getClass().getName(); - temp.type = temp.type.substring(temp.type.lastIndexOf('.') + 1); - temp.scoreChange = e.scoreChange; - temp.sprites.addAll(e.getEffectSprites()); - - results.add(temp); - } - - return results; + public ArrayList getTerminationData() { + ArrayList result = new ArrayList(); + + TerminationData td; + for (Termination tr : terminations) { + td = new TerminationData(); + int lastDot = tr.getClass().getName().lastIndexOf('.'); + td.type = tr.getClass().getName().substring(lastDot + 1); + td.limit = tr.limit; + td.win = tr.win; + + ArrayList sprites = tr.getTerminationSprites(); + for (String s : sprites) { + int itype = VGDLRegistry.GetInstance().getRegisteredSpriteValue(s); + if (isLeafNode(itype)) { + td.sprites.add(s); + } else { + td.sprites.addAll(expandNonLeafNode(itype)); + } + } + + result.add(td); + } + + return result; + } + + /** + * Get a list of interaction data objects between two sprite types. These + * objects represents the effect happened to the first sprite type. + * + * @param itype1 + * The first sprite type object + * @param itype2 + * The second sprite type object + * @return array of interaction data objects. + */ + public ArrayList getInteractionData(int itype1, int itype2) { + ArrayList results = new ArrayList(); + + ArrayList parent1 = new ArrayList(); + ArrayList parent2 = new ArrayList(); + + if (itype1 != -1) { + parent1.addAll(parentNodes(itype1)); + parent1.add(itype1); + } + + if (itype2 != -1) { + parent2.addAll(parentNodes(itype2)); + parent2.add(itype2); + } + + ArrayList effects = new ArrayList(); + if (parent1.size() > 0 && parent2.size() > 0) { + for (int p1 : parent1) { + for (int p2 : parent2) { + effects.addAll(getCollisionEffects(p1, p2)); + } + } + } else if (parent1.size() > 0) { + for (int p1 : parent1) { + effects.addAll(getEosEffects(p1)); + + } + } else if (parent2.size() > 0) { + for (int p2 : parent2) { + effects.addAll(getEosEffects(p2)); + } + } + + InteractionData temp; + for (Effect e : effects) { + temp = new InteractionData(); + temp.type = e.getClass().getName(); + temp.type = temp.type.substring(temp.type.lastIndexOf('.') + 1); + temp.scoreChange = e.scoreChange; + temp.sprites.addAll(e.getEffectSprites()); + + results.add(temp); + } + + return results; } /** * Sets the game back to the state prior to load a level. */ - public void reset() - { - num_sprites = 0; - - for (int i = 0; i < no_players; i++) { - avatars[i] = null; - } - for (int i = 0; i < no_counters; i++) { - counter[i] = 0; - } - isEnded = false; - gameTick = -1; - disqualified = false; - avatarLastAction = new Types.ACTIONS[no_players]; - for (int i = 0; i < no_players; i++) - avatarLastAction[i] = Types.ACTIONS.ACTION_NIL; - - //For each sprite type... - for (int i = 0; i < spriteGroups.length; ++i) - { - //Create the space for the sprites and effects of this type. - spriteGroups[i].clear(); - } - - if(kill_list != null){ - kill_list.clear(); - } - for(int j = 0; j < spriteGroups.length; ++j) - { - bucketList[j].clear(); - } - - for(int i = 0; i < templateSprites.length; ++i) - { - templateSprites[i] = null; - } - - historicEvents.clear(); - - resetShieldEffects(); + public void reset() { + num_sprites = 0; + + for (int i = 0; i < no_players; i++) { + avatars[i] = null; + } + for (int i = 0; i < no_counters; i++) { + counter[i] = 0; + } + isEnded = false; + gameTick = -1; + disqualified = false; + avatarLastAction = new Types.ACTIONS[no_players]; + for (int i = 0; i < no_players; i++) + avatarLastAction[i] = Types.ACTIONS.ACTION_NIL; + + // For each sprite type... + for (int i = 0; i < spriteGroups.length; ++i) { + // Create the space for the sprites and effects of this type. + spriteGroups[i].clear(); + } + + if (kill_list != null) { + kill_list.clear(); + } + for (int j = 0; j < spriteGroups.length; ++j) { + bucketList[j].clear(); + } + + for (int i = 0; i < templateSprites.length; ++i) { + templateSprites[i] = null; + } + + historicEvents.clear(); + + resetShieldEffects(); } /** * Starts the forward model for the game. */ - public void initForwardModel() - { - fwdModel = new ForwardModel(this); - fwdModel.update(this); + public void initForwardModel() { + fwdModel = new ForwardModel(this); + fwdModel.update(this); } /** * Reads the parameters of a game type. - * @param content list of parameter-value pairs. + * + * @param content + * list of parameter-value pairs. */ - protected void parseParameters(GameContent content) - { - VGDLFactory factory = VGDLFactory.GetInstance(); - Class refClass = VGDLFactory.registeredGames.get(content.referenceClass); - //System.out.inn("refClass" + refClass.toString()); - if (!this.getClass().equals(refClass)) { - System.out.println("Error: Game subclass instance not the same as content.referenceClass" + - " " + this.getClass() + - " " + refClass); - return; - } + protected void parseParameters(GameContent content) { + VGDLFactory factory = VGDLFactory.GetInstance(); + Class refClass = VGDLFactory.registeredGames.get(content.referenceClass); + // System.out.inn("refClass" + refClass.toString()); + if (!this.getClass().equals(refClass)) { + System.out.println("Error: Game subclass instance not the same as content.referenceClass" + " " + + this.getClass() + " " + refClass); + return; + } - factory.parseParameters(content, this); + factory.parseParameters(content, this); - //taking care of the key handler parameter: + // taking care of the key handler parameter: - if(key_handler != null && key_handler.equalsIgnoreCase("Pulse")) - CompetitionParameters.KEY_HANDLER = CompetitionParameters.KEY_PULSE; + if (key_handler != null && key_handler.equalsIgnoreCase("Pulse")) + CompetitionParameters.KEY_HANDLER = CompetitionParameters.KEY_PULSE; - ki = CompetitionParameters.KEY_HANDLER == CompetitionParameters.KEY_INPUT ? new KeyInput() : new KeyPulse(no_players); + ki = CompetitionParameters.KEY_HANDLER == CompetitionParameters.KEY_INPUT ? new KeyInput() + : new KeyPulse(no_players); } /** - * Adds a new sprite to the pool of sprites of the game. Increments the sprite - * counter and also modifies is_stochastic and the avatar accordingly. - * @param sprite the new sprite to add. - * @param itype main int type of this sprite (leaf of the hierarchy of types). + * Adds a new sprite to the pool of sprites of the game. Increments the + * sprite counter and also modifies is_stochastic and the avatar + * accordingly. + * + * @param sprite + * the new sprite to add. + * @param itype + * main int type of this sprite (leaf of the hierarchy of types). */ - protected void addSprite(VGDLSprite sprite, int itype) - { - sprite.spriteID = nextSpriteID; - spriteGroups[itype].addSprite(nextSpriteID++, sprite); - num_sprites++; + protected void addSprite(VGDLSprite sprite, int itype) { + sprite.spriteID = nextSpriteID; + spriteGroups[itype].addSprite(nextSpriteID++, sprite); + num_sprites++; - if(sprite.is_stochastic) - this.is_stochastic = true; + if (sprite.is_stochastic) + this.is_stochastic = true; - if(itype == wallId) - { - sprite.loadImage("wall.png"); - }else if(itype == avatarId) - { - sprite.loadImage("avatar.png"); - } + if (itype == wallId) { + sprite.loadImage("wall.png"); + } else if (itype == avatarId) { + sprite.loadImage("avatar.png"); + } } /** - * Returns the number of sprites of the type given by parameter, and all its subtypes - * @param itype parent itype requested. + * Returns the number of sprites of the type given by parameter, and all its + * subtypes + * + * @param itype + * parent itype requested. * @return the number of sprites of the type and subtypes. */ - public int getNumSprites(int itype) - { - int acum = 0; - for( Integer subtype : this.iSubTypes[itype] ) - { - acum += spriteGroups[subtype].numSprites(); - } - return acum; + public int getNumSprites(int itype) { + int acum = 0; + for (Integer subtype : this.iSubTypes[itype]) { + acum += spriteGroups[subtype].numSprites(); + } + return acum; } /** * Returns an arraylist of subtypes of the given parent type. - * @param itype parent itype requested. + * + * @param itype + * parent itype requested. */ public ArrayList getSubTypes(int itype) { - return this.iSubTypes[itype]; + return this.iSubTypes[itype]; } /** - * Returns the number of sprites disabled of the type given by parameter and all its subtypes - * @param itype parent itype requested. + * Returns the number of sprites disabled of the type given by parameter and + * all its subtypes + * + * @param itype + * parent itype requested. * @return the number of disabled sprites of the type and subtypes. */ public int getNumDisabledSprites(int itype) { - int acum = 0; - for( Integer subtype : this.iSubTypes[itype] ) - { - acum += spriteGroups[subtype].numDisabledSprites(); - } - return acum; + int acum = 0; + for (Integer subtype : this.iSubTypes[itype]) { + acum += spriteGroups[subtype].numDisabledSprites(); + } + return acum; } /** * Runs a game, without graphics. - * @param players Players that play this game. - * @param randomSeed sampleRandom seed for the whole game. + * + * @param players + * Players that play this game. + * @param randomSeed + * sampleRandom seed for the whole game. * @return the score of the game played. */ - public double[] runGame(Player[] players, int randomSeed) - { - //Prepare some structures and references for this game. - prepareGame(players, randomSeed, -1); + public double[] runGame(Player[] players, int randomSeed) { + // Prepare some structures and references for this game. + prepareGame(players, randomSeed, -1); - //Play until the game is ended - while(!isEnded) - { - this.gameCycle(); //Execute a game cycle. - } + // Play until the game is ended + while (!isEnded) { + this.gameCycle(); // Execute a game cycle. + } - //Update the forward model for the game state sent to the controller. - fwdModel.update(this); + // Update the forward model for the game state sent to the controller. + fwdModel.update(this); - return handleResult(); + return handleResult(); } - /** * Plays the game, graphics enabled. - * @param players Players that play this game. - * @param randomSeed sampleRandom seed for the whole game. - * @param isHuman indicates if a human is playing the game. - * @param humanID ID of the human player + * + * @param players + * Players that play this game. + * @param randomSeed + * sampleRandom seed for the whole game. + * @param isHuman + * indicates if a human is playing the game. + * @param humanID + * ID of the human player * @return the score of the game played. */ - public double[] playGame(Player[] players, int randomSeed, boolean isHuman, int humanID) - { - //Prepare some structures and references for this game. - prepareGame(players, randomSeed, humanID); - - //Create and initialize the panel for the graphics. - VGDLViewer view = new VGDLViewer(this, players[humanID]); - JEasyFrame frame; - frame = new JEasyFrame(view, "Java-VGDL"); - - frame.addKeyListener(ki); - frame.addWindowListener(wi); - wi.windowClosed = false; - - //Determine the delay for playing with a good fps. - double delay = CompetitionParameters.LONG_DELAY; - for (Player player : players) - if(player instanceof tracks.singlePlayer.tools.human.Agent) { - delay = 1000.0 / CompetitionParameters.DELAY; //in milliseconds - break; - } - - boolean firstRun = true; - - //Play until the game is ended - while(!isEnded && !wi.windowClosed) - { - //Determine the time to adjust framerate. - long then = System.currentTimeMillis(); - - this.gameCycle(); //Execute a game cycle. - - //Get the remaining time to keep fps. - long now = System.currentTimeMillis(); - int remaining = (int) Math.max(0, delay - (now-then)); - - //Wait until de next cycle. - waitStep(remaining); - - //Draw all sprites in the panel. - view.paint(this.spriteGroups); - - //Update the frame title to reflect current score and tick. - this.setTitle(frame); - - if(firstRun && isHuman){ - if(CompetitionParameters.dialogBoxOnStartAndEnd){ - JOptionPane.showMessageDialog(frame, - "Click OK to start."); - } - - firstRun = false; - } - } - - if(isHuman && !wi.windowClosed && CompetitionParameters.killWindowOnEnd){ - if(CompetitionParameters.dialogBoxOnStartAndEnd){ - if (no_players == 1) { - String sb = "GAMEOVER: YOU LOSE."; - if(avatars[humanID] != null){ - sb = "GAMEOVER: YOU " + ((avatars[humanID].getWinState() == Types.WINNER.PLAYER_WINS) ? "WIN." : "LOSE."); - } - JOptionPane.showMessageDialog(frame, sb); - } else { - String sb = ""; - for (int i = 0; i < no_players; i++) { - if (avatars[i] != null && avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) { - sb += "Player " + i + "; "; - } - } - if (sb.equals("")) sb = "NONE"; - JOptionPane.showMessageDialog(frame, - "GAMEOVER - WINNER: " + sb); - } - } - frame.dispose(); - } - - //Update the forward model for the game state sent to the controller. - fwdModel.update(this); - - return handleResult(); + public double[] playGame(Player[] players, int randomSeed, boolean isHuman, int humanID) { + // Prepare some structures and references for this game. + prepareGame(players, randomSeed, humanID); + + // Create and initialize the panel for the graphics. + VGDLViewer view = new VGDLViewer(this, players[humanID]); + JEasyFrame frame; + frame = new JEasyFrame(view, "Java-VGDL"); + + frame.addKeyListener(ki); + frame.addWindowListener(wi); + wi.windowClosed = false; + + // Determine the delay for playing with a good fps. + double delay = CompetitionParameters.LONG_DELAY; + for (Player player : players) + if (player instanceof tracks.singlePlayer.tools.human.Agent) { + delay = 1000.0 / CompetitionParameters.DELAY; // in milliseconds + break; + } + + boolean firstRun = true; + + // Play until the game is ended + while (!isEnded && !wi.windowClosed) { + // Determine the time to adjust framerate. + long then = System.currentTimeMillis(); + + this.gameCycle(); // Execute a game cycle. + + // Get the remaining time to keep fps. + long now = System.currentTimeMillis(); + int remaining = (int) Math.max(0, delay - (now - then)); + + // Wait until de next cycle. + waitStep(remaining); + + // Draw all sprites in the panel. + view.paint(this.spriteGroups); + + // Update the frame title to reflect current score and tick. + this.setTitle(frame); + + if (firstRun && isHuman) { + if (CompetitionParameters.dialogBoxOnStartAndEnd) { + JOptionPane.showMessageDialog(frame, "Click OK to start."); + } + + firstRun = false; + } + } + + if (isHuman && !wi.windowClosed && CompetitionParameters.killWindowOnEnd) { + if (CompetitionParameters.dialogBoxOnStartAndEnd) { + if (no_players == 1) { + String sb = "GAMEOVER: YOU LOSE."; + if (avatars[humanID] != null) { + sb = "GAMEOVER: YOU " + + ((avatars[humanID].getWinState() == Types.WINNER.PLAYER_WINS) ? "WIN." : "LOSE."); + } + JOptionPane.showMessageDialog(frame, sb); + } else { + String sb = ""; + for (int i = 0; i < no_players; i++) { + if (avatars[i] != null && avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) { + sb += "Player " + i + "; "; + } + } + if (sb.equals("")) + sb = "NONE"; + JOptionPane.showMessageDialog(frame, "GAMEOVER - WINNER: " + sb); + } + } + frame.dispose(); + } + + // Update the forward model for the game state sent to the controller. + fwdModel.update(this); + + return handleResult(); } /** * Sets the title of the game screen, depending on the game ending state. - * @param frame The frame whose title needs to be set. + * + * @param frame + * The frame whose title needs to be set. */ - private void setTitle (JEasyFrame frame) - { - String sb = ""; - sb += "Java-VGDL: "; - for (int i = 0; i < no_players; i++) { - if(avatars[i] != null){ - sb += "Player" + i + "-Score:" + avatars[i].getScore() + ". "; - } - } - sb += "Tick:" + this.getGameTick(); + private void setTitle(JEasyFrame frame) { + String sb = ""; + sb += "Java-VGDL: "; + for (int i = 0; i < no_players; i++) { + if (avatars[i] != null) { + sb += "Player" + i + "-Score:" + avatars[i].getScore() + ". "; + } + } + sb += "Tick:" + this.getGameTick(); -// sb += " --Counter:"; -// for (int i = 0; i < no_counters; i++) { -// sb += counter[i] + ", "; -// } + // sb += " --Counter:"; + // for (int i = 0; i < no_counters; i++) { + // sb += counter[i] + ", "; + // } - if(!isEnded) - frame.setTitle(sb); - else { - for (int i = 0; i < no_players; i++) { - if (avatars[i] != null && avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) - sb += " [Player " + i + " WINS!]"; - else - sb += " [Player " + i + " LOSES!]"; - } - } + if (!isEnded) + frame.setTitle(sb); + else { + for (int i = 0; i < no_players; i++) { + if (avatars[i] != null && avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) + sb += " [Player " + i + " WINS!]"; + else + sb += " [Player " + i + " LOSES!]"; + } + } - frame.setTitle(sb); + frame.setTitle(sb); } /** - * Initializes some variables for the game to be played, such as - * the game tick, sampleRandom number generator, forward model and assigns - * the player to the avatar. - * @param players Players that play this game. - * @param randomSeed sampleRandom seed for the whole game. + * Initializes some variables for the game to be played, such as the game + * tick, sampleRandom number generator, forward model and assigns the player + * to the avatar. + * + * @param players + * Players that play this game. + * @param randomSeed + * sampleRandom seed for the whole game. */ - private void prepareGame(Player[] players, int randomSeed, int humanID) - { - //Start tick counter. - gameTick = -1; + private void prepareGame(Player[] players, int randomSeed, int humanID) { + // Start tick counter. + gameTick = -1; - //Create the sampleRandom generator. - random = new Random(randomSeed); + // Create the sampleRandom generator. + random = new Random(randomSeed); - //Assigns the player to the avatar of the game. - createAvatars(humanID); - assignPlayer(players); + // Assigns the player to the avatar of the game. + createAvatars(humanID); + assignPlayer(players); - //Initialize state observation (sets all non-volatile references). - initForwardModel(); + // Initialize state observation (sets all non-volatile references). + initForwardModel(); } /** @@ -1015,141 +1025,142 @@ private void prepareGame(Player[] players, int randomSeed, int humanID) * updates the forward model and rolls an action in all entities, handling * collisions and end game situations. */ - private void gameCycle() - { - gameTick++; //next game tick. + private void gameCycle() { + gameTick++; // next game tick. - //Update our state observation (forward model) with the information of the current game state. - fwdModel.update(this); - //System.out.println(avatars[0].rect); + // Update our state observation (forward model) with the information of + // the current game state. + fwdModel.update(this); + // System.out.println(avatars[0].rect); - //Execute a game cycle: - this.tick(); //update for all entities. - this.eventHandling(); //handle events such collisions. - this.clearAll(fwdModel); //clear all additional data, including dead sprites. - this.terminationHandling(); //check for game termination. - this.checkTimeOut(); //Check for end of game by time steps. + // Execute a game cycle: + this.tick(); // update for all entities. + this.eventHandling(); // handle events such collisions. + this.clearAll(fwdModel); // clear all additional data, including dead + // sprites. + this.terminationHandling(); // check for game termination. + this.checkTimeOut(); // Check for end of game by time steps. - //if(gameTick == 0 || isEnded) - // fwdModel.printObservationGrid(); //uncomment this to show the observation grid. + // if(gameTick == 0 || isEnded) + // fwdModel.printObservationGrid(); //uncomment this to show the + // observation grid. } /** - * Handles the result for the game, considering disqualifications. Prints the result - * (score, time and winner) and returns the score of the game. + * Handles the result for the game, considering disqualifications. Prints + * the result (score, time and winner) and returns the score of the game. * Default player ID used 0 for single player games. + * * @return the result of the game. */ - public double[] handleResult() - { - // check all players disqualified and set scores - for (int i=0; i < avatars.length; i++) { - if(avatars[i] != null){ - if (avatars[i].is_disqualified()) { - avatars[i].setWinState(Types.WINNER.PLAYER_DISQ); - avatars[i].setScore(Types.SCORE_DISQ); - } - //For sanity: winning a game always gives a positive score - else if(avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) - if(avatars[i].getScore() <= 0) avatars[i].setScore(1); - } - } - - //Prints the result: score, time and winner. - //printResult(); - - double[] scores = new double[no_players]; - for (int i = 0; i < no_players; i++) { - if(avatars[i] == null){ - scores[i] = Types.SCORE_DISQ; - } - else{ - scores[i] = avatars[i].getScore(); - } - } - - return scores; - } - - /** - * Checks if the game must finish because of number of cycles played. This is - * a value stored in CompetitionParameters.MAX_TIMESTEPS. If the game is due to - * end, the winner is determined and the flag isEnded is set to true. - */ - protected void checkTimeOut() - { - if(gameTick >= CompetitionParameters.MAX_TIMESTEPS) - { - isEnded = true; - for (int i = 0; i < no_players; i++) { - if (avatars[i].getWinState() != Types.WINNER.PLAYER_WINS) - avatars[i].setWinState(Types.WINNER.PLAYER_LOSES); - } - } + public double[] handleResult() { + // check all players disqualified and set scores + for (int i = 0; i < avatars.length; i++) { + if (avatars[i] != null) { + if (avatars[i].is_disqualified()) { + avatars[i].setWinState(Types.WINNER.PLAYER_DISQ); + avatars[i].setScore(Types.SCORE_DISQ); + } + // For sanity: winning a game always gives a positive score + else if (avatars[i].getWinState() == Types.WINNER.PLAYER_WINS) + if (avatars[i].getScore() <= 0) + avatars[i].setScore(1); + } + } + + // Prints the result: score, time and winner. + // printResult(); + + double[] scores = new double[no_players]; + for (int i = 0; i < no_players; i++) { + if (avatars[i] == null) { + scores[i] = Types.SCORE_DISQ; + } else { + scores[i] = avatars[i].getScore(); + } + } + + return scores; + } + + /** + * Checks if the game must finish because of number of cycles played. This + * is a value stored in CompetitionParameters.MAX_TIMESTEPS. If the game is + * due to end, the winner is determined and the flag isEnded is set to true. + */ + protected void checkTimeOut() { + if (gameTick >= CompetitionParameters.MAX_TIMESTEPS) { + isEnded = true; + for (int i = 0; i < no_players; i++) { + if (avatars[i].getWinState() != Types.WINNER.PLAYER_WINS) + avatars[i].setWinState(Types.WINNER.PLAYER_LOSES); + } + } } /** * Prints the result of the game, indicating the winner, the score and the * number of game ticks played, in this order. */ - public void printResult() - { - String sb1 = ""; - String sb2 = ""; - for (int i = 0; i < no_players; i++) { - if(avatars[i] != null){ - sb1 += "Player" + i + ":" + avatars[i].getWinState().key() + ", "; - sb2 += "Player" + i + "-Score:" + avatars[i].getScore() + ", "; - } - else{ - sb1 += "Player" + i + ":-100, "; - sb2 += "Player" + i + "-Score:" + Types.SCORE_DISQ + ", "; - } - } + public void printResult() { + String sb1 = ""; + String sb2 = ""; + for (int i = 0; i < no_players; i++) { + if (avatars[i] != null) { + sb1 += "Player" + i + ":" + avatars[i].getWinState().key() + ", "; + sb2 += "Player" + i + "-Score:" + avatars[i].getScore() + ", "; + } else { + sb1 += "Player" + i + ":-100, "; + sb2 += "Player" + i + "-Score:" + Types.SCORE_DISQ + ", "; + } + } - System.out.println("Result (1->win; 0->lose): " + sb1 + sb2 + "timesteps:" + this.getGameTick()); - //System.out.println("Result (1->win; 0->lose):"+ winner.key() + ", Score:" + score + ", timesteps:" + this.getGameTick()); + System.out.println("Result (1->win; 0->lose): " + sb1 + sb2 + "timesteps:" + this.getGameTick()); + // System.out.println("Result (1->win; 0->lose):"+ winner.key() + ", + // Score:" + score + ", timesteps:" + this.getGameTick()); } /** * Returns the complete result of the game (victory, score, timestep). * Indicated in triplets, one per player. + * * @return [w0,s0,t0,w1,s1,t1,...] */ - public double[] getFullResult() - { - int result_dims = 3; - double[] allRes = new double[no_players * result_dims]; - for (int i = 0; i < no_players; i++) { + public double[] getFullResult() { + int result_dims = 3; + double[] allRes = new double[no_players * result_dims]; + for (int i = 0; i < no_players; i++) { - allRes[i*result_dims] = avatars[i].getWinState().key(); - allRes[i*result_dims + 1] = avatars[i].getScore(); - allRes[i*result_dims + 2] = this.getGameTick(); - } - return allRes; + allRes[i * result_dims] = avatars[i].getWinState().key(); + allRes[i * result_dims + 1] = avatars[i].getScore(); + allRes[i * result_dims + 2] = this.getGameTick(); + } + return allRes; } /** - * Disqualifies the player in the game, and also sets the isEnded flag to true. + * Disqualifies the player in the game, and also sets the isEnded flag to + * true. */ - //comment this method out to check if mistakes in method overloading anywhere - public void disqualify() - { - disqualified = true; - isEnded = true; + // comment this method out to check if mistakes in method overloading + // anywhere + public void disqualify() { + disqualified = true; + isEnded = true; } /** * Overloaded method for multiplayer games. Same functionality as above. - * @param id - id of the player that was disqualified + * + * @param id + * - id of the player that was disqualified */ - public void disqualify(int id) - { - if (id == -1) - disqualified = true; - else - avatars[id].disqualify(true); - isEnded = true; + public void disqualify(int id) { + if (id == -1) + disqualified = true; + else + avatars[id].disqualify(true); + isEnded = true; } /** @@ -1157,951 +1168,1016 @@ public void disqualify(int id) */ public void createAvatars(int humanID) { - //Avatars will usually be the first elements, starting from the end. - - //Find avatar sprites - ArrayList avSprites = new ArrayList<>(); - int idx = spriteOrder.length; - int numAvatarSprites = 0; - while (true) { - idx--; - if (idx > 0) { - int spriteTypeId = spriteOrder[idx]; - int num = spriteGroups[spriteTypeId].numSprites(); - if (num > 0) { - //There should be just one sprite in the avatar's group in single player games. - //Could be more than one avatar in multiplayer games - for (int j = 0; j < num; j++) { - VGDLSprite thisSprite = spriteGroups[spriteTypeId].getSpriteByIdx(j); - if (thisSprite.is_avatar) { - avSprites.add((MovingAvatar) thisSprite); - } - } - } - } else { - numAvatarSprites = avSprites.size(); - //System.out.println("Done finding avatars: " + numAvatarSprites); - break; - } - } - - Collections.reverse(avSprites); //read in reverse order - if (!avSprites.isEmpty()) { - for (int i = 0; i < no_players; i++) { - if (numAvatarSprites > i) { //check if there's enough avatars just in case - avatars[i] = avSprites.get(i); - avatars[i].setKeyHandler(ki); - avatars[i].setPlayerID(i); - } - } - } else { - Logger.getInstance().addMessage(new Message(Message.WARNING, "No avatars found.")); - } + // Avatars will usually be the first elements, starting from the end. + + // Find avatar sprites + ArrayList avSprites = new ArrayList<>(); + int idx = spriteOrder.length; + int numAvatarSprites = 0; + while (true) { + idx--; + if (idx > 0) { + int spriteTypeId = spriteOrder[idx]; + int num = spriteGroups[spriteTypeId].numSprites(); + if (num > 0) { + // There should be just one sprite in the avatar's group in + // single player games. + // Could be more than one avatar in multiplayer games + for (int j = 0; j < num; j++) { + VGDLSprite thisSprite = spriteGroups[spriteTypeId].getSpriteByIdx(j); + if (thisSprite.is_avatar) { + avSprites.add((MovingAvatar) thisSprite); + } + } + } + } else { + numAvatarSprites = avSprites.size(); + // System.out.println("Done finding avatars: " + + // numAvatarSprites); + break; + } + } + + Collections.reverse(avSprites); // read in reverse order + if (!avSprites.isEmpty()) { + for (int i = 0; i < no_players; i++) { + if (numAvatarSprites > i) { // check if there's enough avatars + // just in case + avatars[i] = avSprites.get(i); + avatars[i].setKeyHandler(ki); + avatars[i].setPlayerID(i); + } + } + } else { + Logger.getInstance().addMessage(new Message(Message.WARNING, "No avatars found.")); + } } + /** * Looks for the avatar of the game in the existing sprites. If the player * received as a parameter is not null, it is assigned to it. - * @param players the players that will play the game (only 1 in single player games). - */ - private void assignPlayer(Player[] players) - { - //iterate through all avatars and assign their players - if (players.length == no_players) { - for (int i = 0; i < no_players; i++) { - if (players[i] != null && avatars[i] != null) { - avatars[i].player = players[i]; - avatars[i].setPlayerID(i); - //avatars[i].player.setPlayerID(i); - } else { - System.out.println("Null player."); - } - } - } else { - System.out.println("Not enough players."); - } + * + * @param players + * the players that will play the game (only 1 in single player + * games). + */ + private void assignPlayer(Player[] players) { + // iterate through all avatars and assign their players + if (players.length == no_players) { + for (int i = 0; i < no_players; i++) { + if (players[i] != null && avatars[i] != null) { + avatars[i].player = players[i]; + avatars[i].setPlayerID(i); + // avatars[i].player.setPlayerID(i); + } else { + System.out.println("Null player."); + } + } + } else { + System.out.println("Not enough players."); + } } /** * Holds the game for the specified duration milliseconds - * @param duration time to wait. + * + * @param duration + * time to wait. */ void waitStep(int duration) { - try - { - Thread.sleep(duration); - } - catch(InterruptedException e) - { - e.printStackTrace(); - } - } - - /** - * Performs one tick for the game: calling update(this) in all sprites. It follows the - * opposite order of the drawing order (inverse spriteOrder[]). Avatar is always - * updated first. - * Doesn't update disabled sprites. - */ - protected void tick() - { - //Now, do all of the avatars. - for (int i = 0; i < no_players; i++) { - if (avatars[i] != null && !avatars[i].is_disabled()) { - avatars[i].preMovement(); - avatars[i].update(this); - } else if (avatars[i] == null) { - System.out.println(gameTick + ": Something went wrong, no avatar, ID = " + i); - } - } - //random = new Random(this.gameTick * 100); //uncomment this for testing a new rnd generator after avatar's move - - int spriteOrderCount = spriteOrder.length; - for(int i = spriteOrderCount-1; i >= 0 ; --i) - { - int spriteTypeInt = spriteOrder[i]; - ArrayList spritesList = spriteGroups[spriteTypeInt].getSprites(); - if(spritesList != null) for(VGDLSprite sp : spritesList) - { - if(!(sp instanceof MovingAvatar) && !sp.is_disabled()) - { - sp.preMovement(); - sp.update(this); - } - } - - } + try { + Thread.sleep(duration); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Performs one tick for the game: calling update(this) in all sprites. It + * follows the opposite order of the drawing order (inverse spriteOrder[]). + * Avatar is always updated first. Doesn't update disabled sprites. + */ + protected void tick() { + // Now, do all of the avatars. + for (int i = 0; i < no_players; i++) { + if (avatars[i] != null && !avatars[i].is_disabled()) { + avatars[i].preMovement(); + avatars[i].update(this); + } else if (avatars[i] == null) { + System.out.println(gameTick + ": Something went wrong, no avatar, ID = " + i); + } + } + // random = new Random(this.gameTick * 100); //uncomment this for + // testing a new rnd generator after avatar's move + + int spriteOrderCount = spriteOrder.length; + for (int i = spriteOrderCount - 1; i >= 0; --i) { + int spriteTypeInt = spriteOrder[i]; + ArrayList spritesList = spriteGroups[spriteTypeInt].getSprites(); + if (spritesList != null) + for (VGDLSprite sp : spritesList) { + if (!(sp instanceof MovingAvatar) && !sp.is_disabled()) { + sp.preMovement(); + sp.update(this); + } + } + + } } /** * Handles collisions and triggers events. */ - protected void eventHandling() - { - //Array to indicate that the sprite type has no representative in collisions. - boolean noSprites[] = new boolean[spriteGroups.length]; - - //First, check the effects that are triggered in a timely manner. - while (timeEffects.size() > 0 && timeEffects.first().nextExecution <= gameTick) - { - TimeEffect ef = timeEffects.pollFirst(); - if(ef.enabled) { - int intId = ef.itype; - boolean exec = false; - - //if intId==-1, we have no sprite - if (intId == -1) { - //With no sprite, the effect is independent from particular sprites. - ef.execute(null, null, this); - exec = true; - - //Affect score for all players: - if (ef.applyScore) { - for (int i = 0; i < no_players; i++) { - avatars[i].addScore(ef.getScoreChange(i)); - } - } - - } else { - - ArrayList allTypes = iSubTypes[intId]; - for (Integer itype : allTypes) { - //Find all sprites of this subtype. - Collection sprites = this.getSprites(itype); - for (VGDLSprite sp : sprites) { - //Check that they are not dead (could happen in this same cycle). - if (!kill_list.contains(sp) && !sp.is_disabled()) { - executeEffect(ef, sp, null); - exec = true; - } - } - } - } - - //If the time effect is repetitive, need to reinsert in the list of effects - if(ef.repeating) - { - if(!exec) ef.planExecution(this); - this.addTimeEffect(ef); - } - } - - - } - - - //Secondly, we handle single sprite events (EOS). Take each sprite itype that has - //a EOS effect defined. - for(Integer intId : definedEOSEffects) - { - //For each effect that this sprite has assigned. - for(Effect ef : eosEffects[intId]) - { - //Take all the subtypes in the hierarchy of this sprite. - ArrayList allTypes = iSubTypes[intId]; - if(ef.enabled) for(Integer itype : allTypes) - { - //Add all sprites of this subtype to the list of sprites. - //These are sprites that could potentially collide with EOS - Collection sprites = this.getSprites(itype); - for(VGDLSprite sp : sprites) - { - //Check if they are at the edge to trigger the effect. Also check that they - //are not dead (could happen in this same cycle). - if(isAtEdge(sp.rect) && !kill_list.contains(sp) && !sp.is_disabled()) { - executeEffect(ef, sp, null); - } - } - } - } - - } - - - - // Now, we handle events between pairs of sprites, for each pair of sprites that - // has a paired effect defined: - for(Pair p : definedEffects) - { - // We iterate over the (potential) multiple effects that these - // two sprites could have defined between them. - for(Effect ef : collisionEffects[p.first][p.second]) - { - if(ef.enabled) { - - if (shieldedEffects[p.first].size() > 0) { - if (shieldedEffects[p.first].contains(new Pair(p.second, ef.hashCode))) - continue; - } - - ArrayList firstx = new ArrayList(); - ArrayList secondx = new ArrayList(); - - ArrayList allTypes1 = iSubTypes[p.first]; - for (int i : allTypes1) { - firstx.addAll(getSprites(i)); - } - ArrayList allTypes2 = iSubTypes[p.second]; - for (int j : allTypes2) { - secondx.addAll(getSprites(j)); - } - - - ArrayList new_secondx = new ArrayList(); - - for (VGDLSprite s1 : firstx) { - new_secondx = new ArrayList(); - - for (VGDLSprite s2 : secondx) { - if ((s1 != s2 && s1.rect.intersects(s2.rect))) { - new_secondx.add(s2); - } - } - - for (int a = 0; a < new_secondx.size(); a++) { - for (int b = 0; b < new_secondx.size(); b++) { - if (a < b) { - if (Math.sqrt( - ((s1.getPosition().x - new_secondx.get(a).getPosition().x) * - (s1.getPosition().x - new_secondx.get(a).getPosition().x)) + - - ((s1.getPosition().y - new_secondx.get(a).getPosition().y) * - (s1.getPosition().y - new_secondx.get(a).getPosition().y))) > - Math.sqrt( - ((s1.getPosition().x - new_secondx.get(b).getPosition().x) * - (s1.getPosition().x - new_secondx.get(b).getPosition().x)) + - - ((s1.getPosition().y - new_secondx.get(b).getPosition().y) * - (s1.getPosition().y - new_secondx.get(b).getPosition().y)))) { - new_secondx.add(a, new_secondx.get(b)); - new_secondx.remove(b + 1); - } - } - } - } - - for (int i = 0; i < new_secondx.size(); i++) { - if (!kill_list.contains(s1) && s1 != new_secondx.get(i) && s1.rect.intersects(new_secondx.get(i).rect)) { - executeEffect(ef, s1, new_secondx.get(i)); - } - } - } - } - } - } - - } - - private void executeEffect(Effect ef, VGDLSprite s1, VGDLSprite s2) - { - //There is a collision. Apply the effect. - ef.execute(s1,s2,this); - - //Affect score: - if(ef.applyScore) { - //apply scores for all avatars - for (int i = 0; i < no_players; i++) { - avatars[i].addScore(ef.getScoreChange(i)); - } - } - - //Add to events history. - if(s1 != null && s2 != null) - addEvent(s1, s2); - - if(ef.count) { - for (int i = 0; i < no_counters; i++) { - this.counter[i] += ef.getCounter(i); - } - } - - if(ef.countElse) { - for (int i = 0; i < no_counters; i++) { - this.counter[i] += ef.getCounterElse(i); - } - } - } - - private void addEvent(VGDLSprite s1, VGDLSprite s2) - { - if(s1.is_avatar) - historicEvents.add(new Event(gameTick, false, s1.getType(), s2.getType(), - s1.spriteID, s2.spriteID, s1.getPosition())); - - else if(s1.is_from_avatar) - historicEvents.add(new Event(gameTick, true, s1.getType(), s2.getType(), - s1.spriteID, s2.spriteID, s1.getPosition())); - - else if(s2.is_avatar) - historicEvents.add(new Event(gameTick, false, s2.getType(), s1.getType(), - s2.spriteID, s1.spriteID, s2.getPosition())); - - else if(s2.is_from_avatar) - historicEvents.add(new Event(gameTick, true, s2.getType(), s1.getType(), - s2.spriteID, s1.spriteID, s2.getPosition())); + protected void eventHandling() { + // Array to indicate that the sprite type has no representative in + // collisions. + boolean noSprites[] = new boolean[spriteGroups.length]; + + // First, check the effects that are triggered in a timely manner. + while (timeEffects.size() > 0 && timeEffects.first().nextExecution <= gameTick) { + TimeEffect ef = timeEffects.pollFirst(); + if (ef.enabled) { + int intId = ef.itype; + boolean exec = false; + + // if intId==-1, we have no sprite + if (intId == -1) { + // With no sprite, the effect is independent from particular + // sprites. + ef.execute(null, null, this); + exec = true; + + // Affect score for all players: + if (ef.applyScore) { + for (int i = 0; i < no_players; i++) { + avatars[i].addScore(ef.getScoreChange(i)); + } + } + + } else { + + ArrayList allTypes = iSubTypes[intId]; + for (Integer itype : allTypes) { + // Find all sprites of this subtype. + Collection sprites = this.getSprites(itype); + for (VGDLSprite sp : sprites) { + // Check that they are not dead (could happen in + // this same cycle). + if (!kill_list.contains(sp) && !sp.is_disabled()) { + executeEffect(ef, sp, null); + exec = true; + } + } + } + } + + // If the time effect is repetitive, need to reinsert in the + // list of effects + if (ef.repeating) { + if (!exec) + ef.planExecution(this); + this.addTimeEffect(ef); + } + } + + } + + // Secondly, we handle single sprite events (EOS). Take each sprite + // itype that has + // a EOS effect defined. + for (Integer intId : definedEOSEffects) { + // For each effect that this sprite has assigned. + for (Effect ef : eosEffects[intId]) { + // Take all the subtypes in the hierarchy of this sprite. + ArrayList allTypes = iSubTypes[intId]; + if (ef.enabled) + for (Integer itype : allTypes) { + // Add all sprites of this subtype to the list of + // sprites. + // These are sprites that could potentially collide with + // EOS + Collection sprites = this.getSprites(itype); + for (VGDLSprite sp : sprites) { + // Check if they are at the edge to trigger the + // effect. Also check that they + // are not dead (could happen in this same cycle). + if (isAtEdge(sp.rect) && !kill_list.contains(sp) && !sp.is_disabled()) { + executeEffect(ef, sp, null); + } + } + } + } + + } + + // Now, we handle events between pairs of sprites, for each pair of + // sprites that + // has a paired effect defined: + for (Pair p : definedEffects) { + // We iterate over the (potential) multiple effects that these + // two sprites could have defined between them. + for (Effect ef : collisionEffects[p.first][p.second]) { + if (ef.enabled) { + + if (shieldedEffects[p.first].size() > 0) { + if (shieldedEffects[p.first].contains(new Pair(p.second, ef.hashCode))) + continue; + } + + ArrayList firstx = new ArrayList(); + ArrayList secondx = new ArrayList(); + + ArrayList allTypes1 = iSubTypes[p.first]; + for (int i : allTypes1) { + firstx.addAll(getSprites(i)); + } + ArrayList allTypes2 = iSubTypes[p.second]; + for (int j : allTypes2) { + secondx.addAll(getSprites(j)); + } + + ArrayList new_secondx = new ArrayList(); + + for (VGDLSprite s1 : firstx) { + new_secondx = new ArrayList(); + + for (VGDLSprite s2 : secondx) { + if ((s1 != s2 && s1.rect.intersects(s2.rect))) { + new_secondx.add(s2); + } + } + + for (int a = 0; a < new_secondx.size(); a++) { + for (int b = 0; b < new_secondx.size(); b++) { + if (a < b) { + if (Math.sqrt(((s1.getPosition().x - new_secondx.get(a).getPosition().x) + * (s1.getPosition().x - new_secondx.get(a).getPosition().x)) + + + ((s1.getPosition().y - new_secondx.get(a).getPosition().y) + * (s1.getPosition().y - new_secondx.get(a).getPosition().y))) > Math + .sqrt(((s1.getPosition().x + - new_secondx.get(b).getPosition().x) + * (s1.getPosition().x + - new_secondx.get(b).getPosition().x)) + + + + ((s1.getPosition().y + - new_secondx.get(b).getPosition().y) + * (s1.getPosition().y - new_secondx.get(b) + .getPosition().y)))) { + new_secondx.add(a, new_secondx.get(b)); + new_secondx.remove(b + 1); + } + } + } + } + + for (int i = 0; i < new_secondx.size(); i++) { + if (!kill_list.contains(s1) && s1 != new_secondx.get(i) + && s1.rect.intersects(new_secondx.get(i).rect)) { + executeEffect(ef, s1, new_secondx.get(i)); + } + } + } + } + } + } + + } + + private void executeEffect(Effect ef, VGDLSprite s1, VGDLSprite s2) { + // There is a collision. Apply the effect. + ef.execute(s1, s2, this); + + // Affect score: + if (ef.applyScore) { + // apply scores for all avatars + for (int i = 0; i < no_players; i++) { + avatars[i].addScore(ef.getScoreChange(i)); + } + } + + // Add to events history. + if (s1 != null && s2 != null) + addEvent(s1, s2); + + if (ef.count) { + for (int i = 0; i < no_counters; i++) { + this.counter[i] += ef.getCounter(i); + } + } + + if (ef.countElse) { + for (int i = 0; i < no_counters; i++) { + this.counter[i] += ef.getCounterElse(i); + } + } + } + + private void addEvent(VGDLSprite s1, VGDLSprite s2) { + if (s1.is_avatar) + historicEvents.add( + new Event(gameTick, false, s1.getType(), s2.getType(), s1.spriteID, s2.spriteID, s1.getPosition())); + + else if (s1.is_from_avatar) + historicEvents.add( + new Event(gameTick, true, s1.getType(), s2.getType(), s1.spriteID, s2.spriteID, s1.getPosition())); + + else if (s2.is_avatar) + historicEvents.add( + new Event(gameTick, false, s2.getType(), s1.getType(), s2.spriteID, s1.spriteID, s2.getPosition())); + + else if (s2.is_from_avatar) + historicEvents.add( + new Event(gameTick, true, s2.getType(), s1.getType(), s2.spriteID, s1.spriteID, s2.getPosition())); } /** * Checks if a given rectangle is at the edge of the screen. - * @param rect the rectangle to check + * + * @param rect + * the rectangle to check * @return true if rect is at the edge of the screen. */ - private boolean isAtEdge(Rectangle rect) - { - Rectangle r = new Rectangle(screenSize); - if(!r.contains(rect)) - { - return true; - } - return false; + private boolean isAtEdge(Rectangle rect) { + Rectangle r = new Rectangle(screenSize); + if (!r.contains(rect)) { + return true; + } + return false; } /** - * Handles termination conditions, for every termination defined in 'terminations' array. + * Handles termination conditions, for every termination defined in + * 'terminations' array. */ - protected void terminationHandling() - { - int numTerminations = terminations.size(); - for(int i = 0; !isEnded && i < numTerminations; ++i) - { - Termination t = terminations.get(i); - if(t.isDone(this)) - { - isEnded = true; - for (int j = 0; j < no_players; j++) { - if(avatars[j] != null){ - avatars[j].setWinState(t.win(j) ? Types.WINNER.PLAYER_WINS : Types.WINNER.PLAYER_LOSES); - } - } - } - } + protected void terminationHandling() { + int numTerminations = terminations.size(); + for (int i = 0; !isEnded && i < numTerminations; ++i) { + Termination t = terminations.get(i); + if (t.isDone(this)) { + isEnded = true; + for (int j = 0; j < no_players; j++) { + if (avatars[j] != null) { + avatars[j].setWinState(t.win(j) ? Types.WINNER.PLAYER_WINS : Types.WINNER.PLAYER_LOSES); + } + } + } + } } /** - * Deletes all the sprites killed in the previous step. Also, clears the array of collisions - * from the last step. - * @param fm Forward model where we are cleaning sprites. + * Deletes all the sprites killed in the previous step. Also, clears the + * array of collisions from the last step. + * + * @param fm + * Forward model where we are cleaning sprites. */ - protected void clearAll(ForwardModel fm) - { - for(VGDLSprite sprite : kill_list) - { - int spriteType = sprite.getType(); - this.spriteGroups[spriteType].removeSprite(sprite); - if(fm != null) { - fm.removeSpriteObservation(sprite); - } - + protected void clearAll(ForwardModel fm) { + for (VGDLSprite sprite : kill_list) { + int spriteType = sprite.getType(); + this.spriteGroups[spriteType].removeSprite(sprite); + if (fm != null) { + fm.removeSpriteObservation(sprite); + } - if(sprite.is_avatar) - //go through all avatars to see which avatar is dead - for (int i = 0; i < no_players; i++) - if (sprite == avatars[i]) - avatars[i] = null; + if (sprite.is_avatar) + // go through all avatars to see which avatar is dead + for (int i = 0; i < no_players; i++) + if (sprite == avatars[i]) + avatars[i] = null; - num_sprites--; + num_sprites--; - } - kill_list.clear(); + } + kill_list.clear(); - for(int j = 0; j < spriteGroups.length; ++j) - { - bucketList[j].clear(); - } + for (int j = 0; j < spriteGroups.length; ++j) { + bucketList[j].clear(); + } - resetShieldEffects(); + resetShieldEffects(); } /** * Cleans the array of shielded effects. */ - private void resetShieldEffects() - { - for(int i =0; i < shieldedEffects.length; ++i) - shieldedEffects[i].clear(); + private void resetShieldEffects() { + for (int i = 0; i < shieldedEffects.length; ++i) + shieldedEffects[i].clear(); } /** * Adds a new Shield effect to the scene. - * @param type1 Recipient of the effect (sprite ID) - * @param type2 Second sprite ID - * @param functHash Hash of the effect name to shield. + * + * @param type1 + * Recipient of the effect (sprite ID) + * @param type2 + * Second sprite ID + * @param functHash + * Hash of the effect name to shield. */ - public void addShield(int type1, int type2, long functHash) - { - Pair newShield = new Pair(type2, functHash); - shieldedEffects[type1].add(newShield); + public void addShield(int type1, int type2, long functHash) { + Pair newShield = new Pair(type2, functHash); + shieldedEffects[type1].add(newShield); } /** * Adds a sprite given a content and position. - * @param itype integer that identifies the definition of the sprite to add - * @param position where the sprite has to be placed. + * + * @param itype + * integer that identifies the definition of the sprite to add + * @param position + * where the sprite has to be placed. */ - public VGDLSprite addSprite(int itype, Vector2d position) - { - return this.addSprite((SpriteContent) classConst[itype], position, itype, false); + public VGDLSprite addSprite(int itype, Vector2d position) { + return this.addSprite((SpriteContent) classConst[itype], position, itype, false); } /** * Adds a sprite given a content and position. - * @param itype integer that identifies the definition of the sprite to add - * @param position where the sprite has to be placed. - * @param force if true, ignores the singleton restrictions and creates it anyway. - */ - public VGDLSprite addSprite(int itype, Vector2d position, boolean force) - { - return this.addSprite((SpriteContent) classConst[itype], position, itype, force); - } - - /** - * Adds a sprite given a content and position. It checks for possible singletons. - * @param content definition of the sprite to add - * @param position where the sprite has to be placed. - * @param itype integer identifier of this type of sprite. - * @param force If true, forces the creation ignoring singleton restrictions - */ - public VGDLSprite addSprite(SpriteContent content, Vector2d position, int itype, boolean force) - { - if(num_sprites > MAX_SPRITES) - { - Logger.getInstance().addMessage(new Message(Message.WARNING, "Sprite limit reached.")); - return null; - } - - //Check for singleton Sprites - boolean anyother = false; - if(!force) { - - for (Integer typeInt : content.itypes) { - //If this type is a singleton and we have one already - if (singletons[typeInt] && getNumSprites(typeInt) > 0) { - //that's it, no more creations of this type. - anyother = true; - break; - } - } - } - - //Only create the sprite if there is not any other sprite that blocks it. - if(!anyother) - { - VGDLSprite newSprite; - - if(templateSprites[itype] == null) // don't have a template yet, so need to create one - { - newSprite = VGDLFactory.GetInstance().createSprite( - this, content , position, new Dimension(block_size, block_size)); - - //Assign its types and add it to the collection of sprites. - newSprite.itypes = (ArrayList) content.itypes.clone(); - - // save a copy as template object - templateSprites[itype] = newSprite.copy(); - } - else // we already have a template, so simply copy that one - { - newSprite = templateSprites[itype].copy(); - - // make sure the copy is moved to the correct position - newSprite.setRect(position, new Dimension(block_size, block_size)); - - //Set last rect - newSprite.lastrect = new Rectangle(newSprite.rect); - } - - // add the sprite to the collection of sprites in the game - this.addSprite(newSprite, itype); - return newSprite; - } - - Logger.getInstance().addMessage(new Message(Message.WARNING, "You can't have multiple objects of singleton.")); - return null; - } - - - public void _updateCollisionDict(VGDLSprite sprite) {} + * + * @param itype + * integer that identifies the definition of the sprite to add + * @param position + * where the sprite has to be placed. + * @param force + * if true, ignores the singleton restrictions and creates it + * anyway. + */ + public VGDLSprite addSprite(int itype, Vector2d position, boolean force) { + return this.addSprite((SpriteContent) classConst[itype], position, itype, force); + } + + /** + * Adds a sprite given a content and position. It checks for possible + * singletons. + * + * @param content + * definition of the sprite to add + * @param position + * where the sprite has to be placed. + * @param itype + * integer identifier of this type of sprite. + * @param force + * If true, forces the creation ignoring singleton restrictions + */ + public VGDLSprite addSprite(SpriteContent content, Vector2d position, int itype, boolean force) { + if (num_sprites > MAX_SPRITES) { + Logger.getInstance().addMessage(new Message(Message.WARNING, "Sprite limit reached.")); + return null; + } + + // Check for singleton Sprites + boolean anyother = false; + if (!force) { + + for (Integer typeInt : content.itypes) { + // If this type is a singleton and we have one already + if (singletons[typeInt] && getNumSprites(typeInt) > 0) { + // that's it, no more creations of this type. + anyother = true; + break; + } + } + } + + // Only create the sprite if there is not any other sprite that blocks + // it. + if (!anyother) { + VGDLSprite newSprite; + + if (templateSprites[itype] == null) // don't have a template yet, so + // need to create one + { + newSprite = VGDLFactory.GetInstance().createSprite(this, content, position, + new Dimension(block_size, block_size)); + + // Assign its types and add it to the collection of sprites. + newSprite.itypes = (ArrayList) content.itypes.clone(); + + // save a copy as template object + templateSprites[itype] = newSprite.copy(); + } else // we already have a template, so simply copy that one + { + newSprite = templateSprites[itype].copy(); + + // make sure the copy is moved to the correct position + newSprite.setRect(position, new Dimension(block_size, block_size)); + + // Set last rect + newSprite.lastrect = new Rectangle(newSprite.rect); + } + + // add the sprite to the collection of sprites in the game + this.addSprite(newSprite, itype); + return newSprite; + } + + Logger.getInstance().addMessage(new Message(Message.WARNING, "You can't have multiple objects of singleton.")); + return null; + } + + public void _updateCollisionDict(VGDLSprite sprite) { + } /** * Returns the game score. */ - public double getScore() { return getScore(0); } - + public double getScore() { + return getScore(0); + } /** - * Method overloaded for multi player games. - * Returns the game score of the specified player. - * @param playerID ID of the player. + * Method overloaded for multi player games. Returns the game score of the + * specified player. + * + * @param playerID + * ID of the player. */ - public double getScore(int playerID) - { - return avatars[playerID].getScore(); + public double getScore(int playerID) { + return avatars[playerID].getScore(); } /** * Reverses the direction of a given sprite. - * @param sprite sprite to reverse. + * + * @param sprite + * sprite to reverse. */ - public void reverseDirection(VGDLSprite sprite) - { - sprite.orientation = new Direction(-sprite.orientation.x(), -sprite.orientation.y()); + public void reverseDirection(VGDLSprite sprite) { + sprite.orientation = new Direction(-sprite.orientation.x(), -sprite.orientation.y()); } /** - * Kills a given sprite, adding it to the list of sprites killed at this step. - * @param sprite the sprite to kill. - * @param transformed - indicates if the sprite was transformed (necessary to kill - * sprite even if avatar, instead of disabling it). + * Kills a given sprite, adding it to the list of sprites killed at this + * step. + * + * @param sprite + * the sprite to kill. + * @param transformed + * - indicates if the sprite was transformed (necessary to kill + * sprite even if avatar, instead of disabling it). */ - public void killSprite(VGDLSprite sprite, boolean transformed) - { - if (sprite instanceof MovingAvatar && !transformed) { //if avatar, just disable - sprite.setDisabled(true); - } else { - kill_list.add(sprite); - } + public void killSprite(VGDLSprite sprite, boolean transformed) { + if (sprite instanceof MovingAvatar && !transformed) { // if avatar, just + // disable + sprite.setDisabled(true); + } else { + kill_list.add(sprite); + } } /** - * Gets an iterator for the collection of sprites for a particular sprite type. - * @param spriteItype type of the sprite to retrieve. + * Gets an iterator for the collection of sprites for a particular sprite + * type. + * + * @param spriteItype + * type of the sprite to retrieve. * @return sprite collection of the specified type. */ - public Iterator getSpriteGroup(int spriteItype) - { - return spriteGroups[spriteItype].getSpriteIterator(); + public Iterator getSpriteGroup(int spriteItype) { + return spriteGroups[spriteItype].getSpriteIterator(); } /** - * Gets an iterator for the collection of sprites for a particular sprite type, AND all subtypes. - * @param spriteItype type of the sprite to retrieve. + * Gets an iterator for the collection of sprites for a particular sprite + * type, AND all subtypes. + * + * @param spriteItype + * type of the sprite to retrieve. * @return sprite collection of the specified type and subtypes. */ - public Iterator getSubSpritesGroup(int spriteItype) - { - //Create a sprite group for all the sprites - SpriteGroup allSprites = new SpriteGroup(spriteItype); - //Get all the subtypes - ArrayList allTypes = iSubTypes[spriteItype]; + public Iterator getSubSpritesGroup(int spriteItype) { + // Create a sprite group for all the sprites + SpriteGroup allSprites = new SpriteGroup(spriteItype); + // Get all the subtypes + ArrayList allTypes = iSubTypes[spriteItype]; - //Add sprites of this type, and all subtypes. - allSprites.addAllSprites(this.getSprites(spriteItype)); - for(Integer itype : allTypes) - { - allSprites.addAllSprites(this.getSprites(itype)); - } + // Add sprites of this type, and all subtypes. + allSprites.addAllSprites(this.getSprites(spriteItype)); + for (Integer itype : allTypes) { + allSprites.addAllSprites(this.getSprites(itype)); + } - //Return the iterator. - return allSprites.getSpriteIterator(); + // Return the iterator. + return allSprites.getSpriteIterator(); } /** * Gets the collection of sprites for a particular sprite type. - * @param spriteItype type of the sprite to retrieve. + * + * @param spriteItype + * type of the sprite to retrieve. * @return sprite collection of the specified type. */ - public ArrayList getSprites(int spriteItype) - { - return spriteGroups[spriteItype].getSprites(); + public ArrayList getSprites(int spriteItype) { + return spriteGroups[spriteItype].getSprites(); } /** * Gets the array of collisions defined for two types of sprites. - * @param spriteItype1 type of the first sprite. - * @param spriteItype2 type of the second sprite. - * @return the collection of the effects defined between the two sprite types. + * + * @param spriteItype1 + * type of the first sprite. + * @param spriteItype2 + * type of the second sprite. + * @return the collection of the effects defined between the two sprite + * types. */ - public ArrayList getCollisionEffects(int spriteItype1, int spriteItype2) - { - return collisionEffects[spriteItype1][spriteItype2]; + public ArrayList getCollisionEffects(int spriteItype1, int spriteItype2) { + return collisionEffects[spriteItype1][spriteItype2]; } /** * Returns all paired effects defined in the game. + * * @return all paired effects defined in the game. */ - public ArrayList> getDefinedEffects() - { - return definedEffects; + public ArrayList> getDefinedEffects() { + return definedEffects; } /** * Returns the list of sprite type with at least one EOS effect defined. + * * @return the list of sprite type with at least one EOS effect defined. */ - public ArrayList getDefinedEosEffects() - { - return definedEOSEffects; + public ArrayList getDefinedEosEffects() { + return definedEOSEffects; } /** * Returns all EOS effects defined in the game. + * * @return all EOS effects defined in the game. */ - public ArrayList getEosEffects(int obj1) - { - return eosEffects[obj1]; + public ArrayList getEosEffects(int obj1) { + return eosEffects[obj1]; } /** * Adds a time effect to the game. */ - public void addTimeEffect(TimeEffect ef) - { - timeEffects.add(ef); + public void addTimeEffect(TimeEffect ef) { + timeEffects.add(ef); } /** - * Returns the char mapping of this array, that relates characters in the level with - * sprite names that it references. - * @return the char mapping of this array. For each character, there is a list of N sprite names. + * Returns the char mapping of this array, that relates characters in the + * level with sprite names that it references. + * + * @return the char mapping of this array. For each character, there is a + * list of N sprite names. */ - public HashMap> getCharMapping() - { - return charMapping; + public HashMap> getCharMapping() { + return charMapping; } - + /** * Set the char mapping that is used to parse loaded levels - * @param charMapping new character mapping + * + * @param charMapping + * new character mapping */ - public void setCharMapping(HashMap> charMapping){ - this.charMapping = charMapping; + public void setCharMapping(HashMap> charMapping) { + this.charMapping = charMapping; } /** * Gets the array of termination conditions for this game. + * * @return the array of termination conditions. */ - public ArrayList getTerminations() - { - return terminations; + public ArrayList getTerminations() { + return terminations; } /** - * Gets the maximum amount of resources of type resourceId that are allowed by entities in the game. - * @param resourceId the id of the resource to query for. + * Gets the maximum amount of resources of type resourceId that are allowed + * by entities in the game. + * + * @param resourceId + * the id of the resource to query for. * @return maximum amount of resources of type resourceId. */ - public int getResourceLimit(int resourceId) - { - return resources_limits[resourceId]; + public int getResourceLimit(int resourceId) { + return resources_limits[resourceId]; } /** * Gets the color of the resource of type resourceId - * @param resourceId id of the resource to query for. + * + * @param resourceId + * id of the resource to query for. * @return Color assigned to this resource. */ - public Color getResourceColor(int resourceId) - { - return resources_colors[resourceId]; + public Color getResourceColor(int resourceId) { + return resources_colors[resourceId]; } /** * Gets the dimensions of the screen. + * * @return the dimensions of the screen. */ - public Dimension getScreenSize() {return screenSize;} + public Dimension getScreenSize() { + return screenSize; + } /** - * Defines this game as stochastic (or not) depending on the parameter passed. - * @param stoch true if the game is stochastic. + * Defines this game as stochastic (or not) depending on the parameter + * passed. + * + * @param stoch + * true if the game is stochastic. */ - public void setStochastic(boolean stoch) {is_stochastic = stoch;} + public void setStochastic(boolean stoch) { + is_stochastic = stoch; + } /** * Returns the avatar of the game in single player games. + * * @return the avatar of the game. */ - public MovingAvatar getAvatar() { return getAvatar(0); } + public MovingAvatar getAvatar() { + return getAvatar(0); + } /** - * Overloaded method, returns the avatar of the player specified (for multi player games). - * @param playerID ID of the player desired. + * Overloaded method, returns the avatar of the player specified (for multi + * player games). + * + * @param playerID + * ID of the player desired. * @return the corresponding avatar. */ - public MovingAvatar getAvatar(int playerID) { return avatars[playerID]; } + public MovingAvatar getAvatar(int playerID) { + return avatars[playerID]; + } /** * Returns an array of all avatars in the game. + * * @return array of avatars. */ - public MovingAvatar[] getAvatars() { return avatars; } - + public MovingAvatar[] getAvatars() { + return avatars; + } /** * Sets the avatar of the game. - * @param newAvatar the avatar of the game. + * + * @param newAvatar + * the avatar of the game. */ - public void setAvatar(MovingAvatar newAvatar) {avatars[0] = newAvatar;} + public void setAvatar(MovingAvatar newAvatar) { + avatars[0] = newAvatar; + } /** * Overloaded method, sets the avatar specified. - * @param newAvatar the avatar of the game. - * @param playerID the ID of the player desired. + * + * @param newAvatar + * the avatar of the game. + * @param playerID + * the ID of the player desired. */ - public void setAvatar(MovingAvatar newAvatar, int playerID) {avatars[playerID] = newAvatar;} + public void setAvatar(MovingAvatar newAvatar, int playerID) { + avatars[playerID] = newAvatar; + } /** - * Sets the last action executed by the avatar. It could be NIL in case of time overspent. - * @param action the action to set. + * Sets the last action executed by the avatar. It could be NIL in case of + * time overspent. + * + * @param action + * the action to set. */ - public void setAvatarLastAction(Types.ACTIONS action) - { - setAvatarLastAction(action, 0); + public void setAvatarLastAction(Types.ACTIONS action) { + setAvatarLastAction(action, 0); } - /** - * Overloaded method for multi player games. - * Sets the last action executed by the avatar with the corresponding player ID. - * It could be NIL in case of time overspent. - * @param action the action to set. - * @param playerID the ID of the player. + * Overloaded method for multi player games. Sets the last action executed + * by the avatar with the corresponding player ID. It could be NIL in case + * of time overspent. + * + * @param action + * the action to set. + * @param playerID + * the ID of the player. */ - public void setAvatarLastAction(Types.ACTIONS action, int playerID) { this.avatarLastAction[playerID] = action; } + public void setAvatarLastAction(Types.ACTIONS action, int playerID) { + this.avatarLastAction[playerID] = action; + } /** * Indicates if the game is over, or if it is still being played. + * * @return true if the game is over, false if it is still being played. */ public abstract boolean isGameOver(); - /** * clear all the interactions and termination in the current game */ - public void clearInteractionTerminationData(){ - this.setStochastic(false); - this.terminations.clear(); + public void clearInteractionTerminationData() { + this.setStochastic(false); + this.terminations.clear(); + + this.definedEffects.clear(); + for (int i = 0; i < this.collisionEffects.length; i++) { + for (int j = 0; j < this.collisionEffects[i].length; j++) { + this.collisionEffects[i][j].clear(); + } + } - this.definedEffects.clear(); - for(int i=0; i getPath(Vector2d start, Vector2d end) - { - Vector2d pathStart = new Vector2d(start); - Vector2d pathEnd = new Vector2d(end); + public ArrayList getPath(Vector2d start, Vector2d end) { + Vector2d pathStart = new Vector2d(start); + Vector2d pathEnd = new Vector2d(end); - pathStart.mul(1.0 / (double) block_size); - pathEnd.mul(1.0/(double)block_size); + pathStart.mul(1.0 / (double) block_size); + pathEnd.mul(1.0 / (double) block_size); - return pathf.getPath(pathStart, pathEnd); + return pathf.getPath(pathStart, pathEnd); } - - public HashMap getParameters() - { - return parameters; + public HashMap getParameters() { + return parameters; } - public void setParameters(HashMap parameters) - { - this.parameters = parameters; + public void setParameters(HashMap parameters) { + this.parameters = parameters; } - + /** * Class for helping collision detection. */ - protected class Bucket - { - ArrayList allSprites; - HashMap> spriteLists; - int totalNumSprites; - - public Bucket() - { - allSprites = new ArrayList(); - spriteLists = new HashMap>(); - totalNumSprites = 0; - } - - public void clear() - { - allSprites.clear(); - spriteLists.clear(); - totalNumSprites = 0; - } - - public void add(VGDLSprite sp) - { - int bucket = sp.bucket; - ArrayList sprites = spriteLists.get(bucket); - if(sprites == null) - { - sprites = new ArrayList(); - spriteLists.put(bucket, sprites); - } - sprites.add(sp); - allSprites.add(sp); - totalNumSprites++; - } - - public int size() - { - return totalNumSprites; - } - - public int size(int bucket) - { - ArrayList sprites = spriteLists.get(bucket); - if(sprites == null) - return 0; - return sprites.size(); - } - - public ArrayList getAllSprites() - { - return allSprites; - } - - public HashMap> getSpriteList() - { - return spriteLists; - } + protected class Bucket { + ArrayList allSprites; + HashMap> spriteLists; + int totalNumSprites; + + public Bucket() { + allSprites = new ArrayList(); + spriteLists = new HashMap>(); + totalNumSprites = 0; + } + + public void clear() { + allSprites.clear(); + spriteLists.clear(); + totalNumSprites = 0; + } + + public void add(VGDLSprite sp) { + int bucket = sp.bucket; + ArrayList sprites = spriteLists.get(bucket); + if (sprites == null) { + sprites = new ArrayList(); + spriteLists.put(bucket, sprites); + } + sprites.add(sp); + allSprites.add(sp); + totalNumSprites++; + } + + public int size() { + return totalNumSprites; + } + + public int size(int bucket) { + ArrayList sprites = spriteLists.get(bucket); + if (sprites == null) + return 0; + return sprites.size(); + } + + public ArrayList getAllSprites() { + return allSprites; + } + + public HashMap> getSpriteList() { + return spriteLists; + } } diff --git a/src/core/game/SLDescription.java b/src/core/game/SLDescription.java index 806e86e6..a8bd3a27 100644 --- a/src/core/game/SLDescription.java +++ b/src/core/game/SLDescription.java @@ -177,6 +177,9 @@ private int encodeName(String name, int seed) { * @return correct sprite name */ private String decodeName(int value, int seed) { + if((value ^ seed) < 0 || (value ^ seed) >= this.gameSprites.length){ + return ""; + } return this.gameSprites[value ^ seed].name; } @@ -223,35 +226,48 @@ public String[][] getCurrentLevel() { * @return return decoded interaction and termination rules */ public String[][] modifyRules(String[] rules, String[] wins, int seed) { - String[] modifiedRules = new String[rules.length]; - for (int i = 0; i < modifiedRules.length; i++) { + ArrayList modifiedRules = new ArrayList(); + for (int i = 0; i < rules.length; i++) { String[] parts = rules[i].split(" "); - modifiedRules[i] = ""; + modifiedRules.add(""); for (int j = 0; j < parts.length; j++) { if (parts[j].toLowerCase().contains(KEYWORD + "_")) { String[] temp = parts[j].split(KEYWORD + "_"); - modifiedRules[i] += temp[0] + this.decodeName(Integer.parseInt(temp[1]), seed) + " "; + String spriteName = this.decodeName(Integer.parseInt(temp[1]), seed); + if(spriteName.length() > 0){ + modifiedRules.set(modifiedRules.size() - 1, modifiedRules.get(modifiedRules.size() - 1) + temp[0] + spriteName + " "); + } + else{ + Logger.getInstance().addMessage(new Message(Message.WARNING, parts[j] + " is undefined in the game.")); + } + } else { - modifiedRules[i] += parts[j] + " "; + modifiedRules.set(modifiedRules.size() - 1, modifiedRules.get(modifiedRules.size() - 1) + parts[j] + " "); } } } - String[] modifiedWins = new String[wins.length]; - for (int i = 0; i < modifiedWins.length; i++) { + ArrayList modifiedWins = new ArrayList(); + for (int i = 0; i < wins.length; i++) { String[] parts = wins[i].split(" "); - modifiedWins[i] = ""; + modifiedWins.add(""); for (int j = 0; j < parts.length; j++) { if (parts[j].toLowerCase().contains(KEYWORD + "_")) { String[] temp = parts[j].split(KEYWORD + "_"); - modifiedWins[i] += temp[0] + this.decodeName(Integer.parseInt(temp[1]), seed) + " "; + String spriteName = this.decodeName(Integer.parseInt(temp[1]), seed); + if(spriteName.length() > 0){ + modifiedWins.set(modifiedWins.size() - 1, modifiedWins.get(modifiedWins.size() - 1) + temp[0] + spriteName + " "); + } + else{ + Logger.getInstance().addMessage(new Message(Message.WARNING, parts[j] + " is undefined in the game.")); + } } else { - modifiedWins[i] += parts[j] + " "; + modifiedWins.set(modifiedWins.size() - 1, modifiedWins.get(modifiedWins.size() - 1) + parts[j] + " "); } } } - return new String[][] { modifiedRules, modifiedWins }; + return new String[][] { modifiedRules.toArray(new String[modifiedRules.size()]), modifiedWins.toArray(new String[modifiedWins.size()]) }; } /** @@ -275,7 +291,7 @@ public StateObservation testRules(String[] rules, String[] wins) { this.currentGame.reset(); this.currentGame.buildStringLevel(this.level, this.random.nextInt()); - if (Logger.getInstance().getMessageCount(1) > 0) { + if (Logger.getInstance().getMessageCount(Message.ERROR) > 0) { return null; } return this.currentGame.getObservation(); diff --git a/src/core/logging/Logger.java b/src/core/logging/Logger.java index 56336aad..095639b0 100644 --- a/src/core/logging/Logger.java +++ b/src/core/logging/Logger.java @@ -44,8 +44,8 @@ public ArrayList getMessages(){ */ public void printMessages() { System.out.println("*** Logged Messages ***"); - for (Object msg : messages) { - System.out.println(((Message) msg).getContent()); + for (Message msg : messages) { + System.out.println(msg.toString()); } System.out.println("*** Logged Messages End ***"); } diff --git a/src/core/logging/Message.java b/src/core/logging/Message.java index 3f2932a8..310022f5 100644 --- a/src/core/logging/Message.java +++ b/src/core/logging/Message.java @@ -41,4 +41,12 @@ public int getType() { public String getContent() { return content; } + + /** + * return a string that explains the message + * @return a string explaining the whole error/warning + */ + public String toString() { + return (this.type == Message.ERROR? "Error: ": "Warning: ") + this.content; + } } diff --git a/src/ontology/effects/binary/Align.java b/src/ontology/effects/binary/Align.java index 4c9cbfc4..3495ea9b 100644 --- a/src/ontology/effects/binary/Align.java +++ b/src/ontology/effects/binary/Align.java @@ -3,6 +3,8 @@ import core.vgdl.VGDLSprite; import core.content.InteractionContent; import core.game.Game; +import core.logging.Logger; +import core.logging.Message; import ontology.effects.Effect; import java.awt.*; @@ -25,6 +27,10 @@ public Align(InteractionContent cnt) @Override public void execute(VGDLSprite sprite1, VGDLSprite sprite2, Game game) { + if(sprite1 == null || sprite2 == null){ + Logger.getInstance().addMessage(new Message(Message.WARNING, "Neither 1st not 2nd sprite can be EOS with Align interaction.")); + return; + } sprite1.orientation = sprite2.orientation.copy(); sprite1.rect = new Rectangle(sprite2.rect.x, sprite2.rect.y, sprite1.rect.width, sprite1.rect.height); diff --git a/src/ontology/effects/binary/PullWithIt.java b/src/ontology/effects/binary/PullWithIt.java index 665c113b..d0e48d34 100644 --- a/src/ontology/effects/binary/PullWithIt.java +++ b/src/ontology/effects/binary/PullWithIt.java @@ -6,6 +6,8 @@ import core.vgdl.VGDLSprite; import core.content.InteractionContent; import core.game.Game; +import core.logging.Logger; +import core.logging.Message; import ontology.Types; import ontology.effects.Effect; import ontology.physics.ContinuousPhysics; @@ -39,6 +41,10 @@ public PullWithIt(InteractionContent cnt) @Override public void execute(VGDLSprite sprite1, VGDLSprite sprite2, Game game) { + if(sprite1 == null || sprite2 == null){ + Logger.getInstance().addMessage(new Message(Message.WARNING, "Neither the 1st nor 2nd sprite can be EOS with PullWithIt interaction.")); + return; + } //Keep in the list, for the current cycle, the sprites that have triggered this event. int currentGameTime = game.getGameTick(); if(currentGameTime > lastGameTime) diff --git a/src/ontology/effects/binary/TeleportToExit.java b/src/ontology/effects/binary/TeleportToExit.java index 25231f8b..7344768e 100644 --- a/src/ontology/effects/binary/TeleportToExit.java +++ b/src/ontology/effects/binary/TeleportToExit.java @@ -6,6 +6,8 @@ import core.vgdl.VGDLSprite; import core.content.InteractionContent; import core.game.Game; +import core.logging.Logger; +import core.logging.Message; import ontology.effects.Effect; import tools.Utils; @@ -29,7 +31,14 @@ public void execute(VGDLSprite sprite1, VGDLSprite sprite2, Game game) { int destinationId = VGDLFactory.GetInstance().requestFieldValueInt(sprite2, "itype"); - Collection sprites = game.getSprites(destinationId); + Collection sprites = null; + if(destinationId != -1){ + sprites = game.getSprites(destinationId); + } + else{ + Logger.getInstance().addMessage(new Message(Message.WARNING, "Ignoring TeleportToExit effect as " + sprite2.name + " isn't of type portal.")); + return; + } if(sprites.size() > 0){ VGDLSprite destination = (VGDLSprite) Utils.choice(sprites.toArray(), game.getRandomGenerator());