BooMfire: il mio programma per il 13° BASIC 10Liner Contest

Quest’anno non sono riuscito a trovare il tempo per realizzare nuovi giochi per il BASIC 10 Liner Contest, così ho ripreso e completato una vecchia idea, su cui avevo iniziato a lavorare qualche tempo fa: ispirato dal programma per MSX sviluppato da Roberto Capuano per l’11a edizione del contest, ho implementato una mia versione del noto effetto DOOM Fire, per ZX Spectrum. Per ottenere un’animazione fluida, ho abbandonato l’interprete Sinclair BASIC dello ZX Spectrum e mi sono affidato al compilatore ugBASIC di Marco Spedaletti. Il risultato è BooMfire, una demo realizzata in 9 linee di codice e candidata per la categoria SCHAU.

Penso che il risultato, che puoi osservare nel seguente video, non sia male:

Video che mostra BooMfire in azione (emulatore Fuse)

All’avvio del programma, viede disegnato il logo “BOOM“, per mezzo un algoritmo simile a quello utilizzato dal Kickstart dei computer Amiga per visualizzare l’immagine di richiesta inserimento floppy disk. Per lo riempimento, non ho utilizzato l’isitruzione PAINT di ugBASIC, ma ho implementato una subroutine che permettesse anche la riproduzione di una musica di sottofondo, per rendere meno noiosa l’attesa. Tale subroutine è basata sulla tecnica ricorsiva descritta nell’articolo A Fast Well-Behaved Pattern Flood Fill di Alvin Albrecht. A proposito di musica, il suono è riprodotto tramite chip AY-3-8912, per cui per apprezzare appieno la demo, non è sufficiente lo ZX Spectrum 48K, ma è necessario un modello avanzato (128K, +2, +3, Next, …).

L’animazione delle fiamme è la mia implementazione dell’effetto originariamente introdotto sulla versione di Final DOOM per Playstation, ovviamente riadattata per il computer Sinclair. L’animazione non lavora a livello di pixel, ma di carattere (8×8 pixel) e, mediante la pressione dei tasti 1, 2, o 3, è possibile simulare tre diversi livelli di sovrapposizione tra le fiamme e la scritta “BOOM“. Questo è stato possibile scegliendo opportunamente i colori di carta e inchiostro nelle tre corrispondenti “tavolozze”.

Puoi provare BooMfire utilizzando l’emulatore online oppure scaricarlo per eseguirlo su un emulatore o su un vero ZX Spectrum semplicemente accedendo alla pagina del progetto su retrobits.itch.io. Se sei interessato ad approfondire il funzionamento di BooMfire, puoi dare un’occhiata alla documentazione, corredata di codice sorgente commentato e inclusa nel download.

Enjoy the SCHAU!

Link e riferimenti

Read in English

La sfida di Natale, edizione 2023

Logiker ha appena presentato i risultati dell’edizione 2023 della Vintage Computing Christmas Challenge (VC³ 2023), un’interessante concorso non competitivo di programmazione, orientato principalmente ai sistemi vintage, che si svolge nel periodo natalizio.

L’obiettivo è la realizzazione di un programma in grado di rappresentare fedelmente la seguente immagine, utilizzando un codice più compatto possibile:

Screenshot dell'immagine da realizzare per la Vintage Computing Christmas Challenge 2023
L’immagine da realizzare per la Vintage Computing Christmas Challenge 2023

I partecipanti sono stati più di 200 (Logiker ha condiviso tutte le entry su Google Drive, demozoo.org e scene.org; consulta la homepage per ulteriori link e dettagli) e, oltre ai consueti BASIC e Assembly, sono stati utilizzati i linguaggi più disparati, tra cui APL, SQL e Canvas (ambiente di cui non ero a conoscenza).
Alcuni programmi sono davvero impressionanti e meritevoli di studio!

Il mio programma

