You are on page 1of 36

UNIVERSIDAD DE LA REPÚBLICA

FACULTAD DE INGENIERÍA
INSTITUTO DE COMPUTACIÓN

ORIENTACIÓN A
OBJETOS EN PROLOG
PROGRAMACIÓN LÓGICA

DANIEL PEROVICH
GUILLERMO MONCECCHI

JULIO, 2002
Orientación a Objetos en Prolog
PROGRAMACIÓN LÓGICA

INTRODUCCIÓN ________________________________________________ 3

ORIENTACIÓN A OBJETOS EN SICSTUS PROLOG ___________________ 4

Prolog objects ________________________________________________________________________ 4

Sintaxis _____________________________________________________________________________ 4
Declaración de Objetos _______________________________________________________________ 4
Declaración de Métodos ______________________________________________________________ 5
Atributos __________________________________________________________________________ 6
Ejemplo de Declaración ______________________________________________________________ 6

Herencia y Jerarquías de Objetos _______________________________________________________ 8


Self, Sub, Super _____________________________________________________________________ 9
Objetos Genéricos ___________________________________________________________________ 9

Envio de Mensajes ____________________________________________________________________ 9

OBJETOS ESTÁTICOS Y DINÁMICOS______________________________ 13

Objetos Estáticos ____________________________________________________________________ 13

Objetos Dinámicos ___________________________________________________________________ 13


Métodos Dinámicos_________________________________________________________________ 13
Creación Dinámica de Objetos ________________________________________________________ 14
Creación Dinámica de Instancias ______________________________________________________ 14

BIBLIOTECA DE SOPORTE OO EN PROLOG (SICSTUS) ______________ 16


Métodos Universales ________________________________________________________________ 16
Metodos inlined ____________________________________________________________________ 16
Prototipo: object ___________________________________________________________________ 16
Prototipo: Utility ___________________________________________________________________ 17

APÉNDICE 1: LISTAS, CONJUNTOS, ÁRBOLES BINARIOS ____________ 19

APÉNDICE 2: OOTUTLOG _______________________________________ 21

Esquema de trabajo __________________________________________________________________ 21

Análisis de requerimientos ____________________________________________________________ 21

Análisis orientado a objetos ___________________________________________________________ 22

Diseño orientado a objetos ____________________________________________________________ 23


ORIENTACIÓN A OBJETOS EN PROLOG

Implementación utilizando C# _________________________________________________________ 28

Implementación utilizando Prolog. _____________________________________________________ 29


Predicados del juego ________________________________________________________________ 29
Predicados de la partida______________________________________________________________ 29
Predicados de una vuelta _____________________________________________________________ 30
Predicados de un turno ______________________________________________________________ 30
Estrategia _________________________________________________________________________ 30

Implementación utilizado Prolog Objects ________________________________________________ 31


Generalidades _____________________________________________________________________ 31
Modo de Uso ______________________________________________________________________ 33

CONCLUSIONES _______________________________________________ 34

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
2
ORIENTACIÓN A OBJETOS EN PROLOG

I N TRO D U C C I Ó N

La posibilidad de incorporar elementos del paradigma de orientación a objetos en la


programación lógica parece, a priori, interesante, dado que permitiría sumar lo mejor de ambos
mundos. Los lenguajes de programación lógica han tenido siempre como ventaja el permitir enfocar
la atención del programador en el problema a resolver y en el diseño de la solución, más que en la
mecánica de la misma. La incorpororación de orientación a objetos ayudaría en la reutilización del
código, ocultamiento de información y además permitiría realizar un diseño más claro de las
soluciones.

En este trabajo se estudia una aproximación al tema de la orientación a objetos en Prolog, la


realizada por el módulo Prolog Objects de SICStus Prolog. Se muestran las ideas principales del
módulo, su sintaxis y funcionamiento, para presentar finalmente algunos ejemplos de diseño
utilizando el paradigma.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
3
ORIENTACIÓN A OBJETOS EN PROLOG

O R I E N TA C I Ó N A O B J E TO S E N S I C S T U S P RO L O G

PROLOG OBJECTS

Prolog Objects es una extensión al SICStus prolog, basada en la noción de prototipos. Un


prototipo es un objeto que representa el comportamiento típico de un concepto, y que puede ser
utilizado directamente, o para construir otros objetos que comparten sus mismas características.

Los mecanismos básicos para compartir datos en Prolog Objects son la herencia y la delegación. La
herencia permite definir un objeto tomando como base las características de otro ya existente, y para
su implementación se utiliza el mecanismo de importación del sistema de módulos de SICStus. La
delegación permite a un objeto enviar un mensaje a otro para invocar a un método definido por el
receptor pero interpretado en el contexto del objeto que lo envía.

En Prolog Objects, los objetos son, conceptualmente, una colección de predicados Prolog
(métodos), a los que se les asigna un nombre. Además pueden tener atributos modificables a través
de métodos predefinidos. Por ser Prolog, los métodos pueden ser definidos no determinísticamente y
puede haber respuestas alternativas a través del mecanismo de backtracking.

Los objetos pueden definirse estáticamente en un archivo, o ser creados durante la ejecución.
Vale notar que Prolog Objects maneja orientación a objetos – y no a clases, como por ejemplo lo
hacen Java, C++, u otras versiones de Prolog, como Trinc Prolog. Esto es, un objeto puede heredar
de otro, pero no existe el concepto de “clase”, como una definición, aunque (como se verá más
adelante), las instancias podrían verse como objetos de una clase dada por el objeto a partir del cual
se construyen.

Existe un proto-objeto inicial object, desde el cual otros objetos pueden crearse directa o
indirectamente.

Prolog Objects es una biblioteca más de SICStus, por lo que, para que esté disponible, debe
importarse el módulo:

?- use_module(library(objects)).

SINTAXIS

DECLARACIÓN DE OBJETOS

La forma de declarar un objeto en Prolog Objects es la siguiente:

obj_ident :: {

sentence_1 &

sentence_2 &

...

sentence_n
}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
4
ORIENTACIÓN A OBJETOS EN PROLOG

