Esiste un tale algoritmo in cui, se dotato di una potenza di elaborazione infinita, un computer potrebbe giocare a scacchi perfettamente in modo da non perdere mai?
In tal caso, dove posso trovare lo pseudo codice per esso?
Esiste un tale algoritmo in cui, se dotato di una potenza di elaborazione infinita, un computer potrebbe giocare a scacchi perfettamente in modo da non perdere mai?
In tal caso, dove posso trovare lo pseudo codice per esso?
Risposte:
Esiste un algoritmo? Sì. Secondo il Teorema di Zermelo , ci sono tre possibilità per una partita a due giocatori deterministica a informazioni perfette finite come gli scacchi: o il primo giocatore ha una strategia vincente, oppure il secondo giocatore ha una strategia vincente, o entrambi possono forzare un pareggio. Non sappiamo (ancora) quale sia per gli scacchi. (Dama invece è stata risolta : entrambi i giocatori possono forzare un pareggio.)
Concettualmente, l'algoritmo è abbastanza semplice: costruisci un albero di gioco completo , analizza i nodi foglia (le posizioni finali del gioco) e fai la mossa iniziale vincente, rassegna le dimissioni o offri un pareggio.
Il problema sta nei dettagli: ci sono circa 10 43 posizioni possibili e un numero ancora maggiore di mosse (la maggior parte delle posizioni può essere raggiunta in più di un modo). Hai davvero bisogno del tuo computer infinitamente potente per trarne vantaggio, dal momento che un computer che può trarre vantaggio da questo algoritmo o non può adattarsi all'universo conosciuto, o non finirà il calcolo fino a qualche tempo dopo la fine dell'universo.
Vedi https://en.wikipedia.org/wiki/Endgame_tablebase .
Con la potenza infinita del computer, si potrebbe costruire una tabella del genere per la posizione iniziale e risolvere gli scacchi .
In pratica, solo le posizioni con un massimo di sette "uomini" (pedine e pezzi, contando i re) sono state risolte usando gli attuali supercomputer, quindi siamo molto lontani dal risolvere gli scacchi. La complessità del problema aumenta esponenzialmente con il numero di pezzi.
Se avessi davvero una potenza di elaborazione infinita , un tale algoritmo sarebbe in realtà banale da scrivere. Dato che gli scacchi hanno un numero finito di stati possibili, in teoria si potrebbe semplicemente scorrere attraverso di essi fino a trovare un percorso di gioco perfetto. Sarebbe terribilmente inefficiente, ma se hai una potenza di elaborazione infinita , non importerebbe.
Per rispondere direttamente alla domanda: sì, esiste un tale algoritmo. Si chiama minimax. (I tablebase di endgame sono generati usando questo algoritmo (indietro!), Ma il semplice vecchio algoritmo minimax minimo è tutto ciò di cui hai bisogno). Questo algoritmo può giocare perfettamente a qualsiasi gioco a somma zero per due giocatori. Trova pseudocodice qui:
https://en.wikipedia.org/wiki/Minimax
si noti che le varianti di questo algoritmo sono utilizzate dai moderni programmi di scacchi per computer.
Non solo esiste un algoritmo per giocare a scacchi perfetti, ma è anche possibile scrivere un breve programma che (con infinite risorse) giocherà perfettamente a qualsiasi gioco deterministico a due giocatori di durata finita .
Il motore di gioco non ha nemmeno bisogno di conoscere le regole del gioco a cui sta giocando. Tutto ciò di cui ha bisogno è una rappresentazione opaca di uno "stato di gioco" e funzioni che (a) dato qualsiasi stato di gioco, forniscono un elenco di stati di gioco successivi legali e (b) dato uno stato di gioco, decidono se si tratta di una vittoria per il giocatore 1 , una vittoria per il giocatore 2, un pareggio o non è uno stato finale.
Date queste funzioni, un semplice algoritmo ricorsivo "risolve" il gioco.
Questo fatto è stato accennato nelle risposte precedenti da chessprogrammer (minimax) e da Acccumulation (che fornisce una versione del programma in python).
Ho scritto un programma del genere più di 20 anni fa. L'ho provato suonando noughts and crosses (tic-tac-toe se sei americano). Abbastanza sicuro ha giocato un gioco perfetto.
Naturalmente questo cadrà rapidamente su qualsiasi computer immaginabile per qualsiasi gioco serio. Poiché è ricorsivo, sta effettivamente costruendo l'intero albero di gioco in pila, quindi otterrai uno "overflow dello stack" (gioco di parole molto inteso) prima di arrivare ovunque vicino all'analisi dei 10 ^ 123 stati degli scacchi a cui si fa riferimento in altre risposte. Ma è divertente sapere che in linea di principio questo piccolo programma farebbe il lavoro.
Per me questo dice anche qualcosa di interessante sull'intelligenza artificiale: per quanto molta "intelligenza" pensi che sia esibita da Deep Blue, o Go Zero, o in effetti da un umano che gioca a scacchi o vai, c'è un senso in cui questi giochi hanno un'ottimale banale, esattamente calcolabile soluzioni. La sfida è come ottenere una soluzione buona ma non ottimale in un tempo ragionevole.
Ignorerò le possibilità di estrazioni o sequenze infinite di mosse per semplicità. Una volta compreso l'algoritmo, non è particolarmente difficile estenderlo a questi casi.
Innanzitutto, alcune definizioni:
Ogni mossa che vince il gioco per il giocatore che fa quella mossa è una mossa vincente.
Ogni mossa che perde il gioco per il giocatore che fa quella mossa è una mossa perdente.
Ogni mossa che lascia l'altro giocatore con almeno una mossa vincente è anche una mossa perdente. (Dal momento che l'avversario può prendere quella mossa e forzare una perdita.)
Ogni mossa che lascia l'altro giocatore con solo mosse perdenti è anche una mossa vincente. (Non importa quale mossa faccia il tuo avversario, vincerai.)
Una strategia perfetta significa fare sempre mosse vincenti se ne rimangono e dimettersi quando rimangono solo mosse perdenti.
Ora, è banale scrivere una strategia perfetta. Basta esplodere tutte le possibili sequenze di mosse e identificare le mosse vincenti / perdenti. Ignorando la situazione di stallo, questo alla fine identificherà ogni mossa come mossa vincente o mossa perdente.
Ora, la strategia è banale. Guarda tutte le tue mosse possibili. Se rimangono delle mosse vincenti, prendine una e vinci. Se rimangono solo le mosse perdenti, dimettiti, poiché il tuo avversario può costringerti a perdere.
Non è difficile adattare la strategia per includere la possibilità di una situazione di stallo.
Aggiornamento : nel caso in cui non sia chiaro come questo identifichi ogni mossa come una mossa vincente o perdente, considera:
n
il numero di mosse nella partita a scacchi più lunga possibile. (Per ora stiamo ignorando le sequenze illimitate, anche se includerle non è difficile.)n
mosse precedenti che dobbiamo considerare.n-1
mosse precedenti è una mossa vincente o perdente poiché le n
mosse terminano il gioco più lungo.n-2
è seguita solo da mosse vincenti o mosse perdenti e quindi è essa stessa una mossa vincente o una mossa perdente.1. d4
con ...resigns
?
Supponiamo di avere tre funzioni: win_state
, get_player
, e next_states
. L'input per win_state
è uno stato di gioco e l'output è -1 se il bianco è in scacco matto, 0 se è un pareggio, 1 se il nero è in scacco matto, e None
altrimenti. L'input per get_player
è uno stato di gioco e l'output è -1 se è il turno del nero e 1 se è il turno del bianco. L'input per next_states
è un elenco di possibili stati di gioco successivi che possono derivare da una mossa legale. Quindi la seguente funzione, quando viene dato uno stato di gioco e un giocatore, dovrebbe dirti in quale stato di gioco passare per quel giocatore per vincere.
def best_state(game_state,player)
def best_result(game_state):
if win_state(game_state):
return(win_state)
else:
player = get_player(game_state)
return max([best_result(move)*player for move in next_states(game_state)])*player
cur_best_move = next_states(games_state)[0]
cur_best_outcome = -1
for state in next_states(game_state):
if best_result(state)*player > cur_best_outcome:
cur_best_outcome = best_result(state)*player
cur_best_move = state
return(best_move)
Sì. È facile. Non hai nemmeno bisogno di una potenza di elaborazione infinita. Tutto ciò di cui hai bisogno è una tabella di consultazione che contiene, per ogni possibile posizione del tabellone, la mossa migliore per giocare in quella posizione. Ecco lo pseudo-codice:
def play-move(my-color, board-position):
return table-of-best-moves[my-color, board-position]
L'unico problema è che questo tavolo di consultazione dovrebbe essere molto, molto grande - forse più grande della galassia della Via Lattea - e ci vorrebbe molto tempo per costruirlo - forse più lungo dell'era attuale dell'universo, a meno che non ci sia un po 'di regolarità da scoprire negli scacchi che lo rende molto più semplice di quanto possiamo vedere in questo momento. Ma se avessi questa tabella di consultazione, la subroutine per scegliere una mossa perfetta ogni volta potrebbe essere implementata in appena un'istruzione CPU.
Inoltre, data la nostra attuale conoscenza degli scacchi, non c'è modo di essere sicuri che il gioco perfetto garantisca che non perderai. Ad esempio, se il gioco perfetto garantisce una vittoria per il Bianco, il Nero perderebbe anche se il Nero gioca perfettamente.