Avendo già partecipato all’edizione dell’anno precedente, a inizio Dicembre 2023 sono stato invitato da Logiker a prendere parte alla nuova sfida; ho così realizzato un programma in linguaggio BASIC per l’home computer Sinclair ZX Spectrum.

Il programma, chiamato The Snowing Christmas Sweater, è costituito da un’unica riga di codice che occupa solamente 63 byte e simula un effetto “nevicata”, stampando gli asterischi “*” in modo pseudo-casuale, fino a produrre l’immagine richiesta:

3 LET x=RND*VAL "18": PRINT AT x,INT (RND+RND)*VAL "18"-ABS (x+VAL "6"*INT (RND*INT PI)-VAL "15");"*": GO TO PI
Animazione che mostra il mio programma in esecuzione su ZX Spectrum
Il mio programma in esecuzione su ZX Spectrum

Per semplificare la realizzazione, ho deciso di procedere per piccoli passi, ponendomi inizialmente l’obiettivo di stampare l’immagine richiesta nella sua interezza, per poi modificare il programma per aggiungere l’effetto “nevicata” ed apportare le opportune ottimizzazioni.

Il primo passo è stato stampare una linea obliqua di asterischi. Sperimentando con il codice, mi sono reso conto che nella stampa con PRINT AT, è possibile specificare valori negativi come numero di riga e/o di colonna, senza causare errori nell’interprete, che utilizza effettivamente i valori assoluti. Con questo accorgimento, è stato possibile disegnare due segmenti con un singolo ciclo FOR:

100 FOR x=0 TO 18
200 PRINT AT x,x-3;"*"
300 NEXT x
Animazione che mostra 2 segmenti di asterischi, disegnati con un ciclo FOR
2 segmenti di asterischi, disegnati con un ciclo FOR

Iterando questo procedimento per 3 volte, sono riuscito ad ottenere metà della forma desiderata:

90 FOR a=-15 TO -3 STEP 6
100 FOR x=0 TO 18
200 PRINT AT x,a+x;"*"
300 NEXT x
310 NEXT a
Animazione che mostra il programma che disegna metà dell'immagine
Metà dell’immagine

L’immagine completa può quindi essere prodotta aggiungendo l’immagine stessa, ribaltata specularmente rispetto all’asse verticale, vale a dire stampando, in ciascuna iterazione, un ulteriore “*” alla colonna 18 – ABS(colonna corrente). La dimensione del programma ottenuto è: 116 byte:

90 FOR a=-15 TO -3 STEP 6
100 FOR x=0 TO 18
200 PRINT AT x,a+x;"*"
210 PRINT AT x,18-ABS (a+x);"*"
300 NEXT x
310 NEXT a
Animazione che mostra il programma che disegna l'immagine completa
Immagine completa

L’effetto ottenuto è carino, ma volevo che i fiocchi di neve*” apparissero casualmente sullo schermo. Ho quindi trasformato il programma in un ciclo infinito costituito da una sola riga di codice, che determina in ciascuna iterazione in modo pseudocasuale la posizione degli asterischi appartenenti a ciascuna delle due metà dell’immagine:

3 LET a=6*INT (RND*INT PI)-15: LET x=INT (RND*19): PRINT AT x,a+x;"*": PRINT AT x,18-ABS (a+x);"*": GO TO PI

Questa versione del programma occupa 88 byte. L’istruzione GO TO finale utilizza un espediente per ridurre la dimensione, infatti il π PI richiede solamente un token, mentre l’utilizzo della costante numerica “3” avrebbe richiesto 6 byte in più (si veda il capitolo relativo alla memoria sul manuale dello ZX Spectrum).

Nel passaggio successivo, ho ridotto il programma per utilizzare un’unico statement di PRINT, per stampare in ciascuna iterazione un asterisco, appartenente a una delle due metà dell’immagine scelta casualmente (dimensione: 83 byte):

3 LET a=6*INT (RND*INT PI)-15: LET x=INT (RND*19): PRINT AT x,INT (RND+RND)*18-ABS (a+x);"*": GO TO PI

