BriscoParse -...
Transcript of BriscoParse -...
BriscoParseUn linguaggio per descrivere partite di
Briscola a 4 giocatori.
Linguaggi e Modelli Computazionali LS
Marco D’Alessandro
1
Obiettivo del Progetto Sviluppare un Linguaggio semplice che permetta la descrizione dello svolgimento di partite di Briscola “parlata” a 4 giocatori, intendendo per “parlata” la possibilità di suggerire al compagno la mossa da effettuare (“metti carico/puntarelli/briscola/vai liscio”).
Realizzare un interprete in grado di calcolare i punteggi parziali delle singole partite e quello complessivo della Briscola, verificando il corretto svolgimento delle varie fasi del gioco.
Realizzare un’interfaccia grafica che permetta di visualizzare e simulare a video la partita di Briscola analizzata.
2
Grammatica - Formalismo
4
G = <VT, VN, P, S>
VT - Insieme dei simboli terminali o token.
VN - Insieme dei simboli non-terminali.P - Insieme delle produzioni.S - Scopo della grammatica.
Grammatica - Proprietà
5
Tutte le produzioni della grammatica sono nella forma: A → α con α ∈ (VN ∪ VT)∗, A ∈ VN.
La grammatica è perciò di Tipo 2 (context-free) secondo la classificazione di Chomsky.
La grammatica non contiene self-embedding → il linguaggio generato sarà di Tipo 3 (regolare).
La grammatica è LL(1) poiché per ogni metasimbolo che appare nella parte sinistra di più produzioni, i Director Symbols relativi a produzioni alternative sono disgiunti.
Grammatica - Token
6
Token per nomi e numeri:
<CIFRA_NON_NULLA: ["1"-"9"]><CIFRA: <CIFRA_NON_NULLA> | "0"><NUM: <CIFRA_NON_NULLA> (<CIFRA>)*><CARATTERE: ["a"-"z","A"-"Z","_"]><NOME: <CARATTERE> (<CARATTERE> | <CIFRA>)*>
G = <VT, VN, P, S>
<SEME: "Denari" | "Coppe" | "Spade" | "Bastoni"><VALORE: "Asso" | "Tre" | "Dieci" | "Nove" | "Otto" | "Sette" | "Sei" | "Cinque" | "Quattro" | "Due"><POSIZIONE: "Nord" | "Sud" | "Ovest" | "Est"><GIOCATA: "Carico" | "Briscola" | "Puntarelli" | "Liscio"><RISPOSTA: "Sì" | "No">
Token per carte, posizione giocatori e “parlate”:
Grammatica - Non-terminali
7
G = <VT, VN, P, S>
Scopo S della grammatica:
Scope::="BRISCOLA" "{" Giocatori ( Partita )+ "}"
Descrizione dei giocatori e delle partite:
Giocatori::="GIOCATORI:" Giocatore "," Giocatore "," Giocatore "," Giocatore "."Giocatore::=<NOME> "SIEDE A" <POSIZIONE>Partita::="PARTITA" "{" ConsegnaCarte Round "}"
La grammatica contiene obbligatoriamente le indicazioni sui giocatori (le squadre saranno create durante la valutazione), ed una o più partite. La briscola non può esistere senza giocatori ed almeno una partita (in realtà il controllo sulle partite “al meglio delle 3” sarà fatto in seguito).
Da notare che le parentesi graffe, usate da qui in poi, non causano self-embedding, in quanto in numero finito: c’è una sola parentesi all’inizio e alla fine della produzione. Il token <POSIZIONE> sarà utilizzato per la determinazione delle squadre (lo vedremo).
8
Grammatica - Non-terminaliG = <VT, VN, P, S>
Distribuzione delle carte:
ConsegnaCarte::=<NOME> "CONSEGNA LE CARTE:" GiroDiConsegna GiroDiConsegna GiroDiConsegna BriscolaGiroDiConsegna::="{" Consegna ";" Consegna ";" Consegna ";" Consegna "." "}"Consegna::=<NOME> "RICEVE" CartaNapoletana
La Briscola:
Briscola::="BRISCOLA:" CartaNapoletana "."
Ad inizio partita, ogni giocatore riceve esattamente tre carte dal mazziere, una alla volta. Dopo la consegna il mazziere scopre la Briscola che sarà anche la carta pescata all’ultimo turno dall’ultimo giocatore del turno.
La Briscola sarà una CartaNapoletana e non verrà indicato solo il seme, poiché verrà scoperta sul tavolo e utilizzata nell’ultima mano.
9
Grammatica - Non-terminaliG = <VT, VN, P, S>
Descrizione del round di briscola:
Round::=Mano Pescate Mano Pescate Mano Pescate Mano Pescate Mano Pescate Mano Pescate Mano Pescate Mano Mano ManoMano::="MANO:" ScartaPlus "," ScartaPlus "," Scarta "," Scarta "."ScartaPlus::=<NOME> ( "PARLA:" "{" Parla "}" )? "SCARTA" CartaNapoletanaScarta::=<NOME> "SCARTA" CartaNapoletanaPescate::=Pesca "," Pesca "," Pesca "," Pesca "."Pesca::=<NOME> "PESCA" CartaNapoletanaCartaNapoletana::=<VALORE> "di" <SEME>
ScartaPlus::=<NOME> ( "PARLA:" "{" Parla "}" )? "SCARTA" CartaNapoletanaParla::="CHIEDE" <GIOCATA> Risponde ( "SUGGERISCE" <GIOCATA> )?Risponde::=<NOME> "RISPONDE" <RISPOSTA>
Descrizione della “Parlata”:
Un round è composto esattamente da 10 mani e 7 giri di pescate.Ogni mano è formata da 4 scartate di cui le primi due ScartaPlus. Le pescate sono 4 nel giro di pescata, una per ogni giocatore.
Sintassi/Semantica
Possono fare una “parlata” solo i due che giocano per primi nella mano
Grammatica - Osservazioni
10
G = <VT, VN, P, S>
La grammatica potrebbe essere resa più compatta e leggibile; per esempio la produzione:
Round::=(Turno)+ Mano Mano ManoTurno::=Mano Pescate Round::=Mano Pescate Mano Pescate ... Mano Pescate Mano Mano Mano
Si è preferito usare la prima produzione, poiché la struttura sintattica del linguaggio si lega direttamente a un requisito semantico, cioè che un round di briscola sia fatto esattamente da 7 Mano alternate a 7 Pescate con 3 Mano finali. Così, frasi con un numero di Mano/Pescate diverso dal previsto sono sintatticamente errate; si alleggerisce con poco sforzo il lavoro del valutatore (lo stesso discorso si applica a GiroDiConsegna e Consegna).
Non sono presenti ε-rules e si verifica facilmente come gli starter-set siano disgiunti: la grammatica è LL(1) (con l’abuso di notazione di ε->“finestringa” ≠ ”stringanonvuota” Parla::="CHIEDE"<GIOCATA>Risponde("SUGGERISCE" <GIOCATA> )?).
Sintassi/Semantica
Strumenti utilizzati
11
Linguaggio di programmazione: Java (jdk1.6.0_37)
Ambiente di sviluppo: Eclipse Juno Service Release 1
Generazione parser: JavaCC 5.0
Generazione classi AST e Visitor generici: JTB 1.4.7
Interfaccia grafica: Jigloo GUI Builder 4.6.6
Diagrammi UML: ObjectAid UML Explorer 1.0.11
JavaCC Eclipse
Plug-in 1.5.27⎬
Architettura: Package
12
Il package parser è stato generato in automatico da
JavaCC; i package visitor e syntaxtree sono stati
generati da JTB.
13
Package: briscola (1)
Contiene tutte le classi che descrivono gli oggetti fondamentali di una
partita di briscola, come il Mazzo, la Carta, la Squadra, i Giocatori (v. dopo).
14
Package: briscola (1)Seme e Valore: enumerativi che rappresentano rispettivamente il seme di
una carta (bastoni, denari, coppe, spade) e il suo valore (asso, due, etc.);
utili per descrivere una Carta.
MazzoNapoletane: estende Mazzo e rappresenta un mazzo di 40 carte
napoletane (tramite un Vector<Carta>). Fornisce metodi accessori (ad es.
shuffle).
Carta: rappresenta una singola carta di gioco con le sue proprietà.
BriscolaException: un’eccezione apposita scatenata da errori semantici;
sarà utile al BriscoParseVisitor per intercettare errori semantici (v. dopo).
16
Posizione: Enumerativo che rappresenta la posizione di seduta sul tavolo da gioco, descritta dai quattro simboli cardinali nord, sud, est, ovest.
Giocatore: Permette di istanziare i vari giocatori della partita di briscola. Fornisce metodi accessori per ricevere e scartare una Carta lanciando le eccezioni dovute (se riceve più di tre carte, se scarta carta che non possiede, etc.).
Squadra: Rappresenta una coppia di istanze di Giocatore in una partita. Si occupa di controllare che i giocatori in coppia siano in posizione opposte (N-S e E-O) e fornisce metodi accessori per la ricerca di un giocatore e le informazioni relative al punteggio parziale e totale.
Tavolo: Classe che rappresenta l’ambiente di gioco di una partita di briscola: contiene tutti i metodi che permettono di controllare che la partita sia svolta secondo le regole, lanciando le dovute eccezioni in caso contrario. Fornisce i metodi per stabilire il Giocatore che effettua la presa ad ogni mano e per assegnare conseguentemente i punti alla Squadra. Si occupa anche di controllare il corretto giro di giocate (antiorario).
Package: briscola (2)
17
Architettura: Visitor
BriscoParseASTVisitor:
Costruisce una struttura a TreeNode per rappresentare l’albero sintattico. Non esegue controlli semantici, quindi sarà sufficiente che un testo sia conforme alla sintassi del linguaggio (ma non alla semantica) per generare l’albero.
BriscoParseVisitor
Visitor che percorre l’albero e istanzia tutti gli oggetti necessari (Giocatori, Squadre, ecc) tra cui Tavolo che rappresenterà l’ambiente di gioco. Calcola il risultato di una partita di Briscola: i punti dei singoli round e dell'intera partita ("al meglio dei 3"). Si occupa di controllare tutti gli errori semantici che si possono verificare (aiutato anche dalle eccezioni lanciate dai vari oggetti).
BriscoParseDrawVisitor
Visitor che simula graficamente la partita di Briscola utilizzando i metodi di javax.swing.JFrame; non c'è controllo semantico. Se però è invocato a seguito di BriscoParseVisitor, nel caso ci siano errori semantici, verrà visualizzato un relativo messaggio in una JProgressBar.
Sono stati implementati 3 visitor costruiti basandosi su DepthFirstVoidVisitor (autogenerato da JTB):
Controlli semantici
18
Controllo che i giocatori siano seduti nella giusta posizione (no giocatori su stesso posto e Nord con Sud/Est con Ovest).
Controllo che i giocatori abbiano nomi diversi all’interno della stessa squadra (si può eliminare utilizzando come chiave anche la <SEDUTA>).
Controllo che non giochi un giocatore inesistente.
Controllo del corretto giro di gioco (antiorario):
Controllo che non vengano consegnate, scartate, pescate carte già utilizzate precedentemente o non presenti nel mazzo in quell’istante.
Assegnazione corretta della presa alla squadra con la Carta più forte in ogni mano.
Controllo che il numero delle partite non superi "al meglio delle 3".
Controllo che il numero delle partite non sia inferiore "al meglio delle 3".
Escludendo i controlli definiti nella grammatica stessa (controllo del numero di pescate, scarti, mani, etc.), durante la visita dell’albero BriscoParseVisitor si occupa di tutti i controlli semantici necessari al corretto svolgimento di una partita di Briscola.
consegna carte in senso antiorario;
inizia il giocatore dopo il mazziere;
carte scartate in senso antiorario;
pesca per primo il Giocatore che ha effet tuato la presa nel la mano precedente;
pescate avvengono in senso antiorario;
gioca per primo il Giocatore che ha effet tuato la presa nel la mano precedente.
Sintassi/Semantica
19
Interfaccia Grafica
Risultato della visita di BriscoParseVisitor
Risultato della visita di BriscoParseASTVisitor
21
TestAlcuni test per verificare il funzionamento di metodi
“complicati”, come l’assegnazione della presa al giocatore
che ha scartato la carta più “forte” o il controllo della
direzione delle giocate in un turno (antiorario).
Numerosi test ad-hoc direttamente sull’editor di BriscoParse
per verificare il riconoscimento di errori sintattici e semantici,
forzando situazioni anomale previste, permettendo inoltre di
intercettare errori semantici prima ignoti (v. demo).
Limiti e sviluppi futuri
22
Aggiungere alcune regole del gioco non implementate: non si può parlare alla prima e/o ultima mano (facile → modifica grammatica); possibilità di visualizzare le carte del compagno di squadra o contare i propri punti prima dell’ultima mano (non è necessario modificare la grammatica).
Il linguaggio è migliorabile da un punto di vista di Editor: le frasi sono abbastanza lunghe → inserire un tool per generare automaticamente le frasi (ad es. “clickando” su vari bottoni che rappresentano le diverse frasi).
Integrare BriscoParseVisitor e BriscoParseDrawVisitor permettendo così di visualizzare le partite calcolando prese/punteggi e interrompendosi nel caso di errori semantici, dando il relativo feedback.
Implementazione del gioco via rete: quattro client su internet che possono “clickare” sulle carte da giocare, producendo su un server centrale una frase del linguaggio da valutare. Sarà lo stesso server a produrre e valutare frasi non dipendenti dai giocatori ma dal caso (come ad esempio le pescate e la consegna delle carte).