Donde obj_ident es un átomo o un término f(v1,…vn), donde v1,…,vn son diferentes variables.
El cuerpo del objeto consiste en un conjunto de sentencias (posiblemente vacío), las cuales pueden
ser:

 Un método directiva, que se ejecuta cuando el objeto es creado (por ejemplo:


:- : use_module(library(lists))

 Una cláusula de método, que tiene una sintaxis similar a las cláusulas comunes de Prolog,
pero que, en lugar de llamadas a predicados, tiene llamadas a métodos. Un método es un
conjunto de cláusulas de método, con el mismo functor. Tambien es posible llamar a
objetivos Prolog comunes, prefijándolos con ‘:’

Ejemplo:

func_lista :: {

:- use_module(library(lists, [append/3, member/2]) &

length([], 0) &

length([_|L], N) :-

:: length(L, N1),

:(N is N1 + 1)

}.

Declara un objeto func_lista, el cual contiene el método length, y que utiliza las funciones
append y member de la biblioteca de listas.

DECLARACIÓN DE MÉTODOS

Los cláusulas de método se declaran de forma similar a las cláusulas Prolog. Por lo tanto pueden
ser hechos o cláusulas con cuerpo no vacío. Los objetivos en el cuerpo conservan las estructuras de
control normales en Prolog (conjunción, disjunción, cut, negación, unificación).

Los átomos en el cuerpo de una cláusula de método pueden ser alguno de los siguientes:

 : goal → llama al predicado goal en el módulo origen

 m : goal → llama al predicado goal en el módulo m

 goal → envía el mensaje goal al objeto Self

 :: goal → envía el mensaje goal a un método que puede estar definido localmente
o heredado

 <: goal → delega el mensaje goal a un método que puede estar definido
localmente o heredado

 object <: goal → delega el mensaje goal al objeto object

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
5
ORIENTACIÓN A OBJETOS EN PROLOG

En el punto “Envío de mensajes” de este documento se explica la diferencia entre envío de


mensajes y delegación.

ATRIBUTOS

Existe en Prolog Object una forma estándar de definir atributos de un objeto. Para esto se utiliza
el predicado attributes. Los atributos definidos pueden ser leídos y modificados a través de los
métodos get/1 y set/1.

EJEMPLO DE DECLARACIÓN

A continuación se muestra como ejemplo la definición de un objeto lista, el cual tiene como
único atributo una lista Prolog, y como único método a sin_ultimo/1 y sin_ultimo/0, que devuelve la
lista sin el último elemento. Accesoriamente, se define el objeto list_lib, que es una biblioteca de
funciones genéricas sobre listas, que será utilizada por el objeto lista. En este ejemplo puede verse la
sobrecarga de métodos y el uso de los métodos get y set para trabajar con los atributos.

:- use_module(library(lists),[append/3,member/2]).
:- use_module(library(objects)).

list_lib :: {

%% sin_ultimo(+L, ?S)

%% S es la lista que se obtiene de suprimir el último elemento de L

sin_ultimo([X], []) &

sin_ultimo([X|R], [X|Y]) :-

:: sin_ultimo(R, Y)

}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
6
ORIENTACIÓN A OBJETOS EN PROLOG

list :: {

%% Hereda de 'object'

super(object) &

%% Tiene una lista como atributo

attributes([content([])]) &

%% sin_ultimo(-S).

%% Si recibe una variable, devuelve en ella la lista del objeto sin el

%% último elemento.

%% Utiliza el método sin_ultimo de la biblioteca

sin_ultimo(S) :-

<: get(content(L)),

list_lib :: sin_ultimo(L, S)

&

%% Remueve el ultimo elemento de la lista implicita

%% Utiliza el método sin_ultimo de la biblioteca

sin_ultimo :-

<: get(content(L)),

list_lib :: sin_ultimo(L, S),

<: set(content(S))

}.

Luego de consultado el fuente, veamos el funcionamiento.

Método de la biblioteca:

| ?- list_lib :: sin_ultimo([1,2,3,4], X).

X = [1,2,3] ? ;

no

Funcionamiento del objeto list:

| ?- list :: sin_ultimo.

no

| ?- list :: set(content([a,b,c])).

yes

| ?- list :: get(content(X)).

X = [a,b,c] ? ;

no

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
7
ORIENTACIÓN A OBJETOS EN PROLOG

| ?- list :: sin_ultimo(X).

X = [a,b] ? ;

no

| ?- list :: sin_ultimo.

yes

| ?- list :: get(content(X)).

X = [a,b] ? ;

HERENCIA Y JERARQUÍAS DE OBJETOS

Por medio del método super/2 es posible declarar los super-objetos de un objeto dado. Los
objetos declarados por super/2 son los objetos inmediatos desde los cuales se hereda un método si
éste no está definido dentro del objeto (se utiliza un mecanismo de herencia por overriding). La
sintaxis es super(Super, NotInherited). El primer argumento es el objeto a declarar como super-objeto, y
el segundo es una lista con los métodos no heredados. Todas las llamadas a super/1 se transforman a
super(Super, []).

Un objeto puede heredar de más de un objeto (herencia múltiple), y esto se logra utilizando
varias cláusulas super en el objeto. En caso de conflictos (esto es, hay métodos definidos en más de un
super-objeto) predominan los métodos del objeto definido primero como super-objeto.

Ejemplo: definimos los siguientes objetos

obj1 :: {

super(object) &

m(1) &
p(2)
}.

obj2 :: {

super(object) &

m(2)&

q(3)

}.

obj3 :: {

super(obj2) &

super(obj1)

}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
8
ORIENTACIÓN A OBJETOS EN PROLOG

Y veamos como se heredan los métodos y como se definen las prioridades cuando existe más de
un super-objeto.

?- obj3 :: p(X).
X=2;

no

?- obj3 :: q(X).

X=3;

no

?- obj3 :: m(X).

X=2;

no

SELF, SUB, SUPER

Existen tres métodos definidos en el objeto inicial object (del cual, por ello mismo, todo objeto
debiera heredar), que retornan los padres, los hijos y el propio objeto. Estos métodos son,
respectivamente super/1, sub/1 y self/0.

También es posible enviar o delegar mensajes al supeobjeto, a través de la clave super. La


sintaxis para su uso es super :: method, o super <: method.

OBJETOS GENÉRICOS

Existen dos objetos genéricos en Prolog Objects: object (que provee métodos básicos que están
disponibles a todos los objetos por medio de la delegación, tales como super/1,sub/1,object/1) y util
(que provee métodos adicionales como subs/1,supers/1,o ancestors/2). El detalle de las funcionalidades
provistas, puede verse en el punto “Biblioteca de Soporte a Objetos” de este documento.

ENVIO DE MENSAJES

En Prolog Objects cada método se ejecuta en el contexto de un objeto. Este objeto puede o no
ser el objeto estático donde se declara el método. Qué atributos acceder y cuáles métodos utilizar, se
determina dinámicamente según el contexto (dynamic binding). Cuando se envía un mensaje a un
objeto, el método se ejecuta en el contexto del objeto destino. En cambio, si el método se delega,
éste se ejecuta en el contexto del objeto que lo envía.

La sintaxis para el envío y la delegación es la siguiente:

object :: message → envía el mensaje a object, poniendo como Self del receptor al receptor. Si se
omite object, el receptor es el objeto donde aparece textualmente el objetivo.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
9
ORIENTACIÓN A OBJETOS EN PROLOG

object <: message → envía el mensaje a object, seteando Self del receptor a Self del que envía. Si se
omite object, el receptor es el objeto en el cual aparece textualmente el objetivo.

Por ejemplo, si definimos los objetos obj y v de la siguiente forma:

:- use_module(library(objects)).

% El objeto obj tiene valor 1

obj :: {

attributes([valor(1)]) &

m :- get(valor(X)), :write('Metodo m en obj,valor '), :write(X), :nl

}.

% El objeto v tien valor 2. Hereda de object para tener disponible

% el metodo new.
v :: {

attributes([valor(2)]) &

super(object) &

p :-

obj :: m,

:: m,

obj <: m,

<: m

&

m :- get(valor(X)), :write('Metodo m en v, valor '), :write(X), :nl

}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
10
ORIENTACIÓN A OBJETOS EN PROLOG

Si creamos luego dinámicamente un objeto v2 basado en v, y le enviamos el mensaje p, el


resultado será el siguiente. La creación dinámica de v2 se hace mediante el método new. El manejo
de objetos estáticos y dinámicos se verá más adelante.

| ?- v :: new(v2).

yes

| ?- v2 :: set(valor(3)).

yes

| ?- v2 :: p.

Metodo m en obj, valor 1

Metodo m en v, valor 2

Metodo m en obj, valor 3

Metodo m en v, valor 3
yes

En el primer caso (obj :: m), se envía el mensaje m al objeto obj, utilizando al receptor (el propio
obj) como contexto. En el segundo caso v2 envía el mensaje a su superobjeto v (donde está definido el
método), utilizando además su contexto. En los casos 3 y 4, los mensajes se siguen enviando a obj y v,
pero (como se utiliza delegación) el contexto es v2, y es por ello que el valor del atributo valor es 3.

Se presenta a continuación un ejemplo que indica como el utilizar envío de mensaje en lugar de
delegación puede provocar resultados no esperados. Considere para este ejemplo las definiciones en
el ejemplo de lista.

list2 :: { super(list) }.

| ?- list :: sin_ultimo(X).

no

| ?- list :: set(content([1,2,3])).
yes
| ?- list2 :: set(content([a,b,c])).

yes

| ?- list :: sin_ultimo(X).

X = [1,2] ? ;

no

| ?- list2 :: sin_ultimo(X).

X = [a,b] ? ;

no

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
11
ORIENTACIÓN A OBJETOS EN PROLOG

Si modificamos la definición de sin_ultimo a:

sin_ultimo(S) :-
:: get(content(L)),

list_lib :: sin_ultimo(L, S)

&

el resultado es diferente:

| ?- list :: sin_ultimo(X).

no

| ?- list :: set(content([1,2,3])).

yes

| ?- list2 :: set(content([a,b,c])).

yes

| ?- list :: sin_ultimo(X).

X = [1,2] ? ;

no

| ?- list2 :: sin_ultimo(X).

X = [1,2] ? ;

no

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
12
ORIENTACIÓN A OBJETOS EN PROLOG

O B J E TO S E S T Á T I C O S Y D I N Á M I C O S

OBJETOS ESTÁTICOS

Los objetos vistos hasta el momento son estáticos: son declarados y compilados y no pueden
cambiarse durante la ejecución.

OBJETOS DINÁMICOS

Los objetos pueden declararse como dinámicos, y de esta forma es posible modificar sus
métodos dinámicamente. Para declarar un objeto como dinámico, se utiliza la palabra clave dynamic.

obj_din :: {

dynamic &

...

}.

MÉTODOS DINÁMICOS

También es posible declarar como dinámicos sólo a algunos métodos dentro de un objeto:

objeto::{

dynamic F/N&

...

Luego de definidos como dinámicos, la forma de modificarlos es enviándoles los mensajes assert
y retract, los cuales se utilizan de la misma forma que las correspondientes cláusulas Prolog. El
comportamiento dinámico de un objeto se conserva con la herencia, esto es, los métodos declarados
como dinámicos en el padre serán copiados en el objeto y su comportamiento dinámico se
preservará.

Ejemplo:
grupo :: {

super(object)&

dynamic integrante/1&

integrante(juan)

}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
13
ORIENTACIÓN A OBJETOS EN PROLOG

Modificación dinámica del método integrante:

| ?- grupo :: asserta(integrante(pedro)).
yes

| ?- grupo :: asserta(integrante(jose)).

yes

| ?- grupo :: integrante(X).

X = jose ? ;

X = pedro ? ;

X = juan ? ;
no

CREACIÓN DINÁMICA DE OBJETOS

Con el operador new, es posible declarar dinámicamente nuevos objetos basados en otro. El
nuevo objeto tendrá como super objeto a aquel que se le haya invocado new. A su vez, los objetos así
creados pueden servir como super objeto a otros objetos. Si se crea un objeto dinámicamente a partir
de otro, no se heredan los atributos del objeto original.

Ejemplo:

list :: new(list3).

list3 :: new(list4).

CREACIÓN DINÁMICA DE INSTANCIAS

Las instancias son objetos con capacidades restringidas. Se crean a partir de un objeto, obtienen
una copia de los atributos y no pueden ser utilizados como super objeto para otros objetos., aunque
sí pueden crearse nuevas instancias a partir de ellas. La utilización de este mecanismo se asemeja a la
instanciación a partir de una clase en los lenguajes orientados a objetos tradicionales. Se crean nuevas
instancias con el predicado instante la cual recibe como parámetro el nombre de la instancia.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
14
ORIENTACIÓN A OBJETOS EN PROLOG

Ejemplo:
| ?- list :: instance(lista5).
yes
| ?- lista5 :: instance(lista6).
yes
| ?- lista6 :: new(lista7).
! Existence error in user:(::)/2
! object lista6 does not exist
! goal: lista6 :: new(lista7)
| ?- lista6 :: instance(lista7).
yes
| ?- lista7 :: get(content(X)).
X = [1,2,3] ? ;
no

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
15
ORIENTACIÓN A OBJETOS EN PROLOG

B I B L I O TE C A D E S O P O RT E O O E N P RO L O G ( S I C S TU S )

MÉTODOS UNIVERSALES

Estos métodos están definidos localmente para todo objeto de Prolog Objects:

super(?Object, ?NotInheritList)

Object es un superobject de Self. super(Object) se traduce a super(Object, [])

attributes(+Attributes)

Attributes es una lista de términos compuestos que especifican los atributos locales de Self y sus
valores iniciales.

METODOS INLINED

Estos métodos se compilan inline (las llamadas se reemplazan por definiciones). Esto implica que
tienen semántica fija y no pueden ser redefinidos.

self(?Self)

Unifica Self con “self”

get(+Attribute)

Obtiene los valores de los atributos definidos con el functor de Attribute. Los valores son
unificados con los argumentos de Attribute.

set(+Attribute)

Modifica los valores de los atributos definidos con el functor de Attribute. Los valores son
tomados de los argumentos de Attribute.

PROTOTIPO: OBJECT

El objeto object provee métodos disponibles para todos los otros objetos por delegación.
Algunos de ellos son1:

super(?Object)
Object es padre de Self.

1 Para una referencia completa, véase el manual de referencia de SICStus Prolog

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
16
ORIENTACIÓN A OBJETOS EN PROLOG

sub(?Object)
Object es padre de Self.

self(?Self)
Unifica Self con “self”.

object(?Object)
Uno de los objetos definidos en el sistema es Object

static
Self es un objeto estático

dynamic
Self es un objeto dinámico

dynamic ?Nombre/?Aridad
?Nombre/?Aridad es un método dinámico de Self.

static ?Nombre/?Aridad
?Nombre/?Aridad es un método estático de Self.

new(?Object)
Crea un nuevo objeto dinámico Object del cual Self será el prototipo. Object puede ser un
término compuesto, un átomo o una variable. En el último caso, el método genera un nombre
único para Object.

instance(?Instance)
Crea una nueva instancia Instance, de la cual Self será clase. Instance puede ser un término
compuesto, un átomo o una variable. En el último caso, el método genera un nombre único para
Instance.

has_instance(?Instance)
Self tiene la instancia Instante

assert(+Fact)
Agrega un nuevo Fact en Self. Si Self es estático, el nombre y la aridad de Fact deben ser
declarados como dinámicos.

PROTOTIPO: UTILITY

El objeto utility provee métodos adicionales. Algunos de sus métodos son:

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
17
ORIENTACIÓN A OBJETOS EN PROLOG

subs(?Objects)
Devuelve todo los hijos de Self

supers(?Objects)
Devuelve todo los padres de Self

objects(?Objects)
Devuelve una lista de todos los objetos

methods(?Methods)
Devuelve una lista de todos los métodos de Self

ancestor(?Object)
Uno de los ancestros de Self es Object

and_cast(+Objects,?Message)
Envía el mismo mensaje a todos los objetos en la lista Objects

or_cast(+Objects,?Message)
Envía el mismo mensaje a uno de los objetos de Objects, haciendo backtracking entre los
diferentes objetos.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
18
ORIENTACIÓN A OBJETOS EN PROLOG

A P É N D I C E 1 : L I S TA S , C O N J U N TO S , Á R B O L E S B I NA R I O S

Como primer ejemplo de uso, se presenta la implementación utilizando Prolog Objects, de


diferentes predicados sobre listas, conjuntos y árboles.

El esquema general es el siguiente: se define un objeto list_lib, que contiene operaciones sobre
listas, para luego definir los objetos (esto es: lista, conjunto, arbol_bin). Aquí sólo se muestra como
ejemplo la definición de la biblioteca, el objeto lista y el método sin_último, que devuelve la lista sin
su último elemento. En el archivo adjunto pca.pl, se incluye una implementación completa de los
objetos, los cuales siguen los mismos criterios que en el ejemplo presentado.

Puede observarse que, en el objeto list, el método sin último se comporta diferente según el
número y tipo de sus parámetros (sobrecarga). Si recibe como parámetro una instancia existente,
entonces compara el contenido de la instancia con la lista contenida en el objeto, sin el último
elemento. Sino, crea una nueva instancia con la lista sin el último elemento como atributo.
Finalmente, si lo que recibe es una variable Prolog, entonces devuelve la lista del objeto sin el último
elemento. En caso de ser llamado sin parámetros, modifica el objeto, sustituyendo la lista implícita
actual por ella misma sin el último elemento.

:- use_module(library(objects)).

list_lib :: {

%% sin_ultimo(+L, ?S)

%% S es la lista que se obtiene de suprimir el último elemento de L

sin_ultimo([X], []) &

sin_ultimo([X|R], [X|Y]) :-

:: sin_ultimo(R, Y)

}.

list :: {

%% Herencia a partir de 'object'

super(object) &

%% Tiene una lista como atributo

attributes([content([])]) &

%%% sin_ultimo(+S)

sin_ultimo(S) :-

: atom(S) ->

%% me pasaron una instancia, veo si es la lista es

%% el la lista del original sin el ultimo elemento

:: has_instance(S) ->

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
19
ORIENTACIÓN A OBJETOS EN PROLOG

<: get(content(L)),

S :: get(content(LS)),

list_lib :: sin_ultimo(L, LS)

%% crea una nueva instancia

%% que contiene la lista sin el ultimo

%% verifica que no haya nada ahi

\+ object(S) ->

<: get(content(L)),

list_lib :: sin_ultimo(L, LS),

list :: new(S, LS)

<: get(content(L)),

list_lib :: sin_ultimo(L, S)

&

%% Remueve el ultimo elemento de la lista implicita

%% caso en que no se le pasan argumentos

sin_ultimo :-

<: get(content(L)),

list_lib :: sin_ultimo(L, S),

<: set(content(S))

}.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
20
ORIENTACIÓN A OBJETOS EN PROLOG

APÉNDICE 2: OOTUTLOG

Como trabajo de laboratorio para el curso de Programación Lógica 2002 se propuso la


implementación, utilizando Prolog, de una versión simplificada del juego de cartas Tute Cabrero. En
este apéndice se presenta una solución al problema utilizando un diseño orientado a objetos y Prolog
Objects para su implementación.

ESQUEMA DE TRABAJO

El objetivo principal es aplicar una metodología de análisis y diseño orientado a objetos al


desarrollo en Prolog. El desarrollo orientado a objetos puede ser entendido como una forma de
pensar basándose en abstracciones de conceptos existentes en el mundo real; es, a su vez, el organizar
el software como una colaboración de objetos que interactúan entre sí por medio del envio de
mensajes.

Los objetivos secundarios planteados son realizar implementaciones alternativas de forma de


posibilitar comparaciones entre el paradigma tradicional en la programación lógica y la aplicación del
paradigma de orientación a objetos a ésta, y entre implementaciones en lenguajes orientados a objetos
tradicionales y la aplicación de este paradigma a la programación lógica. Para ello, se implementó una
solución en Prolog, sin considerar el análisis y diseño realizado. Además, se implementó la solución
diseñada en C# (lenguaje orientado a objetos) y en SICStus Prolog OO.

Las estapas llevadas a cabo se enumeran a continuación:

1. Análisis de requerimientos.

2. Análisis orientado a objetos.

3. Diseño orientado a objetos.

4. Implementación de la solución utilizando un lenguaje orientado a objetos tradicional: C#

5. Implementación de una solución al problema utilizando Prolog.

6. Implementación de la solución utilizando el módulo Prolog Objects de SICStus.

ANÁLISIS DE REQUERIMIENTOS

Se detalla a continuación la descripción general del problema. Una versión más detallada se encuentra
en la letra del laboratorio.

“Se desea simular una partida de “Tutlog” el cuál es, básicamente, una versión modificada del popular “Tute
Cabrero”. Se juega con un mazo de cartas españolas, quitándole los ochos y nueves. En cada partida hay un palo
llamado triunfo, que gana por sobre todos los otros. Cada carta tiene su puntaje propio. Inicialmente se elige el
palo del triunfo al azar. Luego se reparten las cartas y el jugador que es mano tira primero, jugando el resto de
izquierda a derecha. El jugador que es mano puede jugar cualquier carta. En cambio los demás jugadores deben
tirar según lo indicado por las reglas del juego. Una vez que hayan jugado todos los jugadores, el ganador recoge la

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
21
ORIENTACIÓN A OBJETOS EN PROLOG

baza y pasa a ser mano. Esto querrá decir que ahora será él el que empezará a jugar, y los demás jugarán tras él,
según el orden antes explicado. Cuando los jugadores se queden sin cartas acabará la partida y se procederá a
contar los puntos de cada jugador. El jugador que gane la última baza sumará diez puntos adicionales. Los
ganadores de la partida son: el jugador que ha hecho más puntos y el que ha hecho menos. El primer jugador que
logre ganar una cierta cantidad de partidas (establecidas de antemano), será el ganador del juego.”

ANÁLISIS ORIENTADO A OBJETOS

El objetivo del análisis orientado a objetos es encontrar y describir los objetos (o conceptos) en
el dominio de la aplicación. Estos conceptos son una primera aproximación a la solución al
problema.

El resultado fundamental de esta etapa es un modelo conceptual. Un modelo conceptual es una


representación de los conceptos que son significativos en el dominio del problema.

Se presenta a continuación el modelo conceptual para el problema en cuestión:

Carta 10 1 4 1
Palo Mazo
numero
nombre : string
/puntos
0..4
1 triunfo
0..13

 conformada
0..*

Baza
 enMano 0..*

0..13 10,13
gana

0..1 1
0,1

Jugador gana Partida


nombre : string
0,2 0..*
0..*
3..4

1
Juego

{ordered}

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
22
ORIENTACIÓN A OBJETOS EN PROLOG

En él se muestra el concepto mazo, compuesto de 4 palos, que a su vez estan conformados por
10 cartas (recordar que no hay ni 8 ni 9). El juego consta de partidas. En cada partida se juegan 10 o
13 bazas, dependiendo la cantidad de jugadores. Cada baza esta conformada por cartas. Cada jugador
registra las bazas que ha ganado. Además conoce las cartas que tiene en la mano.

Respecto a los jugadores, interesa reflejar que hay distintos tipos de ellos. En particular, un
jugador puede ser un usuario o la propia computadora. Para el caso de esta última, puede tener tres
estrategias diferentes de juego, a saber, Primera, Azar e Inteligente. Primera elige tira siempre la
primer carta dentro de las posibles. Azar elige una carta de las posibles en forma aleatoria. Inteligente
tiene una estrategia de juego más complicada, en función de las cartas ya tiradas, de las cartas en la
mesa, y de las que restan ser tiradas. Conceptualmente, los jugadores pueden modelarse de la
siguiente forma:

Jugador

Usuario Computadora

Primera Azar Inteligente

DISEÑO ORIENTADO A OBJETOS

El objetivo de esta etapa es definir objetos lógicos (de software) y la forma de comunicación
entre ellos para una posterior programación. En base a los “conceptos candidatos” encontrados
durante el análisis y por medio de ciertos principios y técnicas, se debe decidir cuáles de éstos serán
los objetos que participarán en la solución y cómo se hablan entre ellos para obtener el resultado
deseado. El concepto clave aquí radica en la asignación de responsabilidades. En la transición del
análisis al diseño, puede encontrarse conceptos que no participen de la solución, puede ser necesario
reflotar conceptos que inicialmente fueron dejados de lado, y puede ser necesario crear ayudantes
(también objetos) para que los objetos puedan llevar a cabo su tarea.

Dos herramientas principales a utilizar aquí son los diagramas de secuencia y los diagramas de
colaboración de UML. En ellos se muestra la forma en que los objetos interactúan para llegar al
resultado.

Se presenta en primera instacia un diagrama de secuencia donde tiene lugar un juego entero. Se
agregó el objeto visualizador encargado de desplegar los mensajes del juego en pantalla. El juego
comienza mediante el mensaje iniciarJuego que recibe los jugadores que participarán (en el orden
deseado) y la cantidad de partidas a jugar. El juego elige un palo triunfo al azar e indica el mismo a los
jugadores y al visualizador mediante el mensaje indicarPaloTriunfo. Luego se barajan las cartas y se
reparten a cada jugador (mediante el mensaje indicarCartas). En este momento el jugador recibe las
cartas y es cuando decide si va a más o a menos. Luego se inicia una nueva baza y se avisa al

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
23
ORIENTACIÓN A OBJETOS EN PROLOG

visualizador (nuevaBaza). Se consulta a cada jugador que carta desea tirar. En la primer partida
comienza el primer jugador, mientras que en las siguientes comienza el de la derecha del que había
comenzado la partida anterior. Cada jugador conoce las reglas del juego, por lo que determina de las
cartas que tiene en la mano cuales son las que puede tirar, eligiendo una de ellas. Esto último no esta
mostrado en el diagrama, ya que cada jugador realiza la elección en forma distinta. Una vez que cada
jugador tiró una carta, se avisa quien es el ganador de la baza (mensaje ganadorBaza al visualizador).
Luego se avisa a cada jugador que la baza finalizó. El jugador puede tomar nota de que cartas fueron
tiradas. Una vez que se acaben las cartas en la mano de los jugadores se procede a que cada uno
calcule los puntos ganados. A partir de estos puntos se calcula los ganadores de la partida. Se repite
este proceso hasta que algun(os) jugadores alcancen la cantidad de partidas a jugar en el juego. Por
último se indica en el visualizador los ganadores del juego (ganadoresJuego).

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
24
ORIENTACIÓN A OBJETOS EN PROLOG

Se los considera
:Visualizador j1:Jugador ordenados de :Juego j2:Jugador
izquierda a derecha Se elige un palo
triunfo al azar

iniciarJuego(jugadores:Collection, cantPartidas:int)

indicarPaloTriunfo(palo:Palo) indicarPaloTriunfo(palo:Palo)

indicarPaloTriunfo(palo:Palo)
Cuando recibe las
cartas decide si va
a más o a menos

indicarCartas(cartas:Collection) indicarCartas(cartas:Collection)

En la primer partida comienza


nuevaBaza() el primero. En las siguentes
comienza el de la derecha al
que habia comenzado en la
partida anterior.
c:=tirarCarta(baza:Baza)

cartaTirada(baza:Baza)
c:=tirarCarta(baza:Baza)

cartaTirada(baza:Baza)

ganaBaza(baza:Baza)
Se repite hasta que se acaben las
cartas en la mano de cada jugador

ganadorBaza(baza:Baza)

finalizaBaza(baza:Baza) finalizaBaza(baza:Baza)

puntos:=darPuntosGanados() puntos:=darPuntosGanados()

ganadoresPartida(ganadores:Collection) Se repite hasta que un jugador


gane cantPartidas veces

ganadorJuego(j:Jugador)

Una vez decidido a grandes rasgos como procederá el juego, se diseña como hace cada objeto
para llevar a cabo las responsabilidades que le fueron asignadas. A partir de esto vamos a detectar
responsabilidades en otros objetos. Para cada uno de los mensajes que “llegan” a visualizador se
realiza un diagrama de colaboración. A modo de ejemplo, se presentan los diagramas de colaboración
para algunas operaciones:

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
25
ORIENTACIÓN A OBJETOS EN PROLOG

indicarPaloTriunfo(palo) 1: n:=getNombre()

: Visualizador palo : Juego::Palo

1: palo:=getPalo()
cartaTirada(baza) 2: carta:=getNumero()

: Visualizador c : Juego::Carta

ganadorBaza(baza) 1: j:=darGanador()

: Visualizador baza : Juego::Baza


2: n
: = ge
tNom
bre (
)

j : Juego::Jugador

El objeto con mayor responsabilidad es juego. El diseño de sus operaciones dio lugar a nuevos
objetos que eran necesarios para realizar la tarea asignada. Este es el caso de tanteador. Se muestra a
continuación los diagramas de colaboración para juego.

1: g:=jugarJuego(jugadores, cantPartidas)

iniciarJuego(jugadores, cantPartidas) 2: ganadorJuego(g)

: Juego : Visualizador::Visualizador

2* [not hg]: ganadores:=jugarPartida(jugadores)


1: create(jugadores, cantPartidas)
3*: registrarGanadores(ganadores)
5*: hg:=hayGanador()
g:=jugarJuego(jugadores, cantPartidas) 6 [hg]: g:=darGanador()
: Tanteador
: Juego
4* : g
ana
dor e
sPa
rtida
(g ana
Se repite hasta que un jugador dore
s)
gane cantPartidas veces.

: Visualizador::Visualizador

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
26
ORIENTACIÓN A OBJETOS EN PROLOG

1: paloTriunfo:=sortearPaloTriunfo(jugadores)
2: repartirCartas(jugadores)
4* [1..40/cantJugadores]: mano:=jugarBaza(jugadores, mano, paloTriunfo)

3: cantJugadores:=count()
ganadores:=jugarPartida(jugadores) 6* [foreach]: j:=next()

: Juego jugadores:Jugador

7*:
pun
tos
:=d
ar Pun
t osG

9: add(jmenos)
8: add(jmas)
a

5: cre
nad
os (
)

ate()
j : Jugador

Calcula los ganadores jmas y jmenos


según los puntajes obtenidos
ganadores:Jugador

sortearPaloTriunfo:=sortearPaloTriunfo(jugadores) 1* [foreach]: j:=next()

: Juego jugadores:Jugador
2*: in
dica
rP aloT
riunf
3: in

o(pa
lo)
dica
rPa

Elige un palo al azar


loT

j : Jugador
riunfo
(pa
lo)

: Visualizador::Visualizador

repartirCartas(jugadores) 1* [foreach]: j:=next()

: Juego jugadores:Jugador
2*: in
dica
rC ar
tas(c
a r ta
s)

Sortea grupos de igual


cantidad de cartas al azar.
Sea cada grupo de cartas j : Jugador
los indicados por 'cartas'

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
27
ORIENTACIÓN A OBJETOS EN PROLOG

f o)
riun
p a loT r, c) : Baza
, o
ano (jugad or()
e(m a d
c reat aTirad rGana
2: t
car o:=da
5 *: a n
7: m

3* [foreach]: j:=next()
jugarBaza:=jugarBaza(jugadores, mano, paloTriunfo) 9* [foreach]: next:=next()

: Juego jugadores:Jugador
4*:
c
10* :=tirar

ba a)
az (b ()
: fin C

rB da za
a( az

)
aliz arta(b

za
do ira a
aB a a
na taT vaB
za( za)
ga ar ue baz
a)
8: *: c : n
6 1

j : Jugador

: Visualizador::Visualizador

Se explicará a continuación el diagrama de colaboración para la operación jugarBaza de juego.


Recibe la lista de jugadores (jugadores), el jugador mano (mano) y el palo triunfo (paloTriunfo). Primero
le indica al visualizador que comienza una nueva baza (1: nuevaBaza). Crea una instancia de baza (2:
create). Para cada jugador j le pide que tire una carta (4: tirarCarta), le indica a la baza que el jugador
tiró tal carta (5: cartaTirada) y le avisa al visualizador (6: cartaTirada). Una vez consultados todos los
jugadores, se pregunta a la baza quien fue el ganador (7: darGanador). Por último, a cada jugador se le
avisa que la baza terminó (10: finalizaBaza).

La etapa de diseño puede involucrar un diagrama de colaboración para cada una de las
operaciones de cada clase. Sin embargo, algunas de ellas pueden no hacerse debido la sencillez de la
operación, a que involucran excesiva algoritma, o que se deja al implementador que tome las
decisiones.

IMPLEMENTACIÓN UTILIZANDO C#

Una vez superada la etapa de diseño se consideró de interés desarrollar un prototipo de la


solución. El desarrollo temprano de prototipos permite detectar errores en el diseño como ser falta
de información para realizar una tarea, necesidad de más operaciones, entre otras. Realizar una etapa
de diseño detallada para cada una de las operaciones elimina gran cantidad de estos problemas, sin
embargo requiere en general de un tiempo excesivo.

Se utilizó C# para el desarrollo del prototipo. Este es un lenguaje de programación orientado a


objetos de la familia de lenguajes .NET. Presenta características de fuerte tipado, de garbage
collector, entre otros, lo cual lo hacen un lenguaje deseable para el desarrollo OO.

Las principales clases implementadas fueron Juego, Jugador, Mazo, Palo, Carta, Baza y
Tanteador. Se implementó además un jugador usuario (JugadorConsola) y un jugador computadora que
elige la primera carta (JugadorComputadoraPrimera).

El desarrollo en C# llevó aproximadamente 12 horas de trabajo de implementación. Notar que el


tiempo de diseño fue incluso mayor a esas horas, y gracias a él se redujo tanto el tiempo de
implementación.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
28
ORIENTACIÓN A OBJETOS EN PROLOG

IMPLEMENTACIÓN UTILIZANDO PROLOG.

Paralelamente al trabajo anterior, se realizó una implementación utilizando Prolog “puro”. Se


incluyeron en esta solución (particularmente en el predicado ElegirCartaC), las estrategias para un
juego inteligente de la computadora.

El desarrollo en Prolog llevó aproximadamente 46 horas de trabajo de implementación. Estas


horas incluyen la planificación de la solución.

Los predicados se agruparon de acuerdo a los módulos identificados en el estudio del problema:
juego, partida, turno, vuelta y estrategia.

PREDICADOS DEL JUEGO

Estos predicados modelan el transcurso del juego. Incluyen inicializar la base de conocimiento,
inicializar el mazo y lanzar el juego según los jugadores y estrategias definidos por el usuario. La base
de conocimiento está modelada por los siguientes predicados:

• jugadores(X) → Cantidad de jugadores


• partidasganan(C) → Cantidad de partidas a las que se juega
• mano(N) → Número del jugador mano
• manopartida(M) → Mano de la partida actual
• mesa(M) → Cartas en la mesa
• jugaron(J) → Los jugadores que jugaron en la vuelta, en orden
• triunfo(T) → Triunfo de la partida
• estrategia(E) → estrategia de juego (azar o inteligente)
• cartas_jugadas(CJ) → las cartas que se han jugado en la partida.
• descartada(D) → la carta que se descartó si juegan 3.
• jugador(Numero, Tipo, Cartas, Bazas, Puntos, Partidas, Estrategia) → Jugadores. Incluye si es
humano/computadora, las cartas que tiene, las bazas que lleva, los puntos que ha acumulado,
las partidas que ha ganado y la estrategia (azar, mas o menos).
• carta(N,Palo) → las cartas que juegan.
• valor(Carta) → el valor de cada carta

PREDICADOS DE LA PARTIDA

Estos predicados controlan el desarrollo de una partida de 3 o 4 jugadores. Incluyen barajar,


repartir las cartas, elegir el triunfo, definir las estrategias de los jugadores, lanzar las vueltas (parte del
juego en la que cada jugador tira una carta y gana la baza el que tenga la mayor, según las reglas), y
determinar los ganadores.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
29
ORIENTACIÓN A OBJETOS EN PROLOG

Definen también las estrategias de las computadoras. Para ello, determinan si se está jugando al
azar o inteligente (según la base de conocimiento), y para cada jugador de tipo computadora, eligen si
ir a más o menos según las cartas que tiene.

PREDICADOS DE UNA VUELTA

Una vuelta se considera al juego de una carta por jugador. Estos predicados modelan una vuelta
de juego, con un cierto palo como triunfo. Controlan el lanzamiento de la vuelta, y, cuando finaliza
determinan el ganador de la baza según las reglas del juego.

PREDICADOS DE UN TURNO

Un turno es el juego de una carta por uno de los jugadores. Estos predicados son esencialmente
los que eligen una carta, ya sea solicitándola a un humano o jugando según los criterios de la
computadora. Son quienes regulan que el juego se realice de acuerdo a las reglas validando que las
cartas jugadas sean las correctas.

ESTRATEGIA

La computadora tiene dos formas de jugar: al azar o inteligentemente. En el segundo caso, tiene
algunas reglas para jugar, las que se detallan a continuación.

• Determina si ir a más o menos. Para esto , suma los puntos que tiene en la mano, asignando
doble valor a los triunfos con puntos, y sumando dos puntos por cada triunfo con valor 7 o
menor. Si la suma le da mayor a 45, juega a más, sino juega a menos. Este valor se obtuvo
realizando muchas corridas y viendo que valore obtenía cada jugador. El predicado que
implementa la decisión es elegirMasmenos(+Cartas,-MasMenos).

• Si la mesa está vacía y va a más, determina (a partir de las cartas jugadas) si existe alguna carta
“inmatable”, esto es, que nadie la puede superar. Si tiene alguna la juega, sino elige una al azar.

• Si la mesa está vacía y va a menoss, determina (a partir de las cartas jugadas) si existe alguna carta
“matable”, esto es, que alguien puede superarla. De las que tiene, prefiere siempre para jugar
triunfos y cartas altas.

• Si la mesa no está vacía y va a más, mata con la más alta posible y pierde con la más baja posible.

• Si la mesa no está vacía y va a menos, mata con la más baja posible y pierde con la más alta
posible.

Es en este módulo donde se implementan los predicados que toman estas decisiones.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
30
ORIENTACIÓN A OBJETOS EN PROLOG

IMPLEMENTACIÓN UTILIZADO PROLOG OBJECTS

Para la implementación utilizando Prolog Objects se siguió estrictamente lo obtenido en el


diseño orientado a objetos, exactamente de la misma form que se hizo en la implementación en C#.
Además, la implementación fue dirigida por el desarrollo en C#, dado que el diseño no fue
desarrollado completamente.

A continuación se realiza una descripción de las clases utilizadas (estructura, funcionamiento,


interacciones), junto con sus métodos principales. La documentación de cada uno de los predicados
esta detallada en los fuentes de la implementación.

El desarrollo en Prolog Objects llevó aproximadamente 32 horas de trabajo de implementación.


El haber desarrollado la misma solución en C# y el contar con la implementación en Prolog “pura”
redujo significativamente la cantidad de horas dedicadas.

GENERALIDADES

Como se mencionó, cada clase identificada en el diseño tiene su correspondencia en un objeto de


Prolog Objects. En general, todos los objetos heredan del objeto genérico object, e incluyen un
constructor new así como atributos donde se guarda el estado del objeto. Cada una de las clases esta
ubicada en un archivo fuente diferente. Cada uno incluye, además de la declaración del objeto en
cuestión, un objeto auxiliar (llamada clase_lib) donde están los predicados Prolog auxiliares incluídos
como métodos.

En la implementación, debieron utilizarse criterios para representar estructuras imperativas


(como loops, ifs y switchs), utilizando predicados Prolog. Por ejemplo, para representar un switch, se
utilizaron cadenas de predicados Prolog, utilizando cut en cada uno. Para los loops se utilizaba un
parámetro adicional el cual ayudaba a determinar la terminación del loop.

Las clases utilizadas son las siguientes:

Clase App
Objeto que contiene el método main, que inicia el juego.

Clase Carta
Modela a las cartas del juego. Tiene como atributos un número y una referencia a un objeto
Palo. En esta clase está el método puedeMatar que indica si un objeto Carta puede matar a otro
objeto Carta, de acuerdo a un palo de triunfo dado, según las reglas del juego.

Clase Palo
Modela a un Palo del juego. Incluye como atributos el nombre y las cartas que pertenecen al
palo. Puede observarse que existe una doble navegabilidad entre las clases Carta y Palo (lo que nos
permite fácilmente saber cuáles son las cartas de un Palo, y a qué Palo corresponde una cierta Carta).
En el constructor de la clase son creadas las cartas del Palo, agregando las instancias creadas en una
lista en el atributo cartas.

Clase Mazo.
Modela el Mazo. Sus atributos son los 4 palos de la baraja. Cuando se crea el objeto Mazo, se
crean los cuatro palos que lo componen. con lo que se logra de esta forma crear las 40 cartas del

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
31
ORIENTACIÓN A OBJETOS EN PROLOG

mazo. Esta clase es la encargada de armar el mazo, barajar y repartir las cartas a los jugadores, a través
del método repartirCartas.

Clase Jugador
Modela a un jugador. Esta clase contiene los atributos genéricos de los jugadores, y tiene como
sub-clases a los jugadores humanos (JugadorConsola) o computadoras (JugadorComputadora). Es la
responsable de que el Jugador tire una carta (a través del predicado tirarCarta). Este método envía el
mensaje tirarCarta(Baza,Carta) a la biblioteca de funciones, quien obtiene las cartas del jugador, calcula
las cartas pasibles de ser jugadas por el mismo, y envía el mensaje tirarCarta(Baza,CartasPosibles,Carta)
nuevamente al jugador. Este mensaje será interpretado dinámicamente por la subclase
correspondiente, quien actuará de acuerdo a sus características para elegir la carta. Lo mismo sucede
con decidirEstrategia(+Mazo), que, dadas las cartas recibidas, determina si se va a ir a más o menos.

Clase JugadorConsola
Modela a un jugador humano. Como se mencionó, tiene como superclase a jugador. Esta clase
implementa en particular al requerimiento elegirCartaH, a través de su redefinición de
tirarCarta(+Baza, +CartasPosibles, -Carta). Esto es, es la responsable de solicitar al jugador que juegue
su carta, dejando la validación a la clase jugador de la que hereda.

Clase JugadorComputadora
Modela a un jugador computadora. Hereda de jugador, y su única función es servir como
superclase a jugadorComputadoraAzar, jugadorComputadoraInteligente, jugadorComputadoraPrimera.

Clase JugadorComputadoraPrimera
Modela a una computadora que juega tontamente. Su forma de elegir la carta es simplemente
eligiendo la primer carta de las que puede tirar.

Clase JugadorComputadoraAzar
Modela a una computadora que juega al azar. Su forma de elegir la carta es simplemente
sorteando un número y tirando la carta indizada por el número.

Clase JugadorComputadoraInteligente
Modela a una computadora que juega inteligentemente. Para detalles de la estrategia, véase el
punto Estrategia de la implementación en Prolog tradicional, ya que el funcionamiento es idéntico.
En este caso, la estrategia seleccionada y las cartas del oponente se incluyeron como atributos
propios del objeto. Sólo en esta subclase el comportamiento del método decidirEstrategia(+Mazo) no
es trivial, ya que en este caso es donde se cuentan puntos según el criterio definido. Lo mismo sucede
con la redefinición tirarCarta(+Baza,+CartasPosible,-Carta), donde se codifican las elecciones realizadas
para elegir la mejor carta.

Clase Baza
Esta clase modela las cartas jugadas en la mesa y es la responsable de mantener el estado de la
misma. Incluye, por ejemplo, métodos como darGanador(?Jugador) que devuelve el ganador de una
baza o cartaTirada(+Jugador,+Carta) que registra que un jugador jugo una carta a la mesa. Incluye
como atributos al palo del triunfo, al mano, y la lista de jugadores que jugaron y las cartas en la mesa.

Interfaz Visualizador
Implementada por el objeto JugarConsolaUI. Esta clase es la responsable de dar los mensajes a la
consola.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
32
ORIENTACIÓN A OBJETOS EN PROLOG

Clase Tanteador
Lleva el tanteador del juego. Incluye como atributos a los jugadores y los puntos y partidas
ganadas por cada uno. Es responsable de registrar cuando un jugador gana una partida, y de
determinar si hay un ganador de acuerdo a las partidas ganadas y las partidas a las que se jugaba.

Clase juego
Modela la dinámica del juego en general. Incluye como atributos un mazo, un tanteador, y un
visualizador para los resultados. Es responsable de conducir el juego (predicado JugarJuego) , de lanzar
el juego de las partidas, de las bazas y del reparto de cartas.

MODO DE USO

Para cargar las definiciones debe hacerse:


?- use_module('run.pl').

Este modulo define un predicado tutlog(+Nombre,+CantPartidas) el cual permite jugar un jugeo de


CantPartidas con cuatra jugadores. Los jugadores son el propio usuario (identificado por Nombre),
un jugador computadora azar (jca), un jugador computadora primera (jcp) y un jugador computadora
inteligente (jci). Como ejemplo, puede hacerse:
?- tutlog(nombreusuario, 3).

El usuario puede crear nuevos jugadores instanciando directamente algunas de las clases de los
jugadores. El siguiente ejemplo muestra como hacer competir a la computadora consigo misma,
donde hay un jugador de cada tipo.

?- jugadorComputadoraPrimera :: new(jcp, 'jcp').

?- jugadorComputadoraAzar :: new(jca, 'jca').

?- jugadorComputadoraInteligente :: new(jci, 'jci').

?- app :: main([jcp, jca, jci], 2).

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
33
ORIENTACIÓN A OBJETOS EN PROLOG

CONCLUSIONES

La extensión Prolog Object de SICStus presenta las características necesarias para utilizar
conceptos del paradigma de orientación a objetos en la programación lógica. Permite orientación a
objetos “pura” y además simular la orientación a clases provistas por lenguajes de programación
como Java y C#.

Es factible aplicar metodologías de desarrollo orientadas a objetos al momento de crear


soluciones utilizando programación lógica. Las virtudes que conlleva el paradigma de orientación a
objetos como el ocultamiento de la información y la reutilización de código también se aplican
cuando se utiliza OO en programación lógica. Puede verse en el trabajo realizado que es posible
hallar un mapeo directo del diseño a objetos en Prolog, mapeo similar al utilizado en la
implementación en un lenguaje imperativo orientado a objetos como C#.

En lo que respecta a las implementaciones en Prolog “puro” y Prolog Objects se destaca: mayor
facilidad de encontrar la información, mayor legibilidad en el código. La organización de la base de
conocimiento en Prolog “puro”, principalmente cuando la base es alterada dinámicamente (mediante
el uso de assert y retract), dificulta identificar el estado del sistema. Respecto a la legibilidad, el uso de
módulos puede ayudar notoriamente en la programación en Prolog “puro”. El uso de Prolog Objects
extiende el sistema de módulos con las características de OO mencionadas, lo cual facilita la lectura y
el mantenimiento del código generado.

Daniel Perovich – Guillermo Moncecchi Julio, 2002


{perovich,gmonce}@fing.edu.uy
34

You might also like