Nel passaggio successivo, con un refactoring per rimuovere la variabile a, la dimensione del programma è scesa a 78 byte:

3 LET x=INT (RND*19): PRINT AT x,INT (RND+RND)*18-ABS (x+6*INT (RND*INT PI)-15);"*": GO TO PI

Nel passaggio successivo, sono riuscito a risparmiare ancora alcuni byte, sostituendo le costanti numeriche con l’utilizzo della funzione VAL (dimensione: 66 byte):

3 LET x=INT (RND*VAL "19"): PRINT AT x,INT (RND+RND)*VAL "18"-ABS (x+VAL "6"*INT (RND*INT PI)-VAL "15");"*": GO TO PI

Con un’ultima piccola modifica al codice che determina il valore x della riga in cui stampare il carattere “*“, ho risparmiato ancora 3 byte. La dimensione finale del programma è quindi 63 byte:

3 LET x=RND*VAL "18": PRINT AT x,INT (RND+RND)*VAL "18"-ABS (x+VAL "6"*INT (RND*INT PI)-VAL "15");"*": GO TO PI

Nota: la dimensione del programma è calcolata con: PRINT PEEK 23627+256*PEEK 23628-23755 (si veda il capitolo sulle variabili di sistema nel manuale dello ZX Spectrum).

Sicuramente, con un po’ più di tempo a disposizione (la scadenza era il 25 Dicembre), sarei riuscito a limare ancora qualche byte; mi sono riproposto di provarci comunque, come sfida personale.

Penso che con l’opportuna combinazione di colori, l’output del programma ricordi la trama di un maglione natalizio; ecco spiegato il nome The Snowing Christmas Sweater.

Screenshot dell'immagine a colori (bordo verde, carta rossa, inchiostro bianco brillante)
L’immagine a colori

Non sei d’accordo? Dai un’occhiata alla seguente immagine e dimostrami che ho torto! 😄

Ho anche realizzato un breve video per presentare il mio programma, disponibile sul mio canale YouTube:

Video di presentazione di The Snowing Christmas Sweater

Accoglienza e ulteriori ottimizzazioni

Al termine della scadenza per l’invio delle varie realizzazioni, ho pubblicato alcuni dettagli del mio programma sul gruppo Facebook BASIC on the ZX Spectrum, ricevendo con mia somma gioia l’apprezzamento da parte di Johan “Dr Beep” Koelman e Uwe Geiken, due autorità per quanto riguarda la programmazione dei computer Sinclair ZX.

Inoltre, Dr Beep ha ulteriormente ottimizzato il mio codice, riducendone la dimensione a soli 54 byte!

Partendo dal mio listato BASIC, una prima ottimizzazione apportata al codice che sceglie casualmente il valore 0 o 1 è stata la sostituzione di: INT (RND+RND) con la versione più concisa: (RND>RND).

Un’altra ottimizzazione è costituita dallo spostamento delle funzioni RND, ABS and INT all’interno della stringa processata dalla funziona VAL. Nel fare ciò, sono utilizzati i codici dei token corrispondenti alle funzioni e non i loro nomi, per cui ciascuna chiamata a una di queste funzioni occuperà solamente 1 byte. Il codice così ottenuto occupa solamente 55 byte:

3 LET x=VAL "RND*18": PRINT AT x,VAL "(RND>RND)*18-ABS (x+6*INT (RND*3)-15)";"*": GO TO PI

Un refactoring del calcolo della colonna del carattere “*” ha permesso di risparmiare ancora un byte, per cui la versione finale del codice è:

3 LET x=VAL "RND*18": PRINT AT x,VAL "(RND>RND)*18-ABS (x-3-6*INT (RND*3))";"*": GO TO PI

Riporto anche il codice formattato per BasinC (Sinclair BASIC IDE), in cui è evidente l’utilizzo dei codici dei token corrispondenti alle funzioni RND (165), INT (186) e ABS (189) all’interno delle stringa passate come parametri alla funzione VAL (vedi il set di caratteri dello ZX Spectrum):

