Fidarsi del codice che non hai scritto
Ho cambiato l'AI del mio gioco e tutte le metriche sono migliorate. Poi ho messo la versione nuova contro quella vecchia, e ha perso otto a sedici.
di Nicola Sabaini 4 min di lettura Progetto: ExaWar
Il 16 settembre ho cambiato il comportamento dell’intelligenza artificiale di ExaWar, il mio gioco di strategia a turni. Poi ho lanciato il solito lotto di partite simulate per vedere com’era andata.
Le catture erano salite. Le partite finivano in meno turni. Quasi ogni numero che guardo di solito si era mosso dalla parte giusta.
Poi ho messo la versione nuova contro quella vecchia, una di fronte all’altra. Ha perso otto a sedici.
Il lotto non stava misurando la forza
In un lotto normale le partite sono macchina contro macchina, e la modifica ce l’hanno tutte e due. Se rendo l’attacco più deciso, lo divento da entrambe le parti: il tasso di vittorie non si muove, perché descrive il confronto e non la modifica.
Intanto le metriche assolute possono salire tutte insieme mentre la squadra si indebolisce. Più catture vuol dire anche più unità mandate allo sbaraglio, e la partita più corta è quella che perdi prima.
L’unica domanda che conta è se la versione nuova batte quella vecchia, e per rispondere bisogna dare la modifica a una parte sola.
Quella lezione è finita dentro il file di istruzioni del progetto, quello che apriamo all’inizio di ogni sessione io e la macchina con cui lavoro: le modifiche al comportamento dell’AI si validano in scontro diretto. Non l’ho scritto perché me lo ero dimenticato. L’ho scritto perché fra sei mesi me lo dimenticherò.
Non è una storia sull’AI di un gioco
Quel codice l’avevo scritto insieme a una macchina, come faccio quasi sempre adesso. E la domanda che si sente in giro, «l’AI scrive buon codice?», quel giorno non mi sarebbe servita a niente.
Era buono. Faceva esattamente quello che gli avevo chiesto. Era la cosa chiesta a essere sbagliata, e non me l’ha detto una rilettura attenta: me l’ha detto un confronto che poteva benissimo non aver fatto.
Serve un’altra domanda. Com’è fatto un progetto in cui puoi accettare codice che non hai scritto? Vale per il codice della macchina, per quello di un collega, e per quello che hai scritto tu a marzo, che ormai è di un altro.
Rendere impossibile, invece che sconsigliato
Un consiglio si dimentica. Un vincolo scritto nel codice no.
Nel motore di ExaWar i punti ferita non possono scendere sotto zero: la funzione che li toglie li blocca lì. Le risorse non vanno in negativo. I punti azione neanche. Nessuna di queste tre cose è affidata a chi scrive la prossima riga.
Quando si salva non si riscrive mai il file esistente: se ne scrive uno temporaneo, lo si forza su disco e solo allora prende il posto del vecchio. Se la macchina si spegne a metà, il salvataggio buono è ancora lì.
Dentro il gioco c’è una console con un suo filesystem, che vive in memoria e non tocca i file veri del computer. Il suo linguaggio non ha modo di eseguire testo arbitrario. Non è una regola di buon senso da rispettare: è una cosa che lì dentro non si può fare.
Nel multiplayer decide il server. Il client non prevede il risultato delle mosse, lo chiede, e ogni riga che passa dopo la stretta di mano è firmata. Un client modificato non diventa più forte: diventa un client che dice cose che il server non accetta.
Quando lavori con qualcuno che produce molto più in fretta di te, questa è la differenza fra un progetto che regge e uno che si sgretola sotto il proprio peso. Non serve che la macchina sia prudente. Serve che le cose pericolose siano fuori portata.
Un cancello solo
Prima di ogni commit gira un comando unico, che mette in fila quattro cose: il linter, la parità delle cinque lingue, la validazione delle missioni della campagna e la suite di test. Centoquarantuno file di prove, milleseicentonovanta test, due minuti e sedici secondi.
Un aggancio all’editor passa il linter su ogni file Python appena modificato, così gli errori si vedono subito e non a fine giornata.
E una riga, scritta in cima al file di istruzioni, che vale per me come per la macchina: mai procedere con i test rossi.
Due minuti e sedici secondi è il prezzo intero. È meno di quanto ci metto a rileggere un diff di trecento righe, e trova cose che rileggendo non troverei.
Il codice che non ho scritto non mi preoccupa. Mi preoccupa il codice che nessuno può bocciare.