Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Rossinelli Emanuele
10 Aprile 2010
1
CONTENTS 2
Contents
1 Introduzione 3
2 Dama Italiana 3
2.1 Regole del gioco . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.2 Regole rilassate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
3 Intelligenza Artificiale 5
3.1 Costruzione dell’albero di ricerca . . . . . . . . . . . . . . . . . . . . . . . 5
3.2 Valutazione dei nodi foglia . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.3 Verifica di situazioni non quiescenti . . . . . . . . . . . . . . . . . . . . . . 6
3.4 Algoritmo MIN-MAX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.4.1 Potatura alfa-beta . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.5 Scelta della mossa migliore . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4 Implementazione 10
4.1 Struttura del programma . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.2 Implementazione della scacchiera . . . . . . . . . . . . . . . . . . . . . . . 10
4.3 Struttura dati Mossa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.4 Mosse possibili . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.5 Struttura dell’albero di ricerca . . . . . . . . . . . . . . . . . . . . . . . . 13
4.6 Classe IDamaEngine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
4.6.1 Costruzione dell’albero di ricerca . . . . . . . . . . . . . . . . . . . 14
4.6.2 Funzioni di valutazione . . . . . . . . . . . . . . . . . . . . . . . . 14
4.6.3 Verifica di quiescenza . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.6.4 Minimax e potatura alfa-beta . . . . . . . . . . . . . . . . . . . . . 18
4.6.5 Effettuare la mossa . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.7 Grafica e gestione degli eventi . . . . . . . . . . . . . . . . . . . . . . . . . 18
5 Conclusioni 20
5.1 Stato dell’arte sui programmi risolutori della dama . . . . . . . . . . . . . 21
1 INTRODUZIONE 3
1 Introduzione
L’obiettivo del progetto svolto è stato quello di costruire un software che permettesse a
un umano (in seguito chiamato PLAYER) di giocare a dama italiana contro la macchina
(in seguito chiamata COMPUTER).
Per il raggiungimento dell’obiettivo si è reso necessario un preliminare studio delle regole
del gioco, per permettere la scelta di un adatto algoritmo di Intelligenza Artificiale.
Il programma è stato scritto in C#, con l’ausilio dell’ambiente di sviluppo integrato
(IDE) Microsoft Visual Studio 2008.
2 Dama Italiana
3. La pedina si muove sempre in diagonale sulle caselle scure di una casella alla volta e
soltanto in avanti. Quando una pedina raggiunge una delle caselle dell’ultima riga
viene promossa, diventa dama e deve essere contraddistinta con la sovrapposizione
di un’altra pedina prelevata tra quelle non in gioco.
4. Ogni pedina può mangiare quelle avversarie che si trovano in avanti, sulla casella
diagonale accanto alla propria e che abbiano la casella successiva libera. Dopo la
presa, se incontrano in diagonale altre pedine con la successiva casella libera, si
deve continuare a mangiare senza togliere la mano dalla pedina stessa. In tal caso
la presa si chiama multipla. Le pedine prese vanno tolte dalla damiera.
5. La dama si muove anch’essa di una casella alla volta, sempre in diagonale, in tutte
le direzioni possibili, mangiando sia le pedine che le dame avversarie.
6. In caso di presa è obbligatorio mangiare i pezzi. L’antica regola del ”soffio”, ossia
quella di catturare il pezzo avversario che pur avendone diritto, per distrazione o
per scelta non aveva mangiato, è stata abolita dalla Federazione Dama nel 1934.
7. Avendo più possibilità di presa si debbono rispettare obbligatoriamente nell’ordine
le seguenti priorità:
(a) è obbligatorio mangiare dove ci sono più pezzi;
(b) a parità di pezzi di presa tra pedina e dama, quest’ultima è obbligata a
mangiare;
(c) la dama sceglie la presa dove si mangiano più dame;
(d) a parità di condizioni si mangia dove s’incontra prima la dama avversaria.
8. ”Pezzo toccato = Pezzo mosso”: il giocatore che, nel proprio turno di gioco, tocca
un proprio pezzo sulla damiera è obbligato a muoverlo. Se si vuole aggiustare un
pezzo messo male sulla damiera bisogna prima avvertire l’avversario dichiarando
”accomodo” o ”acconcio” e attendere l’assenso dell’avversario.
9. Si vince per abbandono dell’avversario, che si trova in palese difficoltà, o quando
si catturano o si bloccano tutti i pezzi avversari.
10. Si pareggia in una situazione di evidente equilibrio finale per accordo dei giocatori
o per decisione dell’arbitro a seguito del conteggio di 40 mosse richiesto da uno dei
due giocatori. Il conteggio delle mosse si azzera e riparte da capo tutte le volte che
uno dei due giocatori muove una pedina o effettua una presa.
3 Intelligenza Artificiale
Prima di addentrarci nei dettagli implementativi del software, descriviamo come è stato
costruito il modulo di Intelligenza Artificiale, ovvero quali strategie il software usa per
scegliere la mossa migliore da effettuare.
Ogniqualvolta sia il computer a dover muovere, vengono eseguite le seguenti azioni in
sequenza:
1. Costruzione dell’albero di ricerca
2. Valutazione dei nodi foglia dell’albero creato
3. Verifica di situazioni non quiescenti
4. Applicazione dell’algoritmo MIN-MAX per la valutazione di tutti i nodi dell’albero
5. Scelta della mossa migliore da eseguire
Vediamole brevemente.
Adesso che l’albero è stato creato, dobbiamo per prima cosa valutare le situazioni di
arrivo, ovvero associare una valutazione ai nodi foglia.
Tale valutazione, associata quindi alla scacchiera in un preciso istante, è un numero
intero, che deve essere tanto più grande quanto più la scacchiera è favorevole dal punto
di vista del computer. Per ottenere questo, si deve utilizzare una funzione di valutazione,
chiamata anche euristica, che sintetizzi in un numero la possibilità di vincere da parte
del giocatore computer.
La scelta di tale funzione è molto importante, in quanto rappresenta la strategia di gioco
utilizzata dal computer: possiamo costruire euristiche in modo tale che il computer sia
difensivo, e cerchi di proteggere le zone più sensibili della scacchiera, oppure posiamo
fare in modo che il computer giochi aggressivo, cercando di andare velocemente a dama
ed eliminare una ad una le pedine dell’avversario.
Creare euristiche valide non è assolutamente semplice; la prima che ci può venire in
mente è la seguente:
V = 100(|pedinecomputer|−|pedineplayer|)+200(|damecomputer|−|dameplayer|) (1)
E’ ovvio che non si tratta di una buona funzione di valutazione: alcune configurazioni
della scacchiera potrebbero risultare migliori di altre solo perchè presentano una pedina
del giocatore avversario in meno, non considerando il fatto che le posizioni in cui si
trovano le pedine sono fondamentali per l’esito del gioco. Chiameremo questa funzione
”peso pedine”.
Come ultima osservazione, ricordiamo che il calcolo della funzione di valutazione non
deve impiegare troppo tempo per non degradare le prestazioni del software; si preferiscono
quindi funzioni di valutazioni lineari piuttosto che metodi più complessi.
Per prima cosa, cerchiamo di dare una definizione (o almeno un’idea) di situazione
quiescente.
Una situazione (nel nostro caso, una configurazione della scacchiera) si dice quiescente
se è improbabile che nell’immediato futuro manifesti notevoli oscillazioni.
Per esempio, la configurazione rappresentata in fig. 2, è evidentemente non quiescente
se il turno è del giocatore verde: la sua prossima mossa sarà una cattura doppia con una
conseguente certezza di andare a dama.
Chiaramente si tratta di una verifica strettamente legata alla funzione di valutazione
scelta: se abbiamo scelto una funzione che prende in considerazione solo il numero di
pedine, possiamo decidere di etichettare una situazione come non quiescente se alla
prossima mossa il numero di pedine rimarrà invariato. D’altra parte, se avessimo scelto
3 INTELLIGENZA ARTIFICIALE 7
una funzione di valutazione che dà importanza anche alle posizioni delle pedine nella
scacchiera, allora anche lo spostamento di una pedina verso una posizione strategica-
mente buona (per esempio, vicino a dama) renderebbe la situazione non quiescente.
Abbiamo già parlato del taglio della ricerca. Proprio a causa di tale taglio entra in gioco
la ricerca di quiescenza: tagliando la ricerca a una certa profondità depth, andremo a
valutare anche nodi che non sono quiescenti. La situazione rappresentata in fig. 2, per
esempio, secondo la funzione di valutazione ”peso pedine” è in leggero vantaggio per il
giocatore rosso, visto che presenta una pedina in più. In effetti, però, scegliendo questa
mossa, al passo successivo il giocatore verde farà una cattura multipla, passando quindi
immediatamente in vantaggio. Quindi la valutazione che avevamo fatto sul nostro nodo
non è affatto affidabile.
Per questo motivo è necessario applicare una valutazione solo alle situazioni quiescenti,
mentre per quelle situazioni che non lo sono, si preferisce costruire un albero più pro-
fondo, esplorando mosse successive, fino a quando non si arriva a una situazione quies-
cente da poter valutare. Scendere in profondità fino a quando non si arriva ad avere solo
situazioni quiescenti può essere molto oneroso: per questo motivo si sceglie di tagliare
anche la ricerca di quiescenza.
dobbiamo risalire l’albero e valutare tutti i nodi, fino ad arrivare alla radice. Solo in
questo modo possiamo scegliere la mossa migliore da effettuare a partire dalla radice.
L’algoritmo sfrutta le seguenti assunzioni:
• Si considerano due giocatori, MIN e MAX
• Nel nostro caso, il giocatore MAX è il computer: sceglie ogni volta la mossa che
gli consente di massimizzare la valutazione della situazione di arrivo
• Dualmente, il giocatore MIN è l’avversario, e cerca quindi di minimizzare tale
valutazione (ovvero cerca di rendere minime le nostre probabilità di vittoria)
Il turno di gioco passa alternativamente da MIN a MAX e viceversa, e l’algoritmo
etichetta i nodi dell’albero in modo da garantire per il computer la mossa migliore,
assumendo che l’avversario giocherà al meglio, minimizzando la valutazione.
In fig. 3 si vede l’applicazione dell’algoritmo: partendo dalle foglie, sceglie per il padre
la valutazione minore (in quanto il turno è dell’avversario, e minimizzerà le nostre possi-
bilità di vincita). Applicandolo ricorsivamente, alla prossima iterazione il turno sarà di
max, quindi sceglie la valutazione maggiore (perchè è il computer che sceglie la mossa).
Si vede che viene scelta come mossa migliore la seconda, che mi assicura una valutazione
futura di 8, ma potrebbe diventare 10 a causa di un errore dell’avversario. Viene invece
scartata la mossa n. 3, anche se a causa di un errore dell’avversario mi avrebbe portato
una valutazione maggiore, pari a 15. Ma il nostro algoritmo assume che l’avversario sia
preparato, e giochi bene.
3 INTELLIGENZA ARTIFICIALE 9
O(bm ) (2)
dove b è il branching factor medio dei nodi (ovvero il numero di figli medio per ogni
nodo), mentre m è la profondità dell’albero (depth).
Per quanto riguarda la complessità spaziale, essa equivale alla complessità di una ricerca
in profondità, quindi lineare.
Dalla fig. 4 si può intuire perchè i nodi cancellati sono ininfluenti ai fini del calcolo
dell’algoritmo minimax, e possono quindi essere potati. Quando si arriva a valutare
il nodo foglia con valore 3, abbiamo già etichettato un nodo al livello superiore con il
valore 8. Sappiamo che al turno successivo, ovvero per la valutazione del nodo radice,
si sceglierà il massimo, quindi nodi con valore minore di 8 non verranno considerati.
D’altra parte, valutando il nodo foglia di valore 3, sappiamo che la valutazione del nodo
padre sarà il minimo dei suoi figli, quindi nel nostro caso sarà un valore minore o uguale
a 3. Ma siccome 3 è già un valore più piccolo di 8, sappiamo subito che questo sottoal-
bero non verrà certo scelto come mossa migliore. Possiamo quindi tagliarlo ed evitare
di analizzare gli altri figli.
La miglioria portata dalle potature all’algoritmo minimax dipende ovviamente dall’ordine
in cui analizziamo i nodi. Se avessimo analizzato per primo il nodo foglia di valore 8,
avremo tagliato anche il sottoalbero con le foglie 2 e 5, senza bisogno di analizzarlo.
Non è immediato poter ordinare i nodi senza introdurre ulteriore complessità, e anche il
comportamento dell’algoritmo minimax con l’aiuto di alfa-beta risulta scoraggiante: la
complessità temporale diventa
4 IMPLEMENTAZIONE 10
m
b
O . (3)
log(b)
Il lavoro è ormai finito: la scelta della mossa migliore è immediata. Basta infatti anal-
izzare i figli del nodo radice, e considerare il figlio con valutazione massima. A questo
punto andiamo a vedere quale mossa è stata applicata per generare quel figlio (tale in-
formazione deve essere contenuta nel nodo figlio), e semplicemente la applichiamo.
4 Implementazione
Adesso che sono chiare le modalità di funzionamento degli algoritmi usati per l’intelligenza
artificiale, vediamo come sono stati implementati nel linguaggio C#.
La soluzione più ovvia per l’implementazione della scacchiera è usare una matrice. Più
precisamente, una matrice 8x8 di tipo Casella, quindi ogni elemento della matrice è
un’istanza della classe Casella. La scacchiera viene costruita settando opportunamente
gli attributi delle istanze di Casella, a seconda della posizione dell’elemento. Avremo
quindi alcune caselle di tipo NERA, alcune di tipo FREE, alcune COMPUTER e altre
PLAYER. Questi tipi sono definiti dalla struttura enumerativa casella tipo. Allo stesso
modo, la struttura casella peso indica se la casella (in questo caso un pezzo di un gioca-
tore) è una PEDINA oppure una DAMA.
Questa matrice rappresentante la scacchiera è un attributo della classe Scacchiera; si è
ritenuto necessario definire una classe che contenesse la scacchiera in quanto durante la
costruzione dell’albero, ogni nodo avrà come attributo una diversa istanza della classe
Scacchiera, ciascuna rappresentante la particolare configurazione di pezzi nella damiera.
Alcuni dei metodi più rilevanti della classe Scacchiera sono:
• posizione futura: data una istanza di Casella e una direzione (mossa direction)
ritorna la futura posizione della casella, in termini di row e col;
4 IMPLEMENTAZIONE 11
• mossa possibile multiple: data una istanza di Casella e una direzione, ritorna una
lista di tipo Mossa che rappresenta tutte le mosse possibili a partire da quella
direzione. Sarà analizzata in dettaglio più avanti;
• muovi multiple: data una istanza di Casella e una Mossa, effettua la mossa sulla
scacchiera;
• n caselle player: ritorna il numero di pezzi del giocatore sulla scacchiera, per capire
se il computer ha vinto.
Analizziamo in dettaglio la funzione più interessante che abbiamo descritto fino ad ora:
il metodo mossa possibile multiple della classe Scacchiera. La funzione di costruzione
dell’albero, che simula tutte le mosse possibili per tutte le caselle, chiama il presente
metodo per tutte le direzioni: NE, NO, SE, SO. Questo metodo ritorna un valore
booleano, true o false, a seconda che la mossa sia possibile o meno.
La prima fase è controllare se con la mossa proposta si esce o meno dalla scacchiera. In
caso positivo, si va a vedere se la mossa è legale: per esempio, le pedine del computer
non possono muovere verso Nord, cosı̀ come quelle del player non possono muovere verso
Sud, finchè non diventano dame. Se la mossa risulta legale, si prova a vedere se la casella
di arrivo è libera. In tal caso, abbiamo trovato una mossa semplice (priorità = 0) e si
esce.
Se invece la mossa semplice non è possibile, perchè la casella di arrivo è occupata, può
presentarsi possibilità di mangiare un pezzo: se la pedina nella posizione di arrivo ap-
partiene all’avversario, e la casella ancora successiva è libera. In questo caso, dobbiamo
controllare se sono possibili catture consecutive, richiamando ricorsivamente il metodo
4 IMPLEMENTAZIONE 13
Questa funzione ritorna, insieme al valore booleano, una lista di mosse perchè nel caso
di catture multiple la pedina potrebbe poter scegliere tra due o più pedine da mangiare
al secondo step, dopo la prima cattura. Queste sono mosse con la stessa priorità e quindi
tutte legali.
IDamaEngine è la classe che si occupa della strategia di gioco del computer. Di fatto è
la classe che comunica con la parte grafica del programma, come spiegato in dettaglio
più avanti. Essa è definita come ”partial class”, ovvero come classe parziale, dove l’altra
parte della classe è chiamata Euristiche.
Gli attributi sono, ovviamente, una istanza della classe Scacchiera (master), e altre carat-
teristiche definite dall’utente: la profondità massima dell’albero che verrà creato (dMax),
la funzione euristica scelta (funzione euristica), e due variabili booleane (quiescenza e
quiescenzaricorsiva).
Quando è il turno del computer, la parte grafica del programma invoca la funzione
alfabetaPruning che si occupa di costruire l’albero, valutarlo, applicare la verifica di
quiescenza, applicare l’algoritmo minimax ed effettuare la mossa. Vediamo questi passi
in dettaglio.
Per la costruzione dell’albero, viene chiamata la funzione costruisci albero con il parametro
master, ovvero la scacchiera al momento attuale. Tale funzione inizializza l’albero,
costruendo il nodo radice proprio con l’istanza master. Poi chiama la funzione ricor-
siva costruisci albero.
Inizialmente si cerca la mossa possibile con la priorità maggiore; successivamente, si
aggiunge un figlio per ogni mossa legale (quindi si aggiunge un figlio per ogni mossa
possibile di priorità non minore alla priorità massima calcolata). Per ogni figlio creato,
si chiama ricorsivamente la stessa funzione, fino a quando non si raggiunge la profondità
massima stabilita.
L’albero viene poi valutato, applicando alle foglie una funzione di valutazione, tra quelle
descritte nel capitolo successivo.
Abbiamo già parlato di funzioni di valutazione in quanto euristiche, e della loro impor-
tanza ai fini della strategia di gioco della macchina. Nel software sono state implementate
quattro diverse funzioni di valutazione:
1. Peso Pedine
2. Peso + Posizione
3. Spettacolo
4 IMPLEMENTAZIONE 15
4. Fully Guarded
La prima funzione di valutazione, Peso Pedine, valuta una configurazione della scacchiera
ignorando le posizioni delle pedine, ma contandone solo il numero. Alle dame è attribuito
un peso doppio rispetto a quelle delle pedine; i pezzi appartenenti al computer vengono
sommati, mentre quelli appartenenti al player vengono sottratti dalla valutazione. Gio-
cando con questa strategia, ci si accorge che è un po’ troppo semplicistica; per esempio,
il programma ci permetterà facilmente di avvicinarci a dama se gli permetteremo di farci
catturare una pedina.
La funzione Peso + Posizione include nel computo anche un valore legato alla posizione
delle pedine. Il peso dei pezzi viene moltiplicato per il quadrato dell’indice relativo alla
riga in cui si trova il pezzo. In questo modo si preferiscono configurazioni in cui le i
pezzi del computer vanno verso dama, e allo stesso modo si preferisce che le pedine del
computer non si avvicinino troppo alla nostra base. Inoltre viene attribuita una penalità
alle dame che stanno sui bordi, per incitarle a porsi in mezzo alla damiera, per rendere
la strategia più aggressiva. Anche questa funzione di valutazione non ci assicura buone
giocate: tende a scoprire velocemente le sue posizioni di base, per andare verso il centro
della damiera, rendendo cosı̀ il player più facilitato a fare dama.
Per realizzare la terza funzione di valutazione, Spettacolo, sono state utilizzate al-
cune considerazioni che sono state documentate in rete. L’idea sfrutta la geometria
della damiera, che presenta delle regioni più facilmente proteggibili contro gli attacchi
dell’avversario ed altre più vulnerabili. La damiera può essere vista come divisa in quat-
tro aree: l’angolo in alto a destra e quello diametralmente opposto in basso a sinistra
vengono definiti cantoni, mentre i due rimanenti sono definiti biscacchi.
base e con punte avanzate ben appoggiate. Questa frase riassume il punto centrale della
strategia che è stata realizzata: si è provato a muovere le pedine, facendole avanzare verso
dama in formazione offensiva, ma cercando nel contempo che tale formazione fosse ben
salda alla base, cosı̀ da poter sfondare le linee avversarie, mantenendo le proprie spalle
coperte. Per realizzare la strategia, si è costruito una funzione per il calcolo del supporto,
ossia delle pedine che si trovano alle spalle di altre. La funzione scansiona la damiera
cercando se nelle posizioni dietro la pedina selezionata lungo le diagonali, compaiono
pedine dello stesso colore e se questo accade continua a controllare all’indietro ricorsi-
vamente fino al raggiungimento della base. Ogni volta che trova una tale situazione per
una propria pedina aumenta il valore della funzione di valutazione, privilegiando i casi in
cui si presenta una posizione delle proprie pedine che ricorda una forma a piramide con
la base ben saldata sulla linea di base. In tal modo si promuovono quelle configurazioni
ben saldate alla base, penalizzando le altre. Inoltre per ogni pedina si è aggiunto un
valore in base alla posizione occupata all’interno della damiera, privilegiando quelle più
vicine alla dama, e si sono penalizzate le configurazioni che prevedevano le dame vicino
ai bordi laterali della scacchiera, preferendo che ricoprissero ruoli centrali più offensivi.
In tutte le funzioni si aggiunge una piccola quantità aleatoria, per evitare che il pro-
gramma esegua sempre la stessa mossa in caso di mosse con identica valutazione.
Una volta valutate le foglie dell’albero, per ogni foglia si fa la verifica di stato quiescente.
Se ne occupa la funzione is quiescent, che di fatto, data la foglia da verificare, costruisce
un albero di profondità 2 a partire da quella foglia, usando proprio la stessa funzione
costruisci albero. Per prima cosa, si valutano le foglie di questo albero. A questo punto,
viene usato l’algoritmo minimax con potatura alfa-beta (lo stesso di cui parleremo tra
poco) per valutare tutti i nodi dell’albero. Se la valutazione del nodo foglia cosı̀ calcolata,
si discosta molto (negativamente) dalla precedente valutazione associata al nodo foglia
di cui stiamo verificando la quiescenza, si dice che la foglia non è uno stato quiescente.
In questo caso, possiamo decidere di richiamare (ricorsivamente) la stessa funzione, per
esplorare ancora più in profondità l’albero creato, nella speranza di arrivare a configu-
razioni stabili (quiescenti).
Fatto ciò, se non abbiamo trovato configurazioni quiescenti, siamo costretti ad ”appen-
dere” l’albero creato all’albero di ricerca creato inizialmente (con la funzione AddSot-
toAlbero della classe Tree), aumentandone quindi la profondità totale.
La decisione della quiescenza o meno di una configurazione dipende strettamente dalla
funzione di valutazione utilizzata. Sono state definite quindi tante funzioni per prendere
questa decisione quante sono le euristiche implementate.
Adesso che l’albero è totalmente etichettato, basta analizzare tutti i figli del nodo radice
(ovvero tutti i nodi a profondità uno). Consideriamo quindi il nodo che ha la valutazione
maggiore; da tale nodo estraiamo la mossa associata ed il gioco è fatto. Basta richia-
mare la funzione muovi multiple sulla scacchiera, passando come parametro la mossa in
questione.
Tale funzione si occuperà di seguire in dettaglio le direzioni proposte dalla mossa, elim-
inando i pezzi catturati e riconfigurando opportunamente le caselle della scacchiera. In
seguito viene richiamata la procedura che si occupa di visualizzare la mossa effettuata,
quindi di aggiornare la scacchiera sul video.
5 Conclusioni
Per ottenere giocate sensate da parte del computer, è necessario attivare la verifica di
quiescenza a due livelli, con una profondità dell’albero di ricerca almeno pari a 3 (di
fatto, l’albero sarà in questo caso profondo 6). La strategia che sembra essere la migliore
è l’ultima tra quelle analizzate, Fully Guarded. Con questi parametri, la risposta del
programma sarà molto lenta, non solo a causa delle dimensioni dell’albero da valutare,
ma anche a causa dell’analisi delle mosse possibili. C’è da dire che, analizzando le mosse
possibili, in molti casi l’albero di ricerca generato è significativamente ridotto, il che
porta la valutazione ad essere estremamente veloce.
Ricordando la regola che in caso di più mosse possibili si debba scegliere quella che
garantisce il numero massimo di pezzi catturati, si potrebbe pensare che in realtà non è
necessario analizzare la legalità delle mosse prima della costruzione dell’albero, ma sem-
plicemente la ricerca dell’ottimo porterebbe a scegliere la mossa che garantisce il numero
massimo di pezzi catturati. Questo è estremamente falso, in quanto:
1. a causa della profondità dell’albero di ricerca, potrebbe essere conveniente non
eseguire una cattura per migliorare la funzione obiettivo nelle mosse successive;
2. potrebbe essere conveniente non eseguire una cattura per mantenere la pedina in
5 CONCLUSIONI 21
La prima grande impresa relativa all’intelligenza artificiale associata al gioco della dama
risale al 1952, quando Arthur Samuel dell’IBM sviluppò un programma per la dama che
apprese la sua funzione di valutazione giocando da solo per migliaia di volte.
Nel 1989, all’Università di Alberta, sotto la coordinazione del prof. Jonathan Schaeffer,
un gruppo di studiosi comincia a concentrarsi sul problema della dama. Nasce quindi
Chinook, che vince gli U.S. Open nel 1992. Il programma usa, tra l’altro, una ricerca
alfa-beta combinata con un database di soluzioni perfette per tutte le posizioni con sei
pezzi. Nel 2004 vince il campionato del mondo, e nel 2006 il programma è stato costretto
al ritiro per manifesta superiorità.
Nel 2007, finalmente, l’equipe di studiosi ha affermato di aver risolto il gioco della dama,
con il loro programma: Chinook non può perdere, quindi qualsiasi umano provi a sfidarlo,
può al massimo pareggiare.
REFERENCES 22
References