3 LET x=VAL "\#165*18": PRINT AT x,VAL "(\#165>\#165)*18-\#189(x-3-6*\#186(\#165*3))";"*": GO TO PI

e lo stesso codice, formattato per il tool bas2tap (in cui i codici dei token sono espressi in notazione esadecimale):

3 LET x=VAL "{A5}*18": PRINT AT x,VAL "({A5}>{A5})*18-{BD}(x-3-6*{BA}({A5}*3))";"*": GO TO PI

Infine, Johan ha pubblicato sul gruppo ZX81 Owners Club il port per Sinclair ZX81 del programma. Dato che l’interprete BASIC dello ZX81 consente solo un’istruzione per linea, il programma è costituito da 3 linee:

3 LET x=VAL "RND*18"
4 PRINT AT x,VAL "(RND>RND)*18-ABS (x-3-6*INT (RND*3))";"*"
5 GOTO PI
Immagine che mostra il port per ZX81 di The Snowing Christmas Sweater
The Snowing Christmas Sweater, portato su ZX81 da Dr Beep

Concludendo, sono stato felice di partecipare, sia per i risultati raggiunti ma soprattutto perché questa sfida mi ha dato l’opportunità di divertirmi e di imparare qualcosa di nuovo sullo ZX Spectrum!


Read in English

Risultati del BASIC 10Liner Contest 2023

Sabato scorso sono stati pubblicati i risultati dell’undicesima edizione del BASIC 10Liner contest, tradizionale competizione a cui si può partecipare realizzando giochi e programmi per computer a 8 bit in sole 10 righe di codice in linguaggio BASIC.

Classifica BASIC 10Liners 2023

Purtroppo quest’anno, a differenza delle passate edizioni, non sono riuscito a entrare nella TOP 10. Infatti, i miei due giochi in gara per la categoria PUR-80, A Day At The Animal Races (ZX Spectrum) e Squash Trainer (ZX81), si sono classificati 16esimo e 27esimo rispettivamente, su 37 concorrenti.

Complimenti in particolare a RAX, che con Thrust 10 e Pacman 10, entrambi per Oric Atmos, si è aggiudicato sia la prima sia la seconda posizione della stessa categoria.

Thrust10 di RAX, per Oric Atmos
Pacman10 di RAX, per Oric Atmos

Sperando di fare meglio il prossimo anno, mi divertirò provando gli altri giochi e in particolare i vincitori!

Versione in Inglese

Serpenti, serpenti e ancora serpenti!

Il 10 aprile sarà il termine ultimo per partecipare alla Retro Snake Game Jam, sfida di retro-programmazione organizzata dal gruppo Retro Programmers Inside in collaborazione con Phaze101 e ospitata sulla piattaforma itch.io. Lo scopo della sfida è la realizzazione di un gioco in cui vi sia un serpentello, non importa che sia il protagonista del gioco o il “cattivo” da evitare o da sconfiggere. Sono ammessi giochi per computer e console a 8/16 bit basati sulle CPU appartenenti alle “famiglie” Z80, 6502 e Motorola 68K.

baSnake

Ho quindi pensato bene di candidare il mio baSnake, realizzato ormai 6 anni fa in BASIC per lo ZX Spectrum, proprio in occasione di un’altra game jam su itch.io e successivamente arricchito per sfruttare alcune caratteristiche dello ZX Spectrum Next. Per poter partecipare, ho dovuto preparare una versione ad hoc, contenente il messaggio “Partecipante alla Retro Programmers Inside (RPI) and Phaze101 Game Jam“, come richiesto dal regolamento della Retro Snake Game Jam. Tale versione è disponibile, insieme alle precedenti, sulla pagina itch.io di baSnake.

baSnake in esecuzione sullo ZX Spectrum Next

YAS

