diff --git a/package-lock.json b/package-lock.json index be01c17..f136b47 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pilas-bloques-exercises", - "version": "1.4.7", + "version": "1.4.12", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b634fb3..dd92631 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pilas-bloques-exercises", - "version": "1.4.7", + "version": "1.4.12", "description": "Exercises for Pilas Bloques", "homepage": "http://pilasbloques.program.ar", "author": { diff --git a/src/actores/Casilla.ts b/src/actores/Casilla.ts index 9108402..3d00874 100644 --- a/src/actores/Casilla.ts +++ b/src/actores/Casilla.ts @@ -145,6 +145,10 @@ class Casilla extends ActorAnimado { return this.actores.some( actor => actor.tiene_etiqueta(unaEtq)) } + tieneMasDeUnActor(){ + return this.actores.length > 1 + } + actoresConEtiqueta(unaEtq) { return this.actores.filter(actor => actor.tiene_etiqueta(unaEtq)); } diff --git a/src/actores/segundoCiclo/Manic/Manic.ts b/src/actores/segundoCiclo/Manic/Manic.ts index 9768606..552c0ca 100644 --- a/src/actores/segundoCiclo/Manic/Manic.ts +++ b/src/actores/segundoCiclo/Manic/Manic.ts @@ -7,15 +7,12 @@ class Manic extends ActorAnimado { constructor() { super(0,0,{cantColumnas: 10, cantFilas: 9}); this.definirAnimacion("parado", - new Cuadros(0).repetirVeces(16) + new Cuadros(32).repetirVeces(18) + .concat([33, 34, 34, 32, 32, 32, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]) + .concat(new Cuadros(32).repetirVeces(18)) + .concat([33, 34, 34, 32, 32, 32, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]) .concat([32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 34, 32, 32, 32, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]) - .concat(new Cuadros(0).repetirVeces(30)) - .concat([32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 34, 32, 32, 32, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]) - .concat(new Cuadros(0).repetirVeces(30)) - .concat([32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 34, 34, 32, 32, 32, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32]) - .concat(new Cuadros(0).repetirVeces(16)) - .concat([32]) - .concat(new Cuadros(0).repetirVeces(5)), + .concat([32]), 20, true); this.definirAnimacion("correr", [0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 7], 20); this.definirAnimacion("correrChocando", [0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 6, 7, 6, 5, 6, 7, 7], 12) diff --git a/src/actores/segundoCiclo/MetaFinal.ts b/src/actores/segundoCiclo/MetaFinal.ts new file mode 100644 index 0000000..e9c0e0a --- /dev/null +++ b/src/actores/segundoCiclo/MetaFinal.ts @@ -0,0 +1,20 @@ +/// + +class MetaFinal extends ActorAnimado { + + static imagenesPara(actor) : string[] { + return [`marcador-${actor}.png`]; + } + + constructor(actor: string) { + super(0, 0, { grilla: `marcador-${actor}.png`, cantColumnas: 1, cantFilas: 1 }); + } + + enviarAtras() { + this.setZ(Math.min(this.getZ() + 1)) + } + + ajustarSegunCuadricula(alto){ + this.setY(this.getY() + alto / 2) + } +} \ No newline at end of file diff --git a/src/assets/marcador-capy.png b/src/assets/marcador-capy.png new file mode 100644 index 0000000..4a893b3 Binary files /dev/null and b/src/assets/marcador-capy.png differ diff --git a/src/assets/marcador-chuy.png b/src/assets/marcador-chuy.png new file mode 100644 index 0000000..b470dcc Binary files /dev/null and b/src/assets/marcador-chuy.png differ diff --git a/src/assets/marcador-duba.png b/src/assets/marcador-duba.png new file mode 100644 index 0000000..caf533e Binary files /dev/null and b/src/assets/marcador-duba.png differ diff --git a/src/assets/marcador-lita.png b/src/assets/marcador-lita.png new file mode 100644 index 0000000..06b3a7e Binary files /dev/null and b/src/assets/marcador-lita.png differ diff --git a/src/assets/marcador-manic.png b/src/assets/marcador-manic.png new file mode 100644 index 0000000..ab38ec3 Binary files /dev/null and b/src/assets/marcador-manic.png differ diff --git a/src/assets/marcador-yvoty.png b/src/assets/marcador-yvoty.png new file mode 100644 index 0000000..81c3edd Binary files /dev/null and b/src/assets/marcador-yvoty.png differ diff --git a/src/assets/pelotaAnimada.png b/src/assets/pelotaAnimada.png index 6ce8c54..17ecd21 100644 Binary files a/src/assets/pelotaAnimada.png and b/src/assets/pelotaAnimada.png differ diff --git a/src/escenas/EscenaActividad.ts b/src/escenas/EscenaActividad.ts index fd9c9a5..cf48f84 100644 --- a/src/escenas/EscenaActividad.ts +++ b/src/escenas/EscenaActividad.ts @@ -13,6 +13,8 @@ class EscenaActividad extends Base { automata : ActorAnimado; cuadricula : Cuadricula; fondo; + xFinal: number; + yFinal: number; /** * Devuelve todos los nombres de archivo de imagen necesarios para @@ -99,6 +101,18 @@ class EscenaActividad extends Base { return this.obtenerActoresConEtiqueta(actor).every(o => o.nombreAnimacionActual() == estado); } + estaEnPosicionFinalSiLaTiene(): boolean { + return !this.tienePosicionFinal() || this.automataEnPosicionFinal() + } + + tienePosicionFinal(): boolean { + return this.xFinal !== undefined + } + + automataEnPosicionFinal(): boolean { + return this.automata.casillaActual().sos(this.yFinal, this.xFinal); + } + /** * Computa un multiplicador que crece según la cantidad de filas y columnas de la cuadrícula. * El multiplicador es 1 si la cuadrícula es de 1x1, y crece acotado por maxRatio. diff --git a/src/escenas/libroPrimaria/CustomScene.ts b/src/escenas/libroPrimaria/CustomScene.ts index 2dd3113..97b78f8 100644 --- a/src/escenas/libroPrimaria/CustomScene.ts +++ b/src/escenas/libroPrimaria/CustomScene.ts @@ -49,6 +49,10 @@ class CustomScene extends EscenaDesdeMapa { this.initDesdeUnaOVariasDescripciones(options.grid.spec, options.grid.specOptions); } + static nombreAutomata(): string { + return 'custom' + } + obtenerAutomata(): ActorAnimado { return this.automata } diff --git a/src/escenas/libroPrimaria/EscenaCapy.ts b/src/escenas/libroPrimaria/EscenaCapy.ts index 10b4e54..34c063e 100644 --- a/src/escenas/libroPrimaria/EscenaCapy.ts +++ b/src/escenas/libroPrimaria/EscenaCapy.ts @@ -12,13 +12,13 @@ class EscenaCapy extends EscenaDesdeMapa { return 'fondo.capy.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('capy').concat(Obstaculo.imagenesPara('capy')); + static nombreAutomata(): string { + return 'capy' } - constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio) { + constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } ajustarGraficos() { @@ -57,10 +57,6 @@ class EscenaCapy extends EscenaDesdeMapa { return new Obstaculo(archivosObstaculos, (fila + 1) + (fila + 1) * (columna + 1)); } - todosLosActoresCumplen(actor, estado) { - return this.obtenerActoresConEtiqueta(actor).every(o => o.nombreAnimacionActual() == estado); - } - tachosLlenos(): boolean { return this.todosLosActoresCumplen("Tacho", "lleno") } @@ -77,13 +73,8 @@ class EscenaCapy extends EscenaDesdeMapa { return this.recogidos(actor) || this.noHay(actor) } - - noHay(actor): boolean { - return this.contarActoresConEtiqueta(actor) == 0 - } - estaResueltoElProblema(): boolean { - return this.tachoResuelto() && this.recoleccionResuelta("Lata") && this.recoleccionResuelta("Papel") + return super.estaResueltoElProblema() && this.tachoResuelto() && this.recoleccionResuelta("Lata") && this.recoleccionResuelta("Papel") } archivoFondo() { diff --git a/src/escenas/libroPrimaria/EscenaChuy.ts b/src/escenas/libroPrimaria/EscenaChuy.ts index 7b956f9..75c4425 100644 --- a/src/escenas/libroPrimaria/EscenaChuy.ts +++ b/src/escenas/libroPrimaria/EscenaChuy.ts @@ -13,18 +13,13 @@ class EscenaChuy extends EscenaDesdeMapa { return 'fondo.chuy.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('chuy').concat(Obstaculo.imagenesPara('chuy')); + static nombreAutomata(): string { + return 'chuy' } constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); - - if (posFinal) { - this.xFinal = posFinal[0]; - this.yFinal = posFinal[1]; - } + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } ajustarGraficos() { @@ -44,7 +39,7 @@ class EscenaChuy extends EscenaDesdeMapa { this.obtenerActoresConEtiqueta("PelotaAnimada").forEach(actor => { actor.aprender(Flotar, { Desvio: 4 }); - actor.escala *= this.escalaSegunCuadricula(0.5); + actor.escala *= this.escalaSegunCuadricula(0.1); }); this.obtenerActoresConEtiqueta("PingPong").forEach(actor => { @@ -83,7 +78,7 @@ class EscenaChuy extends EscenaDesdeMapa { } estaEnPosicionFinalSiLaTiene(): boolean { - return this.xFinal === undefined || this.automata.casillaActual().sos(this.yFinal, this.xFinal) || this.automata.alFinalDelCamino(); + return super.estaEnPosicionFinalSiLaTiene() || this.automata.alFinalDelCamino(); } noHayPelotas(): boolean { diff --git a/src/escenas/libroPrimaria/EscenaDesdeMapa.ts b/src/escenas/libroPrimaria/EscenaDesdeMapa.ts index ae58749..4cfaf36 100644 --- a/src/escenas/libroPrimaria/EscenaDesdeMapa.ts +++ b/src/escenas/libroPrimaria/EscenaDesdeMapa.ts @@ -6,13 +6,13 @@ /// type MapaEscena = Array>; -declare var grammar : nearley.CompiledRules; // Header para la gramática, que se toma desde ../../../parserAleatorio/gramticaAleatoria.js +declare var grammar: nearley.CompiledRules; // Header para la gramática, que se toma desde ../../../parserAleatorio/gramticaAleatoria.js -type GridSpec = { +type GridSpec = { spec: Spec, specOptions?: opcionesMapaAleatorio - } - +} + type Spec = string | string[] /** @@ -29,47 +29,71 @@ type Spec = string | string[] */ abstract class EscenaDesdeMapa extends EscenaActividad { - mapaEscena : MapaEscena; - generadorDeMapas : GeneradorDeMapas; + mapaEscena: MapaEscena; + generadorDeMapas: GeneradorDeMapas; /** * @param generadorDeMapas El generador que se utilizará para obtener mapas para la actividad. */ - constructor(generadorDeMapas? : GeneradorDeMapas) { + constructor(generadorDeMapas?: GeneradorDeMapas) { super(); this.generadorDeMapas = generadorDeMapas; } - initDesdeMapa(mapa : MapaEscena) { + static imagenesAdicionales(): string[] { + return [Casilla, Obstaculo, MetaFinal].map(clase => clase.imagenesPara(this.nombreAutomata())).reduce((acc, list) => list.concat(acc), []); + } + + /** + * Devuelve el nombre del automata, usado para la precarga de metas finales, obstaculos y casillas + * Pensado para redefinirse por escena. + */ + static nombreAutomata() { + return '' + } + + initDesdeMapa(mapa: MapaEscena) { this.generadorDeMapas = new GeneradorDeMapasSimple(mapa); } - initDesdeArrayDeMapas(mapas : Array) { - var generadores : Array + initDesdeArrayDeMapas(mapas: Array) { + var generadores: Array = mapas.map(m => new GeneradorDeMapasSimple(m)); this.generadorDeMapas = new GeneradorDeMapasArray(generadores); } - initDesdeDescripcion(descripcion : string, opciones?: opcionesMapaAleatorio) { + initDesdeDescripcion(descripcion: string, opciones?: opcionesMapaAleatorio) { this.generadorDeMapas = new GeneradorDeMapasAleatorios(descripcion, opciones); } - initDesdeArrayDeDescripciones(descripciones : Array, opciones?: opcionesMapaAleatorio) { + initDesdeArrayDeDescripciones(descripciones: Array, opciones?: opcionesMapaAleatorio) { var generadores: Array = descripciones.map(d => new GeneradorDeMapasAleatorios(d, opciones)); this.generadorDeMapas = new GeneradorDeMapasArray(generadores); } - initDesdeUnaOVariasDescripciones(especificacion: Spec, opciones?: opcionesMapaAleatorio) { //Podria recibir un GridSpec directamente + initDesdeUnaOVariasDescripciones(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { //Podria recibir un GridSpec directamente + this.guardarPosicionFinal(posFinal) if (Array.isArray(especificacion)) this.initDesdeArrayDeDescripciones(especificacion, opciones); else this.initDesdeDescripcion(especificacion, opciones); } - iniciar() : void { + guardarPosicionFinal(posFinal?: [number, number]){ + if (posFinal && this.posicionValida(posFinal)) { + this.xFinal = posFinal[0]; + this.yFinal = posFinal[1]; + } + } + + posicionValida(posFinal: [number, number]){ + return posFinal[0] >= 0 && posFinal[1] >= 0 + } + + iniciar(): void { this.fondo = new Fondo(this.archivoFondo(), 0, 0); - + this.automata = this.obtenerAutomata(); if (this.generadorDeMapas) { @@ -80,21 +104,40 @@ abstract class EscenaDesdeMapa extends EscenaActividad { this.cuadricula = this.construirCuadricula(this.mapaEscena); + this.agregarCasillaFinalSiLaTiene(); this.automata.enviarAlFrente(); this.ajustarGraficos(); } - protected construirCuadricula(mapa : MapaEscena) : Cuadricula { + protected construirCuadricula(mapa: MapaEscena): Cuadricula { const matrizBooleana = mapa.map(fila => fila.map(casilla => casilla === '_' ? 'F' : 'T')) const cuadricula: CuadriculaEsparsa = new CuadriculaEsparsa(this.cuadriculaX(), this.cuadriculaY(), this.opsCuadricula(), this.opsCasilla(), matrizBooleana); cuadricula.forEachCasilla(casilla => this.llenarCasilla(cuadricula, casilla, mapa)); return cuadricula; } - llenarCasilla(cuadricula : Cuadricula, casilla : Casilla, mapa : MapaEscena) : void { - let nroFila : number = casilla.nroFila; - let nroColumna : number = casilla.nroColumna; - let ids : string[] = mapa[nroFila][nroColumna].split("&"); + casillaFinal(): Casilla { + return this.cuadricula.casilla(this.yFinal, this.xFinal) + } + + agregarCasillaFinalSiLaTiene(): void { + if (this.tienePosicionFinal()) { + const actor = new MetaFinal((this.constructor as typeof EscenaDesdeMapa).nombreAutomata()) + this.cuadricula.agregarActorEnCasilla(actor, this.casillaFinal(), true) + this.ajustarMeta(actor) + } + } + + ajustarMeta(meta){ + meta.escala *= this.escalaSegunCuadricula(0.7); + meta.ajustarSegunCuadricula(this.cuadricula.getOpcionesCasilla().alto) + if(this.casillaFinal().tieneMasDeUnActor()) meta.enviarAtras() //en el caso de que haya un premio, debe ir atrás de este + } + + llenarCasilla(cuadricula: Cuadricula, casilla: Casilla, mapa: MapaEscena): void { + let nroFila: number = casilla.nroFila; + let nroColumna: number = casilla.nroColumna; + let ids: string[] = mapa[nroFila][nroColumna].split("&"); ids.forEach(id => { if (id != '' && id != ' ' && id != '-' && id != '_') { // si no es casilla libre let actor = this.mapearIdentificadorAActor(id, nroFila, nroColumna); @@ -103,17 +146,21 @@ abstract class EscenaDesdeMapa extends EscenaActividad { }) } + estaResueltoElProblema(): Boolean { + return this.estaEnPosicionFinalSiLaTiene() + } + /** * Indica si el mapa es distinto cada vez que se ejecuta la escena. */ - tieneAleatoriedad() : boolean { + tieneAleatoriedad(): boolean { return this.generadorDeMapas.tieneAleatoriedad(); } /** * Crea y devuelve el autómata de la actividad. */ - abstract obtenerAutomata() : ActorAnimado; + abstract obtenerAutomata(): ActorAnimado; /** * Recibe un identificador y crea y devuelve el actor que le corresponde. @@ -122,29 +169,29 @@ abstract class EscenaDesdeMapa extends EscenaActividad { * de la casilla donde se colocará el actor. */ abstract mapearIdentificadorAActor( - id : string, - nroFila : number, + id: string, + nroFila: number, nroColumna: number - ) : ActorAnimado; + ): ActorAnimado; /** * Se puede sobreescribir esta función para definir acciones que se realizarán * justo después de iniciar la escena para mejorar su aspecto visual. Por ejemplo, * ajustar la escala o la posición de los actores. Por defecto, no hace nada. */ - ajustarGraficos() : void {}; - + ajustarGraficos(): void { }; + /** Devuelve el path del archivo que se usará como fondo de la escena. */ - abstract archivoFondo() : string; + abstract archivoFondo(): string; /** Devuelve la posición en el eje X de la cuadrícula. Se puede sobreescribir. */ cuadriculaX(): number { return 0; } /** Devuelve la posición en el eje X de la cuadrícula. Se puede sobreescribir. */ - cuadriculaY() : number { return 0; } + cuadriculaY(): number { return 0; } /** Devuelve las opciones que se usarán para crear la cuadrícula. Se puede sobreescribir. */ - opsCuadricula() : any { return {}; } + opsCuadricula(): any { return {}; } /** Devuelve las opciones que se usarán para crear la casilla. Se puede sobreescribir. */ opsCasilla(): any { return { grilla: 'invisible.png' }; } @@ -155,16 +202,16 @@ abstract class EscenaDesdeMapa extends EscenaActividad { */ interface GeneradorDeMapas { /** Genera un mapa de escena. */ - obtenerMapa() : MapaEscena; + obtenerMapa(): MapaEscena; /** Indica si los mapas generados varían con cada ejecución. */ - tieneAleatoriedad() : boolean; + tieneAleatoriedad(): boolean; } /** * Este generador se inicializa con un mapa y devuelve siempre dicho mapa. */ class GeneradorDeMapasSimple implements GeneradorDeMapas { - constructor(private mapa : MapaEscena) {} + constructor(private mapa: MapaEscena) { } obtenerMapa() { return this.mapa; } tieneAleatoriedad() { return false; } } @@ -174,7 +221,7 @@ class GeneradorDeMapasSimple implements GeneradorDeMapas { * Cada vez que se le pide un mapa, elige uno de ellos al azar. */ class GeneradorDeMapasArray implements GeneradorDeMapas { - constructor(private generadores : Array) {} + constructor(private generadores: Array) { } obtenerMapa() { return Math.randomFrom(this.generadores).obtenerMapa(); } tieneAleatoriedad() { return this.generadores.length > 1 || this.generadores[0].tieneAleatoriedad(); } } @@ -210,18 +257,18 @@ class GeneradorDeMapasArray implements GeneradorDeMapas { * string indicada en la opción `macros`. */ class GeneradorDeMapasAleatorios implements GeneradorDeMapas { - generadoresDeSemillas : Array>; - _probaPorDefecto : number; - bolsa : Array; - bolsas: { [id : string] : Array }; - coleccion : Array; - colecciones: { [id : string] : Array }; - macros : { [id : string] : string }; + generadoresDeSemillas: Array>; + _probaPorDefecto: number; + bolsa: Array; + bolsas: { [id: string]: Array }; + coleccion: Array; + colecciones: { [id: string]: Array }; + macros: { [id: string]: string }; // Se usan durante la generación de un mapa - _anotadosParaColeccion : Array; + _anotadosParaColeccion: Array; _anotadosParaColecciones: { [id: string]: Array }; - _semillasEncoladas: Array<{ pos: [number, number], semilla : SemillaDeCasilla }> = []; + _semillasEncoladas: Array<{ pos: [number, number], semilla: SemillaDeCasilla }> = []; _posActual: [number, number] = [0, 0]; /** @@ -233,12 +280,12 @@ class GeneradorDeMapasAleatorios implements GeneradorDeMapas { * - `coleccion`: La colección de elementos para las casillas señaladas con `*`. * - `colecciones`: Diccionario de colecciones para utilizar `$` con identificadores. */ - constructor(descripcionDeMapa : string, opciones : opcionesMapaAleatorio = {}) { + constructor(descripcionDeMapa: string, opciones: opcionesMapaAleatorio = {}) { this.configurar(opciones); this.generadoresDeSemillas = GeneradorDeMapasAleatorios.parsear(descripcionDeMapa); } - private configurar(opciones : opcionesMapaAleatorio) { + private configurar(opciones: opcionesMapaAleatorio) { this._probaPorDefecto = opciones.probaPorDefecto || 0.5; this.bolsa = opciones.bolsa || []; this.bolsas = opciones.bolsas || {}; @@ -254,13 +301,13 @@ class GeneradorDeMapasAleatorios implements GeneradorDeMapas { obtenerMapa() { // Primera pasada - var semillas : Array> = + var semillas: Array> = this.generadoresDeSemillas.map(fila => fila.map( semilla => semilla.generarSemillaDeCasilla(this) )); this.repartirElementosDeColecciones(); // Segunda pasada - var mapa : MapaEscena = semillas.map((fila, i) => fila.map( + var mapa: MapaEscena = semillas.map((fila, i) => fila.map( (semilla, j) => semilla.germinar(this, [i, j]) )); // Pasadas adicionales @@ -279,45 +326,45 @@ class GeneradorDeMapasAleatorios implements GeneradorDeMapas { } /** Se utiliza durante la obtención del mapa, para realizar pasadas extra */ - encolarSemilla(pos: [number, number], semilla : SemillaDeCasilla) { + encolarSemilla(pos: [number, number], semilla: SemillaDeCasilla) { this._semillasEncoladas.push({ pos: pos, semilla: semilla }); } - tieneAleatoriedad() : boolean { + tieneAleatoriedad(): boolean { return this.generadoresDeSemillas.some(fila => fila.some( semilla => semilla.esAleatorioPara(this) )); } - probaPorDefecto() : number { + probaPorDefecto(): number { return this._probaPorDefecto; } - - dameUnoDeLaBolsa(idBolsa? : string) : string { - var bolsa : Array = idBolsa ? this.bolsas[idBolsa] : this.bolsa; + + dameUnoDeLaBolsa(idBolsa?: string): string { + var bolsa: Array = idBolsa ? this.bolsas[idBolsa] : this.bolsa; return Math.randomFrom(bolsa); } - anotarParaLaColeccion(semilla : SemillaDeCasilla, idColeccion? : string) : void { - var dondeAnotar : Array = idColeccion ? + anotarParaLaColeccion(semilla: SemillaDeCasilla, idColeccion?: string): void { + var dondeAnotar: Array = idColeccion ? this._anotadosParaColecciones[idColeccion] : this._anotadosParaColeccion; dondeAnotar.push(semilla); } - private repartirElementosDeColecciones() : void { + private repartirElementosDeColecciones(): void { this.repartirElementos(this.coleccion, this._anotadosParaColeccion); for (const id in this.colecciones) { this.repartirElementos(this.colecciones[id], this._anotadosParaColecciones[id]); } } - private repartirElementos(coleccion : Array, semillas : Array) { + private repartirElementos(coleccion: Array, semillas: Array) { coleccion.forEach(elemento => { if (semillas.length > 0) Math.takeRandomFrom(semillas).definir(elemento); }); } - + private vaciarAnotadosParaColecciones() { this._anotadosParaColeccion.splice(0); for (const id in this._anotadosParaColecciones) { @@ -325,7 +372,7 @@ class GeneradorDeMapasAleatorios implements GeneradorDeMapas { } } - obtenerGeneradorParaMacro(idMacro : string) { + obtenerGeneradorParaMacro(idMacro: string) { return GeneradorDeMapasAleatorios.parsear(this.macros[idMacro]); } @@ -343,7 +390,7 @@ type opcionesMapaAleatorio = { bolsas?: { [id: string]: Array }, coleccion?: Array, colecciones?: { [id: string]: Array }, - macros?: { [id : string] : string }, + macros?: { [id: string]: string }, } /** @@ -357,12 +404,12 @@ interface GeneradorDeCasilla { * Las semillas son necesarias como paso intermedio porque a veces el contenido definitivo * de una casilla no puede determinarse hasta que se haya construido todo el mapa. */ - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla; + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla; /** * Indica si este generador produce resultados aleatorios al ser utilizado * con un generador de mapas en particular. */ - esAleatorioPara(generador : GeneradorDeMapasAleatorios) : boolean; + esAleatorioPara(generador: GeneradorDeMapasAleatorios): boolean; } /** @@ -370,18 +417,18 @@ interface GeneradorDeCasilla { * de un mapa. Se utiliza durante el proceso de generación de un mapa aleatorio. */ class SemillaDeCasilla { - contenido : string; - generadoresExtra : Array = []; - constructor(contenido? : string) { this.definir(contenido); } - definir(contenido? : string) { this.contenido = contenido || "-"; } - encolarGeneradoresExtra(generadores : Array) { + contenido: string; + generadoresExtra: Array = []; + constructor(contenido?: string) { this.definir(contenido); } + definir(contenido?: string) { this.contenido = contenido || "-"; } + encolarGeneradoresExtra(generadores: Array) { this.generadoresExtra = this.generadoresExtra.concat(generadores); return this; } - seraVacia() : boolean { return this.contenido == "-"; } - germinar(generador : GeneradorDeMapasAleatorios, pos : [number, number]) : string { + seraVacia(): boolean { return this.contenido == "-"; } + germinar(generador: GeneradorDeMapasAleatorios, pos: [number, number]): string { if (this.seraVacia() && this.generadoresExtra.length > 0) { - var semillaSiguiente : SemillaDeCasilla + var semillaSiguiente: SemillaDeCasilla = (this.generadoresExtra.splice(0, 1)[0].generarSemillaDeCasilla(generador)); semillaSiguiente.encolarGeneradoresExtra(this.generadoresExtra); generador.encolarSemilla(pos, semillaSiguiente); @@ -403,22 +450,21 @@ class SemillaCompuesta extends SemillaDeCasilla { } public germinar(generador: GeneradorDeMapasAleatorios, pos: [number, number]): string { - return this.semillas.map(semilla => semilla.germinar(generador,pos)).join("&") + return this.semillas.map(semilla => semilla.germinar(generador, pos)).join("&") } } /** Corresponde a identificadores de la forma `[a-zA-Z0-9]+`. */ class GeneradorDeCasillaSimple implements GeneradorDeCasilla { - constructor(private id : string) {} - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla - { return new SemillaDeCasilla(this.id); } - esAleatorioPara(generador : GeneradorDeMapasAleatorios) : boolean { return false; } + constructor(private id: string) { } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return new SemillaDeCasilla(this.id); } + esAleatorioPara(generador: GeneradorDeMapasAleatorios): boolean { return false; } } /** Corresponde a las casillas indicadas con `$` y `$(id)`. */ class GeneradorDeCasillaBolsa implements GeneradorDeCasilla { - constructor(private idBolsa? : string) {} - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla { + constructor(private idBolsa?: string) { } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return new SemillaDeCasilla(generador.dameUnoDeLaBolsa(this.idBolsa)); } // Por simplicidad se devuelve siempre true, aunque en rigor puede no ser correcto. @@ -429,35 +475,33 @@ class GeneradorDeCasillaBolsa implements GeneradorDeCasilla { /** Corresponde a las casillas indicadas con `*` y `*(id)`. */ class GeneradorDeCasillaColeccion implements GeneradorDeCasilla { - constructor(private idColeccion?: string) {} - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla { - var semilla : SemillaDeCasilla = new SemillaDeCasilla(); + constructor(private idColeccion?: string) { } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { + var semilla: SemillaDeCasilla = new SemillaDeCasilla(); generador.anotarParaLaColeccion(semilla, this.idColeccion); return semilla; } // Por simplicidad. Ver GeneradorDeCasillaBolsa.esAleatorioPara. - esAleatorioPara(generador : GeneradorDeMapasAleatorios) { return true; } + esAleatorioPara(generador: GeneradorDeMapasAleatorios) { return true; } } /** Corresponde a las casillas indicadas con `-`. */ class GeneradorDeCasillaVacia implements GeneradorDeCasilla { - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla - { return new SemillaDeCasilla('-'); } - esAleatorioPara(generador : GeneradorDeMapasAleatorios): boolean { return false; } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return new SemillaDeCasilla('-'); } + esAleatorioPara(generador: GeneradorDeMapasAleatorios): boolean { return false; } } /** Corresponde a las casillas indicadas con `_`. */ class GeneradorDeCasillaNula implements GeneradorDeCasilla { - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla - { return new SemillaDeCasilla('_'); } - esAleatorioPara(generador : GeneradorDeMapasAleatorios): boolean { return false; } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return new SemillaDeCasilla('_'); } + esAleatorioPara(generador: GeneradorDeMapasAleatorios): boolean { return false; } } /** Corresponde al modificador `?` (recursivo). */ class GeneradorDeCasillaMaybe implements GeneradorDeCasilla { - constructor(private generadorInterno : GeneradorDeCasilla, private proba? : number) {} - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla { - var proba : number = this.proba || generador.probaPorDefecto(); + constructor(private generadorInterno: GeneradorDeCasilla, private proba?: number) { } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { + var proba: number = this.proba || generador.probaPorDefecto(); if (Math.random() < proba) return this.generadorInterno.generarSemillaDeCasilla(generador); else @@ -465,13 +509,13 @@ class GeneradorDeCasillaMaybe implements GeneradorDeCasilla { } esAleatorioPara(generador): boolean { var proba: number = this.proba || generador.probaPorDefecto(); - return 0 < proba && proba < 1; + return 0 < proba && proba < 1; } } class GeneradorDeCasillaAnd implements GeneradorDeCasilla { - constructor(private generador1 : GeneradorDeCasilla, private generador2: GeneradorDeCasilla) {} + constructor(private generador1: GeneradorDeCasilla, private generador2: GeneradorDeCasilla) { } - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla { + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { const semilla1: SemillaDeCasilla = this.generador1.generarSemillaDeCasilla(generador) const semilla2: SemillaDeCasilla = this.generador2.generarSemillaDeCasilla(generador) return new SemillaCompuesta([semilla1, semilla2]) @@ -484,19 +528,19 @@ class GeneradorDeCasillaAnd implements GeneradorDeCasilla { /** Corresponde al modificador `|` (recursivo). */ class GeneradorDeCasillaOpcion implements GeneradorDeCasilla { - constructor(private opciones : Array) {} - generarSemillaDeCasilla(generador : GeneradorDeMapasAleatorios) : SemillaDeCasilla { + constructor(private opciones: Array) { } + generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return Math.randomFrom(this.opciones) .generarSemillaDeCasilla(generador); } - esAleatorioPara(generador : GeneradorDeMapasAleatorios) { + esAleatorioPara(generador: GeneradorDeMapasAleatorios) { return this.opciones.length > 1; } } /** Corresponde al modificador `>` (recursivo). */ class GeneradorDeCasillaSucesion implements GeneradorDeCasilla { - constructor(private opciones: Array) {} + constructor(private opciones: Array) { } generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return this.opciones[0].generarSemillaDeCasilla(generador) .encolarGeneradoresExtra(this.opciones.splice(1)); @@ -507,11 +551,11 @@ class GeneradorDeCasillaSucesion implements GeneradorDeCasilla { } class GeneradorDeCasillaMacro implements GeneradorDeCasilla { - constructor(private id : string) {} + constructor(private id: string) { } generarSemillaDeCasilla(generador: GeneradorDeMapasAleatorios): SemillaDeCasilla { return generador.obtenerGeneradorParaMacro(this.id).generarSemillaDeCasilla(generador); } - esAleatorioPara(generador : GeneradorDeMapasAleatorios) { + esAleatorioPara(generador: GeneradorDeMapasAleatorios) { return generador.obtenerGeneradorParaMacro(this.id).esAleatorioPara(generador); } } diff --git a/src/escenas/libroPrimaria/EscenaDuba.ts b/src/escenas/libroPrimaria/EscenaDuba.ts index 9472c4e..cb12b73 100644 --- a/src/escenas/libroPrimaria/EscenaDuba.ts +++ b/src/escenas/libroPrimaria/EscenaDuba.ts @@ -17,18 +17,13 @@ class EscenaDuba extends EscenaDesdeMapa { return 'fondo.duba.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('duba').concat(Obstaculo.imagenesPara('duba')); - } //TODO: Usar flatMap (lodash) + static nombreAutomata(): string { + return 'duba' + } constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); - - if (posFinal) { - this.xFinal = posFinal[0]; - this.yFinal = posFinal[1]; - } + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } ajustarGraficos() { @@ -65,8 +60,7 @@ class EscenaDuba extends EscenaDesdeMapa { } estaResueltoElProblema(): boolean { - return (this.contarActoresConEtiqueta("Churrasco")) === 0 && - (this.xFinal === undefined || this.automata.casillaActual().sos(this.xFinal, this.yFinal)); + return super.estaResueltoElProblema() && this.noHay('Churrasco') } archivoFondo() { diff --git a/src/escenas/libroPrimaria/EscenaLita.ts b/src/escenas/libroPrimaria/EscenaLita.ts index a0ffa14..356a38f 100644 --- a/src/escenas/libroPrimaria/EscenaLita.ts +++ b/src/escenas/libroPrimaria/EscenaLita.ts @@ -17,18 +17,13 @@ class EscenaLita extends EscenaDesdeMapa { return 'fondo.lita.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('lita').concat(Obstaculo.imagenesPara('lita')); - } //TODO: Usar flatMap (lodash) + static nombreAutomata(): string { + return 'lita' + } constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); - - if (posFinal) { - this.xFinal = posFinal[0]; - this.yFinal = posFinal[1]; - } + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } iniciar() { @@ -62,11 +57,7 @@ class EscenaLita extends EscenaDesdeMapa { } estaResueltoElProblema(): boolean { - // Además de verificar que Lita haya cumplido el objetivo de la escena, - // en el caso de que se haya proporcionado una posición final, - // queremos verificar que Lita esté ahí. - return super.estaResueltoElProblema() && - (this.xFinal === undefined || this.automata.casillaActual().sos(this.xFinal, this.yFinal)); + return super.estaResueltoElProblema() && this.estado.soyAceptacion() } ajustarGraficos() { diff --git a/src/escenas/libroPrimaria/EscenaManic.ts b/src/escenas/libroPrimaria/EscenaManic.ts index a70e61a..3344ff6 100644 --- a/src/escenas/libroPrimaria/EscenaManic.ts +++ b/src/escenas/libroPrimaria/EscenaManic.ts @@ -14,17 +14,13 @@ class EscenaManic extends EscenaDesdeMapa { return 'fondo.manic.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('manic').concat(Obstaculo.imagenesPara('manic')); + static nombreAutomata(): string { + return 'manic' } constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); - if (posFinal) { - this.xFinal = posFinal[0]; - this.yFinal = posFinal[1]; - } + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } ajustarGraficos() { @@ -68,10 +64,6 @@ class EscenaManic extends EscenaDesdeMapa { return new Obstaculo(archivosObstaculos, (fila + 1) + (fila + 1) * (columna + 1)); } - todosLosActoresCumplen(actor, estado) { - return this.obtenerActoresConEtiqueta(actor).every(o => o.nombreAnimacionActual() == estado); - } - telescopiosArreglados(): boolean { return this.todosLosActoresCumplen("Telescopio", "arreglado") } @@ -88,17 +80,8 @@ class EscenaManic extends EscenaDesdeMapa { return this.observados(actor) || this.noHay(actor) } - - noHay(actor): boolean { - return this.contarActoresConEtiqueta(actor) == 0 - } - - estaEnPosicionFinalSiLaTiene(): boolean { - return this.xFinal === undefined || this.automata.casillaActual().sos(this.yFinal, this.xFinal); - } - estaResueltoElProblema(): boolean { - return this.estaEnPosicionFinalSiLaTiene() && this.telescopioResuelto() && this.observacionResuelta("Estrella") && this.observacionResuelta("Planeta"); + return super.estaResueltoElProblema() && this.telescopioResuelto() && this.observacionResuelta("Estrella") && this.observacionResuelta("Planeta"); } archivoFondo() { diff --git a/src/escenas/libroPrimaria/EscenaToto.ts b/src/escenas/libroPrimaria/EscenaToto.ts index ff20a4c..7cadc74 100644 --- a/src/escenas/libroPrimaria/EscenaToto.ts +++ b/src/escenas/libroPrimaria/EscenaToto.ts @@ -33,6 +33,10 @@ abstract class EscenaToto extends EscenaDesdeMapa { return [] } + static nombreAutomata(): string { + return 'toto' + } + /** * @param mapaEscena Matriz bidimensional de strings a partir de la cual se crea la escena. * Toto se representa con una 'A' mayúscula. Las letras a leer van en minúscula diff --git a/src/escenas/libroPrimaria/EscenaYvoty.ts b/src/escenas/libroPrimaria/EscenaYvoty.ts index 9bacb12..adb7050 100644 --- a/src/escenas/libroPrimaria/EscenaYvoty.ts +++ b/src/escenas/libroPrimaria/EscenaYvoty.ts @@ -12,13 +12,13 @@ class EscenaYvoty extends EscenaDesdeMapa { return 'fondo.yvoty.png'; } - static imagenesAdicionales(): string[] { - return Casilla.imagenesPara('yvoty').concat(Obstaculo.imagenesPara('yvoty')); + static nombreAutomata(): string { + return 'yvoty' } - constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio) { + constructor(especificacion: Spec, opciones?: opcionesMapaAleatorio, posFinal?: [number, number]) { super(); - this.initDesdeUnaOVariasDescripciones(especificacion, opciones); + this.initDesdeUnaOVariasDescripciones(especificacion, opciones, posFinal); } ajustarGraficos() { @@ -86,7 +86,7 @@ class EscenaYvoty extends EscenaDesdeMapa { } estaResueltoElProblema(): boolean { - return this.luciernagasDespiertas() && this.celularResuelto() && this.noHay("Mariposa") && this.computadorasPrendidas() + return super.estaResueltoElProblema() && this.luciernagasDespiertas() && this.celularResuelto() && this.noHay("Mariposa") && this.computadorasPrendidas() } archivoFondo() {