Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
AI E PRODOTTI VIDEOLUDICI
Invece il numero medio di mosse per turno (con tutti i pezzi ancora sulla scacchiera) si
calcola sommando il numero medio di mosse di ogni singolo pezzo (1 il pedone, 5 il
cavallo, 8.5 l’alfiere, 14 la torre, 22,5 la regina e 6,5 il re) sempre per il numero di pezzi:
In pratica però questo numero sarà sempre inferiore perché non ha in considerazione la
mancanza dei pezzi dalla scacchiera, situazione molto possibile verso metà partita, o
anche il fatto che alcuni pezzi potrebbero limitare i movimenti di altri essendo sulla loro
traiettoria. Tendenzialmente si parla di 30-40 mosse in una posizione media. Per
semplificare i calcoli si considera che ogni volta che ciascuno muove ha a disposizione 20
possibilità e che la partita abbia fine al raggiungimento di 40 mosse. Quindi facendo i
calcoli il numero di posizioni possibili è:
Con un calcolo ancora più accurato si è dimostrato che il numero totale di posizioni in una
partita da 40 mosse è:
Per dare un valore più concreto alla grandezza di questo numero, si pensi che i computer
attuali eseguono 10^18 operazioni al secondo e che un anno è composto da 3.15*10^7
secondi. Ipotizzando che si ha modo di analizzare 10^8 posizioni al secondo, si può
calcolare il numero di anni che sono necessari per analizzare le 10^43 posizioni:
Quindi utilizzando uno dei processori moderni servirebbero 3.17*10^17 anni per analizzare
tutte le posizioni utilizzabili. Facendo un confronto, l’universo ha 10^10 anni circa.
Però il numero di posizioni conterebbe anche alcune posizioni illegali, per esempio il re
che viene messo sotto scacco, l’avanzamento di due caselle dei pedoni dove però esclude
la promozione dei pedoni in nuove unità. Tenendo conto degli aggiustamenti elencati
sopra Victor Allis calcolò un limite maggiore di 5*10^52 e un valore reale di 10^50
posizioni. Però attraverso programmi più recenti è stato fatto successivamente un upper
bound riguardo il calcolo del numero di posizioni:
Quindi 10^123 possibili partite, ci fu un calcolo simile di questo valore effettuato dal
matematico Claude Shannon che fu 10^120 e venne chiamato in suo onore “numero di
Shannon” . Questo numero è maggiore ad un googol (10^100) ed anche al numero di
atomi osservabili nell’universo che è una stima tra 4*10^79 e 10^81. Il che ha portato alla
conclusione che al momento è impossibile risolvere il gioco degli scacchi.
3.3 L’albero di gioco degli scacchi e i suoi algoritmi.
Per descrivere a livello grafico i giochi di tipo sequenziale come gli scacchi si utilizza un
albero di gioco, con i nodi che rappresentano le posizioni mentre gli archi le conseguenti
mosse legali. In questo albero la radice rappresenta la posizione iniziale dei pezzi
all’interno della scacchiera, i figli le possibili posizioni raggiungibili dalle mosse legali e le
foglie sono le posizioni finali. Come visto in precedenza la radice possiede venti figli,
mentre la media dei figli per ogni nodo si aggira tra i trenta e i quaranta. Il numero delle
partite possibili secondo la stima di Shannon vista in precedenza è 10^120 (quindi il
numero di nodi), mentre le diverse posizioni possibili 10^43, valori che sono impensabili da
calcolare ed analizzare per i calcolatori. Quindi l’analisi va limitata ad un albero parziale
che per ottenerlo si utilizzano due strategie principali, dette anche “strategie di Shannon”:
- Strategia di tipo A: esplorazione di tipo per “forza bruta”. Si sfrutta l’effetto orizzonte,
ovvero si valuta ogni mossa possibile per ogni posizione nella scacchiera fino ad un
determinato livello dell’albero di gioco. Negli ultimi tempi un computer ottimizzato
appositamente per l’analisi dell’albero di gioco può arrivare ad esplorare circa alberi
profondi 12/24 semimosse in un tempo di 3 minuti, ovvero il tempo medio di una mossa in
torneo.
-Strategia di tipo B: esplorazione con tipo di valutazione euristica. Si cominciano a valutare
per ogni posizione solo le mosse più “interessanti”; quindi, seguendo una certa euristica si
comincia a valutare quali siano le mosse migliori e quindi tralasciando rami che portano ad
altre mosse. Così questo tipo di strategia dà la possibilità di analisi più profonde nell’albero
di gioco.
Per il primo ventennio (tra il 1955 e il 1975) la ricerca si è focalizzata sulle strategie di tipo
euristico, però non fu mai scoperta una combinazione potente abbastanza per poter
stabilire quali fossero le mosse da utilizzare e quali da scartare. Quindi per analizzare
l’albero di gioco si passò all’utilizzo della strategia di tipo “forza bruta”, rappresentando in
un albero con nodi di un certo peso tutte le possibili evoluzioni del gioco partendo da una
determinata mossa. Per raggiungere questa soluzione viene utilizzato un algoritmo
chiamato minimax, che viene dal teorema del minimax di John Von Neumann. L’algoritmo
funziona scegliendo ogni mossa possibile così da ridurre al minimo la quantità dei
vantaggi massimi che l’avversario può ottenere. Come può farlo? L’algoritmo esplora fino
all’ “effetto orizzonte” tutti i possibili nodi dell’albero e misura la qualità dell’ultima posizione
raggiunta attraverso una valutazione posizionale. Visto che l’algoritmo ha come obiettivo
quello di ridurre al minimo il valore della migliore posizione che l’avversario può
raggiungere, il peso della mossa è direttamente proporzionale a quanto la mossa stessa
diminuisce il valore della posizione dell’avversario. Utilizziamo per convenzione +∞ e -∞
per simboleggiare le mosse che portano allo scaccomatto di un giocatore o del suo
avversario. Chiamiamo il giocatore Max e il suo avversario Min, analizziamo ora lo
pseudocodice dell’algoritmo minimax:
L’algoritmo ha in input il nodo che deve analizzare e la massima profondità che è possibile
analizzare dall’albero e in output il valore del nodo che viene dato, così che il giocatore
sceglie la mossa che impatta al più la contromossa dell’avversario, minimizzandone gli
effetti. Nella successiva immagine c’è una dimostrazione del funzionamento dell’algoritmo
minimax:
L’algoritmo utilizzando la funzione di valutazione comincia a stabilire i pesi dei nodi nel
livello più basso dell’albero. Dopo di che li direziona verso l’alto secondo le regole del
minimax. Se nel penultimo livello deve muovere Max (gli insiemi neri come da figura),
significa che i nodi in quel livello raffigurano il massimo delle valutazioni dei loro rispettivi
figli. Quindi se prendiamo per esempio il nodo -8 e -5, ci andrà il peso maggiore ciò -5.
Successivamente tocca a Min che prenderà il valore minimo nel livello, quindi tra -5 e 11
prenderà -5. Questo processo dell’algoritmo continua a fare valutazioni di minimi e
massimi dei figli assegnandoli ai genitori, fino a che non si raggiunge la radice, la quale nel
nostro caso sceglie il nodo con valore massimo (ovvero 4, tra 4 e -5), ovvero il nodo che
permette di minimizzare la massima perdita.
L’ipotesi alle fondamenta di questo metodo implica che più l’albero da valutare è profondo
e più aumenta l’efficacia dell’algoritmo. Al contrario delle aspettative, ovvero se un albero
ha profondità maggiore risulta più difficile valutarne le posizioni finali, studi pratici ci danno
conferma che programmi con hardware più veloci sconfiggono sistematicamente
programmi con hardware più lenti, per quanto riguarda l’analisi estesa dei nodi.
C’è un modo per poter semplificare il minimax che viene chiamato negamax. L’algoritmo in
questione utilizza il fatto che nei giochi a somma zero max(a,b) = -min(-a,-b). Più
dettagliatamente nel nostro caso la posizione di un giocatore è la negazione della
posizione dell’avversario, andando così a non esserci il bisogno di distinguere tra il
giocatore Min e Max nel percorso di propagazione dei valori verso la radice, ma
semplicemente attribuendo al nodo padre il massimo dei valori dei figli con segno
cambiato, semplificando il processo rispetto al minimax, dove era necessario calcolare il
massimo e il minimo in modo alternato, dove qui invece ci basta un solo calcolo per dare il
valore che ci serve ad ogni posizione. Lo pseudocodice del negamax è il seguente:
La complessità degli algoritmi visti è O(bd), dove b rappresenta il branching factor (la
media di figli per nodo coincidente al numero medio di mosse per posizione) e d
rappresenta la profondità dell’albero.
Un altro algoritmo utilizzato è l’AlphaBeta, il quale deriva dai due precedenti algoritmi,
osservando come essi eseguono una visita completa dell’albero fino al livello orizzonte,
valutando però anche nodi che non contribuiscono oggettivamente alla valutazione della
radice non influendo sulla mossa ideale da prendere. L’algoritmo, quindi, idealizza di
tagliare i rami che non vanno a influenzare la valutazione alla fine, producendo due effetti
positivi: la complessità di ricerca è drasticamente ridotta, ed essa quindi va ad influenzare
anche alla riduzione dei tempi di ricerca. Ma come funziona? Prima di tutto si esegue una
ricerca di tipo depth-first-search (di profondità) da sinistra a destra, successivamente si
La torre ha la sua maggiore efficacia nel medio gioco e nella parte finale, perché
posizionata agli angoli della scacchiera e coperta dai pedoni laterali, che solitamente sono
gli ultimi ad essere mossi. Come detto anche in precedenza con i pedoni, i giocatori
tendono ad avere il controllo delle zone centrali, lasciando le zone laterali in secondo
piano, visto che le zone centrali permettono uno sviluppo più rapido e impattante del
gioco.
Esistono poi 8 posizioni dove il cavallo controlla 3 caselle, esistono 20 posizioni dove ne
controlla 4, esistono 16 posizioni dove ne controlla 6 ed infine ne esistono 16, quelle
centrali dove ne controlla 8.
Perciò andiamo a sommare le seguenti caselle e dividiamo il tutto per la cardinalità di Σ:
Allo stesso modo del cavallo, la forza dell’alfiere è maggiore al centro della scacchiera,
rendendolo un pezzo fondamentale e molti efficace ad inizio partita, perdendo poi efficacia
nel medio gioco dove è circondato da molti più pezzi che limitano e vincolano i suoi
movimenti, tornando infine un pezzo fondamentale verso la fine del gioco quando la
maggior parte dei pezzi non c’è più, essendo in grado di raggiungere ogni angolo della
scacchiera molto rapidamente.