baSnake non è stato l’unico progetto in cui ho avuto a che fare con serpentelli pixellosi. Nel 2015, infatti, mentre mi dilettavo con lo sviluppo di CHIP-OTTO, il mio interprete CHIP-8 per ZX Spectrum e di WEB-OTTO, la controparte per browser web, ho realizzato un clone di Snake proprio per questa piattaforma, chiamato – guarda un pò – YAS – Yet Another Snake (ancora un altro serpente). Sebbene scritti in linguaggi completamente diversi, baSnake eredita da YAS la possibilità di selezionare lo scenario in cui giocare.

Recentemente, ho appreso con piacere che YAS è stato incluso nella distribuzione ufficiale di EMMA02, emulatore multipiattaforma in grado di eseguire l’interprete CHIP-8 originariamente sviluppato per i computer della serie Cosmac.

Video che mostra YAS in azione sul port per ZX Spectrum Next di CHIP-OTTO

ZNAKE

Non è ancora tutto: per arrivare alla mia prima implementazione di un gioco in stile Snake, occorre andare ancora più indietro nel tempo, per l’esattezza al 2005. In quell’anno, infatti, realizzai ZNAKE, il mio primo progetto completo (seppur minimale) di videogioco per retrocomputer.

ZNAKE è infatti un semplice giochino in stile Snake, Worm, Nibbles, etc… per Sinclair ZX Spectrum. Lo scopo del gioco è pilotare il serpente (nelle direzioni alto / basso / sinistra / destra ) in modo che possa mangiare le mele che appaiono sullo schermo, evitando di urtare i muri o il serpente stesso. Per ogni mela ingerita, il giocatore guadagna punti, ma il corpo del serpente si allunga, rendendo così più difficile la partita.

Caricamento di Znake nell’emulatore RealSpectrum, su Windows XP

ZNAKE nasceva dal desiderio di realizzare un gioco, seppur semplice, per il celebre computer ZX Spectrum, al quale sono particolarmente affezionato. Già da tempo avevo avuto modo di conoscere il fantastico Z88DK, ma non ero mai andato oltre qualche semplice prova finchè un giorno, nel 2005, ispirato da un tutorial (purtroppo ho perso il riferimento, si parla di troppi anni fa) sul sistema a finestre X, decisi di implementare il serpentello come lista concatenata. Giocando così con malloc e putchar, ho implementato ZNAKE quasi completamente in C, utilizzando un minimo di Assembly. Non pago, per completare l’opera ho poi provveduto a trasferire ZNAKE su nastro, in modo da poterlo giocare sul vero Spectrum, oltre che sugli emulatori.

Successivamente, grazie all’emulatore Qaop, avevo anche creato un widget di Dashboard (che adesso chiameremmo “app“) per MacOSX e una versione per qualche desktop di Linux.

ZNAKE è quindi un progetto doppiamente retro, in quanto si tratta di un gioco per retrocomputer, realizzato quasi 20 anni fa (l’iBook G4 che utilizzavo all’epoca è ormai un retrocomputer esso stesso!). Tuttavia, giocando a ZNAKE, si può già avere un’idea di quale sarà lo stile di baSnake.

Dopo questo tuffo nel passato, ho pensato che anche ZNAKE avrebbe potuto partecipare alla Retro Snake Game Jam, previo inserimento del succitato messaggio. Il programma originale non è compatibile con le versioni recenti di z88dk, per cui ho dovuto fare alcune modifiche, cogliendo l’occasione per migliorare il codice, eliminando parti scritte da me a favore delle funzioni presenti nelle librerie fornite con z88dk. Il risultato è quindi, come al solito, disponibile per il download o per giocare tramite browser web (grazie all’emulatore JSSpeccy3) sulla pagina dedicata nella piattaforma itch.io.

Video che mostra il gameplay di ZNAKE

Direi, quindi, che 3 implementazioni di Snake bastano e avanzano!
Anche se una versione BASIC 10 Liner, magari… 🙂

