/* * (c) 2000-2009 Carlos G�mez Rodr�guez, todos los derechos reservados / all rights reserved. * Licencia en license/bsd.txt / License in license/bsd.txt */ package eu.irreality.age; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Vector; import eu.irreality.age.debug.Debug; import eu.irreality.age.matching.Match; import eu.irreality.age.matching.Matches; public class EntityList implements Iterable { /**Vector que contiene las entidades.*/ protected java.util.Vector laLista; public Object clone() { EntityList el = new EntityList(); el.laLista = (java.util.Vector) this.laLista.clone(); return el; } public void clear() { laLista.clear(); } public Iterator iterator() { return laLista.iterator(); } /** * La funci�n addElement de java.util.Vector. * */ private void addElement ( Entity o ) { laLista.addElement ( o ); } public void addEntity ( Entity e ) { addElement(e); } /** * La funci�n removeElement de java.util.Vector. * */ private boolean removeElement ( Entity o ) { return laLista.removeElement ( o ); } public boolean remove ( Object o ) { return laLista.remove(o); } public boolean removeAll ( Collection c ) { boolean changed = false; for (Iterator iterator = c.iterator(); iterator.hasNext();) { Object object = (Object) iterator.next(); if ( this.remove(object) ) changed = true; } return changed; } public boolean removeAll ( EntityList el ) { boolean changed = false; for ( int i = 0 ; i < el.size() ; i++ ) { Object object = (Object) el.get(i); if ( this.remove(object) ) changed = true; } return changed; } public int size ( ) { return laLista.size ( ); } public Entity entityAt ( int i ) { return (Entity) laLista.elementAt(i); } public Entity get ( int i ) { return (Entity)laLista.get(i); } public boolean isEmpty ( ) { return laLista.isEmpty(); } public boolean contains ( Object e ) { for ( int i = 0 ; i < size() ; i++ ) { Debug.println(laLista); Debug.println("i=" + i); if ( entityAt(i) != null && entityAt(i).equals( e ) ) return true; } return false; } /*general pattern matching: generates vector (no longer vector) of matches*/ public Matches patternMatch ( String arguments, boolean singOrPlur ) { //Debug.println("patternMatch call: " + this + " - " + arguments + " - " + singOrPlur ); Matches resultado = new Matches ( ); int [] prioridades = new int [ size() ]; for ( int i = 0 ; i < size() ; i++ ) { if ( entityAt(i) == null ) continue; //esto pasa en los wieldedWeapons invs. p.ej. int currentMatchPriority = entityAt(i).matchesCommand(arguments,singOrPlur); //Debug.println(">priority " + currentMatchPriority + "[" + entityAt(i) + "]" ); //con el plural, "dejar piedras" devolvera lista de piedras para dejarlas todas. Con el singular, normalmente solo consideraremos una de la lista. Pero esto no es cosa de esta funci�n. if ( ( currentMatchPriority != 0 ) ) { Vector thePath = new Vector(); thePath.add(entityAt(i)); resultado.addMatch( new Match(thePath,currentMatchPriority) ); //old! /* //insertar en el vector int j = 0; while ((j<size()) && ( prioridades[j] != 0 ) && ( prioridades[j] < currentMatchPriority )) { j++; } //hemos encontrado la posicion //Debug.println("Added " + entityAt(i).getID() + " at pos " + j); if ( j < resultado.size() ) resultado.add ( j , entityAt(i) ); else resultado.add ( entityAt(i) ); for ( int k = size()-2 ; k >= j ; k-- ) { prioridades[k+1] = prioridades[k]; } prioridades[j] = currentMatchPriority; */ } } //if ( resultado.size() == 2 ) //{ // Debug.println("Vector is " + "[" + ((Entity)resultado.get(0)).getID() + "," + ((Entity)resultado.get(1)).getID() + "]" ); //} return resultado; } /** * This generates a Matches object. When we apply the toPathVector() method to it, * we obtain a vector of vectors, where each subvector is a path of containers * to the object mentioned in the arguments. * * Such a path is of the form [pearl,box,chest] if the pearl is inside the box which * is inside the chest. * * The return value of this method can have zero or more paths: for example, if there * are two pearls, one in the box inside the chest and one in a bottle, this method * would return [ [pearl,box,chest], [pearl,bottle] ]. */ public Matches patternMatchWithRecursion ( String arguments , boolean singOrPlur ) { //java.util.Vector resultado = new java.util.Vector ( ); Matches resultado = new Matches(); java.util.Vector path = new java.util.Vector ( ); //System.err.println("pmwr " + arguments + " false\n"); return patternMatchWithRecursion ( arguments , singOrPlur , path , resultado ); } protected Matches patternMatchWithRecursion ( String arguments, boolean singOrPlur , java.util.Vector /*of entities*/ path , Matches resultado ) { for ( int i = 0 ; i < size() ; i++ ) { if ( entityAt(i) == null ) continue; //esto pasa en los wieldedWeapons invs. p.ej. int currentMatchPriority = entityAt(i).matchesCommand(arguments,singOrPlur); //con el plural, "dejar piedras" devolvera lista de piedras para dejarlas todas. Con el singular, normalmente solo consideraremos una de la lista. Pero esto no es cosa de esta funci�n. if ( ( currentMatchPriority != 0 ) ) { java.util.Vector pathToAdd = (java.util.Vector) path.clone(); pathToAdd.add(0,entityAt(i)); resultado.addMatch(new Match(pathToAdd,currentMatchPriority)); } if ( entityAt(i) instanceof Item && ((Item)entityAt(i)).getContents() != null ) { Inventory inv = ((Item)entityAt(i)).getContents(); java.util.Vector newPath = (java.util.Vector) path.clone(); newPath.add(0,entityAt(i)); ((Item)entityAt(i)).getContents().patternMatchWithRecursion(arguments,singOrPlur,newPath,resultado); } } return resultado; } /* protected java.util.Vector patternMatchWithRecursion_old ( String arguments, boolean singOrPlur , java.util.Vector path , java.util.Vector resultado ) { //Debug.println("patternMatch call: " + this + " - " + arguments + " - " + singOrPlur ); //java.util.Vector resultado = new java.util.Vector ( ); int [] prioridades = new int [ size() ]; for ( int i = 0 ; i < size() ; i++ ) { if ( entityAt(i) == null ) continue; //esto pasa en los wieldedWeapons invs. p.ej. int currentMatchPriority = entityAt(i).matchesCommand(arguments,singOrPlur); //Debug.println(">priority " + currentMatchPriority + "[" + entityAt(i) + "]" ); //con el plural, "dejar piedras" devolvera lista de piedras para dejarlas todas. Con el singular, normalmente solo consideraremos una de la lista. Pero esto no es cosa de esta funci�n. if ( ( currentMatchPriority != 0 ) ) { //insertar en el vector int j = 0; while ((j<size()) && ( prioridades[j] != 0 ) && ( prioridades[j] < currentMatchPriority )) { j++; } //hemos encontrado la posicion Debug.println("Added " + entityAt(i).getID() + " at pos " + j); java.util.Vector pathToAdd = (java.util.Vector) path.clone(); pathToAdd.add(0,entityAt(i)); if ( j < resultado.size() ) resultado.add ( j , pathToAdd ); else resultado.add ( pathToAdd ); for ( int k = size()-2 ; k >= j ; k-- ) { prioridades[k+1] = prioridades[k]; } prioridades[j] = currentMatchPriority; } if ( entityAt(i) instanceof Item && ((Item)entityAt(i)).getContents() != null ) { Inventory inv = ((Item)entityAt(i)).getContents(); java.util.Vector newPath = (java.util.Vector) path.clone(); newPath.add(0,entityAt(i)); ((Item)entityAt(i)).getContents().patternMatchWithRecursion(arguments,singOrPlur,newPath,resultado); } } return resultado; } */ /* "pattern matching" para cuando se buscan en una frase referencias a dos objetos, no a uno (ejemplo: abrir la puerta con la llave) */ public Matches [] patternMatchTwoWithRecursion ( String arguments , boolean singOrPlur1 , boolean singOrPlur2 ) { //int [] prioridades = new int [ size() ]; Matches[] resultado = new Matches[2]; //El procedimiento es dividir el string en todos los pares de strings posibles //atendiendo a sus tokens, y hacer patternmatching en cada uno. //Ej. "la puerta con la llave" // probamos "la", "puerta con la llave" -> falla. // "la puerta", "con la llave" -> �OK!, encontrados puerta y llave -> return. //punto division 2? tokens 1-2, 3-5. // ergo, punto division va de 1 a 4 (ntoks-1). p.d. 5 ser�a un solo objeto. int ntokens = StringMethods.numToks ( arguments , ' ' ); int bestPriority = Integer.MAX_VALUE; //best matching priority initially very bad. //probar todas las posibles divisiones en tokens. //�Por qu� va al rev�s? Porque son siempre mejores las divisiones "tard�as": //es mejor poner la cinta roja * en el armario azul que poner la cinta * roja en el armario azul. for ( int punto_division = ntokens-1 ; punto_division >= 1 ; punto_division-- ) { String parte1 = StringMethods.getToks ( arguments , 1 , punto_division , ' ' ); String parte2 = StringMethods.getToks ( arguments , punto_division+1 , ntokens , ' ' ); Matches result1 = patternMatchWithRecursion ( parte1 , singOrPlur1 ); Matches result2 = patternMatchWithRecursion ( parte2 , singOrPlur2 ); if ( result1.size() > 0 && result2.size() > 0 ) { int newPriority = Math.min(result1.getBestPriority(), result2.getBestPriority()); if ( newPriority < bestPriority ) { resultado[0] = result1; resultado[1] = result2; bestPriority = newPriority; } } } if ( resultado[0] == null ) //nothing found { resultado[0] = new Matches(); resultado[1] = new Matches(); //el vacio (no se han encontrado combos de dos objetos) } return resultado; } /* "pattern matching" para cuando se buscan en una frase referencias a dos objetos, no a uno (ejemplo: abrir la puerta con la llave) */ public Matches [] patternMatchTwo ( String arguments , boolean singOrPlur1 , boolean singOrPlur2 ) { //int [] prioridades = new int [ size() ]; Matches[] resultado = new Matches[2]; //El procedimiento es dividir el string en todos los pares de strings posibles //atendiendo a sus tokens, y hacer patternmatching en cada uno. //Ej. "la puerta con la llave" // probamos "la", "puerta con la llave" -> falla. // "la puerta", "con la llave" -> �OK!, encontrados puerta y llave -> return. //punto division 2? tokens 1-2, 3-5. // ergo, punto division va de 1 a 4 (ntoks-1). p.d. 5 ser�a un solo objeto. int ntokens = StringMethods.numToks ( arguments , ' ' ); int bestPriority = Integer.MAX_VALUE; //best matching priority initially very bad. //probar todas las posibles divisiones en tokens. //�Por qu� va al rev�s? Porque son siempre mejores las divisiones "tard�as": //es mejor poner la cinta roja * en el armario azul que poner la cinta * roja en el armario azul. for ( int punto_division = ntokens-1 ; punto_division >= 1 ; punto_division-- ) { String parte1 = StringMethods.getToks ( arguments , 1 , punto_division , ' ' ); String parte2 = StringMethods.getToks ( arguments , punto_division+1 , ntokens , ' ' ); Matches result1 = patternMatch ( parte1 , singOrPlur1 ); Matches result2 = patternMatch ( parte2 , singOrPlur2 ); if ( result1.size() > 0 && result2.size() > 0 ) { int newPriority = Math.min(result1.getBestPriority(), result2.getBestPriority()); if ( newPriority < bestPriority ) { resultado[0] = result1; resultado[1] = result2; bestPriority = newPriority; } } } if ( resultado[0] == null ) //nothing found { resultado[0] = new Matches(); resultado[1] = new Matches(); //el vacio (no se han encontrado combos de dos objetos) } return resultado; } /* Lo mismo que en el anterior; pero cuando los items han de estar en dos inventarios diferentes. Por ejemplo, para "abrir puerta con llave" normalmente se usar�a esta funci�n (a no ser que llevemos la puerta) por estar la llave en nuestro inventario y la puerta en el de la habitaci�n. */ public Matches [] patternMatchTwo ( EntityList i , String arguments , boolean singOrPlur1 , boolean singOrPlur2 ) { //int [] prioridades = new int [ size() ]; Matches[] resultado = new Matches [2]; //El procedimiento es dividir el string en todos los pares de strings posibles //atendiendo a sus tokens, y hacer patternmatching en cada uno. //Ej. "la puerta con la llave" // probamos "la", "puerta con la llave" -> falla. // "la puerta", "con la llave" -> �OK!, encontrados puerta y llave -> return. //punto division 2? tokens 1-2, 3-5. // ergo, punto division va de 1 a 4 (ntoks-1). p.d. 5 ser�a un solo objeto. int ntokens = StringMethods.numToks ( arguments , ' ' ); int bestPriority = Integer.MAX_VALUE; //best matching priority initially very bad. //probar todas las posibles divisiones en tokens for ( int punto_division = ntokens-1 ; punto_division >= 1 ; punto_division-- ) { String parte1 = StringMethods.getToks ( arguments , 1 , punto_division , ' ' ); String parte2 = StringMethods.getToks ( arguments , punto_division+1 , ntokens , ' ' ); Matches result1 = patternMatch ( parte1 , singOrPlur1 ); Matches result2 = i.patternMatch ( parte2 , singOrPlur2 ); if ( result1.size() > 0 && result2.size() > 0 ) { int newPriority = Math.min(result1.getBestPriority(), result2.getBestPriority()); if ( newPriority < bestPriority ) { resultado[0] = result1; resultado[1] = result2; bestPriority = newPriority; } } } if ( resultado[0] == null ) //nothing found { resultado[0] = new Matches(); resultado[1] = new Matches(); //el vacio (no se han encontrado combos de dos objetos) } return resultado; } public EntityList() { laLista = new java.util.Vector(); } }