Imaginen una fila de 9 casilleros. En alguno de ellos se ubican el pacman y un fantasma, no necesariamente en el mismo. Esta IA intenta que el fantasma quede en el mismo casillero que el pacman, pero:
- Le digo muy poco sobre cómo hacerlo, lo aprende.
- Sólo puede moverse 1 casillero como máximo, cada vez.
Pseudo código:
- El criterio actual es: Sólo juzgar situaciones que logran el objetivo.
- Se plantea una situación que aún no haya resuelto.
- Prueba en dicha situación una acción que no haya juzgado aún con el criterio actual.
- Juzga la acción en base al resultado. Si es bueno, genera un archivo cuyo nombre marca cual era la situación, y el contenido del archivo es la acción que realizó y el valor 0.
- Repite el proceso desde el punto 2. Si ya probó todas las acciones en todas las situaciones, cambia el criterio de los juicios:
Una vez realizada la acción, carga info sobre la nueva situación que ha provocado. Si no se puede cargar, vuelve al punto 3. Sino, y si la info cargada contiene el valor 0, crea un archivo sobre la situación anterior, graba la acción y el valor 1.
Así sigue hasta juzgar todo. El valor va aumentando. 0 significa que en este mismo turno ya puede quedar en la mismo casillero que el pacman. 1 significa que podrá en el próximo turno. Well, entre mayor peor está.
--------------------------------------------------------------------------------------------------------
Código (incompleto):
Código :
Frame 1: // Objeto Mem se presenta. Mem.PacX = 1; Mem.GhostX = 0; Frame 2: // Nueva situación. Mem.Actn = -2; Mem.GhostX = Mem.GhostX+1; if (Mem.GhostX == 10) { Mem.GhostX = 1; Mem.PacX = Mem.PacX+1; if (Mem.PacX == 10) { Mem.Eva = 0; Mem.PacX = 1; Mem.GhostX = 0; gotoAndPlay (12); } } Frame 3: // Nuevo act. Mem.Actn = Mem.Actn+1; if (Mem.Actn == 2) { gotoAndPlay (2); } else { // Aplicar Act (Ghost). Mem.GhostXNew = Mem.GhostX + Mem.Actn; // Juzgar resultado, guardar si es bueno. if (Mem.GhostXNew == Mem.PacX) { BestActn = Mem.Actn; BestAct = 0; fscommand ("save", "S"+Mem.PacX+"_"+Mem.GhostX+".txt"); gotoAndPlay (5); } } Frame 4: gotoAndPlay (3); Frame 5: // Objeto Mem2 se presenta. Frame 6: // Preparando verificación del save. Mem.Cargas = 0; Mem2.BestActn = -1; Mem2.BestAct = -1; Frame 7: Mem.Comp = 0; // Cargar para confirmar. Mem.Cargas = Mem.Cargas+1; loadVariables ("S"+Mem.PacX+"_"+Mem.GhostX+".txt", "Mem2"); Frame 8: // Nada. Frame 9: // Convertir a números (necesario para verificar load). Mem2.BestActn = Number (Mem2.BestActn)*1; Mem2.BestAct = Number (Mem2.BestAct)*1; Mem.Verif = 1; // Compara variables. Mem.Comp = Mem.Comp+1; if (BestActn != Mem2.BestActn) { Mem.Verif = 0; } else if (BestAct != Mem2.BestAct) { Mem.Verif = 0; } Frame 10: // Reintentar, reload, fin, o reiniciar según el caso. if (Mem.Comp == 10) { if (Mem.Cargas == 3) { // fin fscommand ("save", "30 fallas en S"+Mem.PacX+"_"+Mem.GhostX+".txt"); fscommand ("quit"); } else { // reload gotoAndPlay (7); } } else if (Mem.Verif != 1) { // reintentar gotoAndPlay (9); } // reiniciar Frame 11: // Objeto Mem2 se retira. gotoAndPlay (2); Frame 12: // Nueva sit. Mem.Actn = -2; Mem.GhostX = Mem.GhostX+1; if (Mem.GhostX == 10) { Mem.GhostX = 1; Mem.PacX = Mem.PacX+1; if (Mem.PacX == 10) { Mem.Eva = Mem.Eva+1; Mem.PacX = 1; Mem.GhostX = 1; } } Frame 13: // Nuevo act. Mem.Actn = Mem.Actn+1; if (Mem.Actn == 2) { gotoAndPlay (12); } else { // Aplicar Act (Ghost). Mem.GhostXNew = Mem.GhostX + Mem.Actn; // Cargar nueva Sit para ver su BestAct. }
Hay cosas que posiblemente no entiendan, pero que no es importante que lo hagan. A lo que deben prestar atención es a:
- Cuando llega al frame 12 ya generó los archivos e info sobre las situaciones en que es posible lograr el objetivo en 1 movimiento. PERO en el frame 12 las va a volver a analizar, lo cual es una pérdida de tiempo, quiero evitar que lo haga.
Lo explicaré mejor, con un ejemplo.
Cuando llega al frame 12, ya hay un archivo que se llama S1_1.txt cuyo contenido es m´ças o menos así:
BestActn=0
BestAct=0
Significa que en el archivo *pacman está en el casillero 1*_*el fantasma está en el casillero 1*.txt ya está marcado, que en la situación que describe, conviene realizar el movimiento *BestActn* y tiene un valor de 0. O sea, es una situación en la que el pacman y fantasma están en el mismo casillero, ergo conviene moverse 0 casilleros, eso marca BestActn, y como el objetivo se logra en este mismo turno, BestAct marca 0.
Ya está.
No obstante, en el frame 12 se plantea otra vez esa situación, para probar otra vez acciones, pero eso no tiene sentido.
¿Qué puedo hacer para que no se pierda tiempo? O mejor dicho, en definitiva, cómo optimizar ese aprendizaje de la IA.
Puedo hacer que cargue la info de la situación y si BestAct es menor o igual que el criterio (Mem.Eva) entonces no prueba acciones en ella, pero ya eso de cargar es bastante tiempo...
Puedo generar una lista de las que debe analizar. ¿No haría que el programa sea más pesado? La lista se alargaría a medida que intente resolver situaciones de otro estilo, más complejas. Y si la lista estuviera en archivos externos entonces tendría que hacer 2 cargas cada vez, en vez de 1.
...
Quisiera empezar a usar tablas en vez de archivos txt, o arreglos.
No uso arreglos porque hace tiempo cuando no tenía Internet intenté guardarlos y cargarlos tal y como lo hago con variables comunes -ver el código- y no funcionaba. Así que no quise perder más tiempo y energía con ellas.
Y usar tablas no sé, leí algo sobre php o no sé qué hace tiempo, y no entendí mucho.
Creo que necesito un nuevo programa, SENCILLO -como Flash 5, he probado el 8 y hacer un save me pareció mucho más complicado-, pero que me permita hacer mejor lo que quiero hacer.
Muchas gracias.