Link e riferimenti

English version

Rettangoli colorati con ugBASIC

Screenshot che mostra i rettangoli colorati sullo ZX Spectrum

Da tempo desideravo provare ugBASIC, linguaggio isomorfo compilato, che permette di produrre programmi per una moltitudine di piattaforme (computer e console) a 8 bit a partire da un unico codice sorgente. A rendere ancora più accattivante il tutto è ugBASIC IDE, un ambiente integrato per Windows che permette di installare le toolchain per le piattaforme desiderate e scrivere, compilare ed eseguire programmi mediante gli appositi emulatori con pochissimi click.

Ho quindi colto l’occasione offerta dalla sfida della settimana, indetta lo scorso venerdì sul gruppo Facebook RetroProgramming Italia, per cimentarmi con ugBASIC. Lo scopo della sfida è realizzare un programma (in qualsiasi linguaggio e per qualsiasi macchina a 8/16 bit) per disegnare rettangoli colorati in modo molto veloce.

Screenshot C64 che mostra l'obiettivo della sfida
Immagine rappresentativa dell’obiettivo della sfida della settimana
(text mode standard del Commodore 64)

L’animazione dei rettangoli colorati ha immediatamente richiamato alla mia mente il programma dimostrativo BGIDemo, incluso nelle distribuzioni Turbo Pascal degli anni ’80 per mostrare le potenzialità delle librerie grafiche di Borland e che in gioventù ammiravo con stupore. Che nostalgia!

Screenshot del programma BGIDemo per Turmo Pascal
Random bars – dal programma BGIDemo per Turbo Pascal 5 di Borland

Ho quindi buttato giù il seguente programmino, per disegnare i rettangoli mediante stringhe formate da spazi vuoti, utilizzando posizione, dimensione e colore casuali.

BITMAP ENABLE
sc = SCREEN COLUMNS: sr = SCREEN ROWS: pc = PAPER COLORS
CLS
LOCATE 0, sr-1
PRINT "COLS:";sc;" ROWS:";sr;" COLORS:";pc;
s$ = "": FOR i=1 TO sc: s$ = s$ + " ": NEXT
DO
	PAPER RND(pc)
	x = RND(sc)
  	y = RND(sr - 1)
  	w = 1 + RND(sc - x)
  	h = 1 + RND(sr - 1 - y)
  	ss$ = LEFT$(s$, w)
  	FOR yy = y TO y+h-1
  		LOCATE x, yy
  		PRINT ss$;
  	NEXT
LOOP

Ho poi compilato il programma utilizzando lo ZX Spectrum come target, riscontrando però un paio di anomalie, che si possono osservare in questo video. L’istruzione PAPER, infatti, oltre allo sfondo alterava anche il colore del bordo. Inoltre, mentre nonostante il numero di colori restituito PAPER COLORS fosse 16, in output erano visibili solo gli 8 colori senza l’attributo bright.

Ho segnalato i problemi all’autore di ugBASIC Marco Spedaletti, il quale, dopo solo poche ore, ha rilasciato un COLDFIX che ha risolto entrambi i bug. Se solo il supporto di [inserisci qui il nome di una qualsiasi azienda fornitrice di energia/servizi telefonici] fosse altrettanto solerte, si vivrebbe in un mondo migliore, ma questa è un’altra storia…

Dopo un aggiornamento dei compilatori direttamente in ugBASIC IDE, sono riuscito ad ottenere una versione corretta dell’eseguibile, come si può osservare in questo video:

I rettangoli colorati sullo ZX Spectrum (emulatore Fuse)

Infine, dato che ugBASIC nasce come ambiente di sviluppo multipiattaforma, ho compilato una versione del programma per MSX e qui si può osservare il risultato:

I rettangoli colorati su MSX (emulatore openMSX)

Link e Riferimenti

Screenshot che mostra i rettangoli colorati sullo ZX Spectrum
I rettangoli colorati sullo ZX Spectrum