Archivio: giugno 2010


28 giu 2010

Omen Nomen v0.9.7 alpha – RELEASED

BeeTLe BeTHLeHeM | Programmazione | Roguelike

E finalmente ho deciso di pubblicare la prima release di Omen Nomen, dopo un paio di giorni dedicati a mettere su una pagina web con un aspetto non dico gradevole ma perlomeno decente, a scrivere un altrettanto decente (anche se minimalista) readme e ad eliminare dei piccoli fastidiosi bug che si sono finalmente rivelati nel momento in cui credevo di poter scrivere la parola fine.

Una fine del tutto simbolica e relativa, naturalmente. Adesso comincia tutta un’altra fase che può svilupparsi in due differenti, ipotetiche strade:
1) Il gioco viene scaricato, qualcuno ci gioca, l’applicazione (immancabilmente) esplode, ricevo del feedback, lavoro sulle correzioni per la prossima versione.
2) Se una qualunque delle premesse appena elencate non dovesse verificarsi, mi rimetto a lavorare sulla nuova iterazione di Dead City – ed anche stavolta l’obiettivo è quello di una release.

Per adesso diffondo la notizia (qui, su Reddit e probabilmente anche su Roguebasin).
La pagina dei giochi, o del gioco, per meglio dire, è questa qui.

Nota: sia la pagina apposita che l’applicazione sono in lingua inglese. L’applicazione non è cross-platform, dato che la libreria JCurses, se ho capito bene, va bene solo su piattaforme Windows. Non me ne vogliano i linuxari. Ho in cantiere, comunque, anche una versione grafica che sostituisce JCurses con Java2D, e questa dovrebbe andare bene su qualunque sistema operativo. Per la versione ASCII vedrò in futuro librerie grafiche alternative – un paio ce ne ho da studiare, ma non ora.

21 giu 2010

Qualche Considerazione

Programmazione | Roguelike

A livello generale tendo a considerare i miei numerosi tentativi di programmazione come parti di un unico percorso che, prima o poi, sfocerà in uno (e spero più) prodotti completi. In questo senso prendo come guida una dichiarazione che ho avuto occasione di leggere tanti, tanti anni fa in un’intervista agli sviluppatori della Maxis, al tempo dell’uscita di Sim City 2000. Il punto era che i precedenti Sim avevano offerto ciascuno un progresso sotto un dato aspetto tecnico o di design, e tutti questi elementi erano stati tutti presi e fusi insieme nel nuovo Sim City. Ad esempio Sim Earth aveva permesso loro di concentrarsi sulla gestione delle finestre di interfaccia.
E più o meno questo è quello che accade sempre, o è lo stile di pensiero sul quale bisognerebbe concentrarsi: che ogni goccia del proprio lavoro non viene mai sprecata, ma è l’opportunità per espandere le proprie conoscenze, per scoprire qualcosa di nuovo, perfezionare qualcosa di già conosciuto, o per sfruttare qualche conoscenza in una maniera completamente diversa.

A livello di progetto direi invece che è importante mantenere il controllo sul proprio lavoro: avere sempre d’occhio lo schema complessivo, l’obiettivo finale, e procedere gradualmente partendo dallo specifico ed ampliandosi verso il generale. Creare prima delle unità funzionali, ovvero moduli di codice che facciano quello che ci si aspetta, e poi farli comunicare tra loro rendendoli compatibili. Prendendo a modello l’analogia più banale del mondo, si tratta di rispettare i canoni di buonsenso che si utilizzano in qualsiasi lavoro di costruzione: si parte dalle fondamenta, e quando queste sono solide, si procede verso l’alto – tenendo sempre d’occhio equilibrio e stabilità.
Ovviamente non è mai un processo costituito da fasi distinte in maniera netta: ci sarà sempre un pò di uno ed un pò dell’altro, e in un singolo momento si dovrà pensare a tre cose diverse. Per questo è necessario avere prima di tutto le idee chiare.
E questo significa anche prendere appunti, specialmente PRIMA di iniziare lo sviluppo. Annotare le idee, organizzarle in base alla loro reale importanza, mettere avanti la visualizzazione a schermo, la lettura dei comandi di base, la creazione e la modifica dei dati, il tipo di variabili e strutture necessarie e più efficaci. L’obiettivo non è tanto creare un gran gioco al primo tentativo, quanto creare un gioco che funzioni, e sul quale si possa poi implementare tutto il resto con la massima facilità raggiungibile.

Per me il quadro complessivo è la creazione di un mondo di gioco dove il personaggio possa dedicarsi al free roaming, girovagando liberamente, completando quest (generate sempre casualmente), e soprattutto dove gli eventi possano trasmettere un certo grado di “finto” realismo, come se venisse messa in scena una rappresentazione teatrale altamente convincente.

In Omen Nomen, l’”unità funzionale” è composta dal villaggio di superficie. Per completare l’ambiente ho introdotto al suo interno anche l’entrata dei dungeon che vengono esplorati dal giocatore. Il prossimo step vedrà più villaggi (tutti basati sul primo) all’interno di una mappa più ampia, che conterrà anche i dungeon, in locazioni separate. Una volta stabilita questa base introdurrò elementi di interazione tra dungeon e villaggi: bande di mostri che girano per la mappa, o carovane di mercanti che vanno da paese a paese. Ad un livello ancora più avanzato verranno introdotti ulteriori punti di interesse che potrebbero comporre una primitiva catena commerciale:
- Miniere/Cave da cui si estraggono minerali magici.
- I minerali vengono trasportati nelle fucine dei fabbri.
- I fabbri usano i minerali per applicare proprietà magiche agli oggetti prodotti.
- Gli oggetti lavorati vengono trasportati nei mercati dei villaggi dalle carovane.
A questo punto l’intervento del personaggio potrebbe avere un peso più grande sul mondo di gioco: salvare una carovana (o depredarla… perchè no?) potrebbe modificare o mantenere l’equilibrio della rete commerciale. Fornendo una varietà di obiettivi ed equilibrando l’esito di azioni con scopi e grandi di moralità diverse è possibile creare un certo livello di libertà.

Anche Dead City dovrebbe seguire uno sviluppo simile: invece del villaggio abbiamo un’intera città, che nel mondo del gioco (di natura più apocalittica, come si potrà immaginare) sarebbe accompagnato da accampamenti di superstiti più o meno protetti, centri di ricerca o bunker militari, mentre orde di zombi dalle varie capacità vanno in giro distruggendo quello che incontrano. La rete commerciale potrebbe basarsi su beni primari come il cibo o le medicine, e il mondo risulterebbe molto più dinamico: gli zombi potrebbero finire con il dominare l’intera mappa, se qualcuno non si mette d’impegno a coordinare e favorire lo sviluppo dei gruppi di sopravvissuti.

Le prospettive sono incredibilmente allettanti, e questi sono solo i punti di sviluppo più evidenti – non meno importante è l’inserimento di dettagli e particolari meno palesi (come un sistema di informazioni che renda possibile venire a sapere di certi eventi aldifuori del proprio raggio d’azione). Ma come ho già avuto modo di dire, occorre mantenere il controllo: anche sulle proprie ambizioni. Ogni cosa a suo tempo.

18 giu 2010

Omen Nomen /2

Programmazione | Roguelike

L’algoritmo di generazione procedurale che utilizzo prende in considerazione diversi dati che vengono impostati nel momento in cui viene creato l’istanza del dungeon: anche in questo caso il nome del dungeon influenza la natura e l’entità delle informazioni, come il numero o i limiti alla dimensione delle stanze, la lunghezza dei corridoi, il tipo di stanze presenti o la quantità di liquidi (acqua, fango, lava).

Avendo a disposizione un oggetto contenente tutti questi dati (nonchè la mappa stessa, una matrice bidimensionale di caratteri), procedo con l’esecuzione dell’algoritmo, con la seguente struttura, derivata in parte dal lavoro di Mike Anderson:

1. Riempio l’intera mappa di tile muro.
2. Creo una stanza all’interno della mappa, con posizione e dimensioni casuali.
3. Eseguo un ciclo che ad ogni iterazione si occupa di inserire una “feature” casuale all’interno della mappa:

- mi posiziono su una posizione casuale corrispondente al muro di una stanza (un tile “vuoto” adiacente ad un muro).
- decido casualmente la feature da creare (stanza, corridoio, caverna, ecc.)
- determino le dimensioni e le coordinate della feature, e controllo che questa non vada oltre i limiti di mappa e non si sovrapponga agli elementi già inseriti.
- una volta ottenuti dati validi, creo la feature nella mappa (basilarmente si tratta di aree rettangolari: per le caverne vado a includere tile muro in posizioni casuali per rendere la forma irregolare).
- considero eventuali probabilità di presenza di liquidi, ed in caso effettuo il riempimento (casuale) nell’area selezionata.

4. Inserisco tile muro lungo i bordi di mappa (questo è più che altro per estetica).

5. Se richiesto, aggiungo delle sezioni predefinite (crateri di lava, parti labintiche, fiumi, caverne circolari ecc.)

6. Creo i punti di entrata ed uscita (con i dovuti controlli sulla posizione estratta).

7. Verifico l’esistenza di un percorso valido tra il punto d’entrata ed il punto di uscita del livello, utilizzando un algoritmo di pathfinding A*. Nel caso le due posizioni siano isolate, provvedo a creare un percorso utilizzando uno tra più metodi, estratto a caso (creando tile vuoti lungo la linea Bresenham tra i due punti, incrociando un corridoio verticale ed uno orizzontale che attraversino rispettivamente uno dei due punti in esame, ecc.)

8. Inserisco le porte, in posizioni valide che ne giustifichino la presenza (principalmente, un tile vuoto tra due tile muro).

Per ogni ciclo implementato in genere inserisco un contatore di sicurezza che lanci un break una volta raggiunto un certo numero di iterazioni – una piccola precauzione per evitare loop infiniti (almeno nei casi in cui non riesco a risalire immediatamente al problema, o se effettivamente il risultato del ciclo non è rilevante).

levelsgenerated_1E nell’immagine a lato ecco alcuni dungeon generati dall’algoritmo: la grafica dei muri cambia a seconda del tipo di dungeon, ed il colore dipende dalla temperatura generale. Sono alcuni tocchi stilistici che puntano sempre ad aumentare la varietà. A questo scopo si potrebbero anche inserire ulteriori sezioni predefinite.

Ma l’algoritmo è anche migliorabile: come si può notare, nelle Frozen Caverns c’è una stanza completamente sgombra dal ghiaccio, e dovrebbe essere quella generata al passo 2. E’ qualcosa che si può evitare con molta facilità – anche solo tenendo da conto le coordinate e le dimensioni per essere sicuri che venga presa in considerazione (ora non ricordo perchè questo non accade, ma un motivo ci sarà – un motivo c’è sempre).

levelsgenerated_2E non tutti i dungeon sono soddisfacenti: nella seconda immagine è possibile ammirare alcuni esempi piuttosto anomali, in cui il minimo che può accadere è che siano presenti sezioni scollegate da tutto il resto (ed in questo caso mi basterebbe introdurre un controllo simile a quello al passo 7. per ogni sezione predefinita inserita sulla mappa), mentre il massimo è un dungeon di dimensioni ridottissime.
Non si parla di problemi di natura trascendentale, o tali da rendere impraticabile l’applicazione o il gioco vero e proprio, ma restano comunque dei bug di cui terrò da conto nelle successive rifiniture e ottimizzazioni (a parte nel caso dell’Hot Daedalus, dove dovrei capire come mai non è stato generato praticamente nulla, tanto da costringere l’algoritmo ad utilizzare direttamente una delle soluzioni adottate al punto 7).

17 giu 2010

Omen Nomen /1

Programmazione | Roguelike

on_097a_1 L’idea di Omen Nomen nasce sia come diversivo, o meglio come un modo di affrontare il tema da un altro punto di vista, ed al tempo stesso viene stimolata dall’idea di introdurre una meccanica di generazione casuale che rende merito a Diablo II ed in parte a Borderlands, che va a rivitalizzare nella mia mente il concetto generale di “oggetto” di gioco (armi, armature ecc…) considerato come una base su cui vengono applicati diversi effetti – bonus o malus. Su questo imposto la generazione del nome dell’oggetto, che andrà a riflettere le proprietà che gli appartengono. Decido di portare il tutto ad un livello che va a rasentare il comico (il che accadeva per certe armi di alto livello in Diablo II).

Nasce così una serie di classificazioni (rank) divisi in fasce (tier), tramite i quali vengono generati oggetti e nomi che vanno da un’estrema semplicità (nessun tipo di effetto applicato), come Falchion, Crossbow ecc…, ad un insieme di effetti che producono descrizioni pompose come Magnetic Flail of Crushing o Glorious Dagger of Daylight. Lo stesso vale per le armature o per gli oggetti di equipaggiamento (stivali, guanti, elmi, anelli ecc.).

Già che ci sono, e dato che il titolo del gioco va a riflettere proprio il modo in cui il nome rispecchia la natura dell’oggetto a cui è legato (Omen Nomen, “il destino nel nome” in latino), espando la meccanica anche ai mostri (mai visto uno Electric Zombie of Moon?), ed ai dungeon (The Vaults, The Abyssal Forge, The Infernal Gelatinous Mausoleum of Luminous Skulls giusto per citare).

Oltre alla mera generazione del materiale di gioco, ho tentato di implementare lo spirito del titolo in maniera più completa, calcolando il seed del motore random dal nome che il giocatore sceglie per il suo personaggio. Questo significa, essenzialmente, che una serie di azioni avrà sempre lo stesso risultato (non è completamente esatto: sarebbe meglio parlare di “una serie di azioni che produce lo stesso numero di estrazioni di numeri casuali”). La cosa mi interessa soprattutto perchè mi porta ad un’interessante conclusione: “registrando” le azioni compiute dal personaggio ad ogni turno dovrebbe essere possibile riprodurre una sorta di replay dell’intera partita. Prima o poi dovrò provarci.

A parte questo, il discorso dungeon va a toccare il cuore di ogni roguelike, ovvero la generazione procedurale delle mappe dei dungeon: prima di arrivare a sviluppare la versione attualmente implementata ho compiuto alcune ricerche, ho riportato in Java un pò di algoritmi e li ho utilizzati come punto di partenza. Si può considerare questa (breve) lista come riferimento:
- Ray Dillinger Cave Generator
- Solarnus Dungeon Generator
- Jimmy_B Dungeon Generator
- Mike Anderson Generator (di questo purtroppo non trovo più il link) (UPDATE: link trovato, ed è proprio sulla sequenza di azioni riportate in pagina che ho basato il mio algoritmo per Omen Nomen).

Aggiungo inoltre un altro paio di pagine a cui ho dato almeno una scorsa:
- Ascii Dreams – Unangband Dungeon Generation – Part Two
- The Chronicles of Doryen – BSP Dungeon Generation
C’erano anche un pò di pagine utili su simugraph.com, ma sembra che il sito sia defunto.

In seguito a smanovelli e riflessioni ho sviluppato varie versioni personali, tra cui una basata sull’algoritmo di Conway (che genera più che altro caverne ampie e irregolari) e una sulla BSP (di cui sopra) che volevo utilizzare per generare un quartiere cittadino.
Dovrei avere ancora il progetto usato come banco di prova per gli algoritmi – appena ho un pò di tempo sistemo e lo metto a disposizione.

05 giu 2010

Breve Riassunto Storico

Programmazione | Roguelike

Dato che in giro di roguelike a tema fantasy ce ne sono molti, la mia prima intenzione è sempre stata quella di puntare verso un’ambientazione differente: seguendo i miei gusti personali ho scelto l’horror, ed in particolare i temi lovecraftiani e gli zombi.

E proprio questi ultimi hanno ispirato il mio primo progetto, nato durante le ferie natalizie di qualche anno fa: Dead City incentra l’azione sull’attraversamento di una città infestata dai suddetti mostri, con la possibilità di raccogliere ed utilizzare armi ed equipaggiamento vario.

dc_1Come linguaggio e piattaforma di sviluppo ho scelto inizialmente Blitz!, che fornisce una certa versatilità e potenza, con il quale ho creato delle prime versioni che già facevano uso di grafica 2D a tile. Il problema è nato quando, con lo scemare dell’esaltazione iniziale, mi sono reso conto che le features che avevo implementato non erano tanto un insieme organizzato quanto un mucchio caotico che seguiva degli standard piuttosto casuali. L’improvvisa consapevolezza che nel momento in cui avessi lasciato perdere il progetto mi sarebbe stato praticamente impossibile riprenderlo in seguito, seminò in me il germe della necessità di una minima analisi preliminare.

La mia difficoltà più grande, a livello di mentalità, è stata in effetti quella di superare uno stadio di estasi creativa in cui le idee si riversavano direttamente sul codice, che risultava più il prodotto di uno stato d’animo preciso che di un lavoro sistematico e organizzato. A questo scopo è stato utile il procedere con successive iterazioni dello stesso progetto, spesso ricominciando da zero o recuperando pezzo per pezzo i miei progressi precedenti.
A mano a mano sono emerse nuove priorità, e ne sono state scartate delle vecchie.

Nel frattempo avevo buttato giù una primissima e limitata bozza per Barton Rook, un roguelike con elementi presi dai racconti di Lovecraft, e che avrebbe avuto una struttura episodica, con livelli raggruppati all’interno di “storie” autoconclusive. Purtroppo per lui, è finito quasi subito in ibernazione.

Il mio idillio con il Blitz! si è concluso quando ho cominciato a lavorare in Java: maneggiando e riparando (soprattutto) varie applicazioni web, avevo acquistato una maggior dimestichezza sia a livello di programmazione (prima avevo lavorato in C++, ma erano già passati due-tre anni di vuoto) che di approccio gestionale. A quel punto la mia immaginazione esplose in tutte le direzioni concepibili, e da zero ripresi Dead City e ne tirai fuori altre due iterazioni, passando dal 2D ad una console application con grafica testuale.
dc_2A livello tecnico i problemi più pressanti che ho dovuto affrontare sono stati la gestione della visualizzazione a schermo e la lettura dell’input da tastiera (di base, in console, la lettura avviene solo dopo che l’utente ha premuto INVIO, ed era quindi improponibile per un gioco). Fortunatamente entrambe le questioni sono state risolte adottando JCurses, il porting Java della libreria Curses.

Quest’ultima operazione (che avrebbe dovuto fornire la base per un framework per il futuro – ma vabeh, per adesso ho accantonato l’idea) è andata avanti per un bel pò, ed è stata protagonista di diversi progressi, tanto da arrivare ad una versione funzionale, anche se priva di diverse features. Ma era già qualcosa. Però a quel punto ero ormai saturo, e sentivo il bisogno di dedicarmi a qualcosa di diverso.

Tipo, che so, ad un roguelike a tema fantasy.
E così ho cominciato lo sviluppo di Omen Nomen.

E finalmente arriviamo al presente.

03 giu 2010

Introduzione

Programmazione | Roguelike

Da adesso, quindi, i miei post riguarderanno in prevalenza lo sviluppo di videogiochi, e nello specifico di roguelike.

Cos’è un roguelike?

Letteralmente, il termine inglese descrive un gioco che presenta una certa somiglianza con Rogue, che viene considerato il capostipite del genere.

I vari successori condividono con Rogue una serie di elementi di base, molti dei quali, più che rappresentare dei cardini, vanno considerati come linee guida, e come tali sono stati soggetti a numerose variazioni:

- Svolgimento a turni alterni tra il giocatore ed il resto del mondo di gioco.
- Interfaccia testuale che utilizza il set di caratteri ASCII per la visualizzazione di tutti gli elementi di gioco.
- Una serie di comandi associata ad una vasta lista di azioni che permettono al giocatore di interagire con l’ambiente circostante.
- Generazione casuale dei livelli, degli oggetti e dei mostri (come minimo), cosa che implica un’elevata rigiocabilità.
- Concept derivato dai GdR, con un’enfasi particolare sull’esplorazione e il combattimento.
- Limitazione o assenza della possibilità di salvare la partita in corso. Nei casi più estremi, permadeath: se il personaggio muore, il file di salvataggio viene automaticamente eliminato.

Da qualche anno nutro per i roguelike una certa passione: a loro ho già dedicato un post in passato, nel quale indico, tralaltro, gli esponenti più caratteristici del genere.

Perchè proprio un roguelike?

Esporre le motivazioni che mi hanno portato a questo punto è un compito che posso assolvere solo parzialmente. Da una parte pesa la mia nascita come videogiocatore, nei primi anni ‘80, e l’assistere all’evoluzione grafica dei giochi. Sono partito, come tanti altri della mia generazione, da un livello di grafica a dir poco minimale, e se trent’anni dopo il mio senso estetico può considerarsi appagato da un livello di dettaglio che tempo fa avrei solo potuto sognare, so istintivamente che devo dare un’occhiata dietro le quinte per capire effettivamente “quanto” gioco c’è. E’ un modo di pensare che ha ricevuto una forte spinta dalla nascita del concetto di modding, nel momento in cui un gioco finisce per essere un’entità unica per venire destrutturato in motore di gioco e plug-in grafico/meccanico/stilistico, ed è lo stesso che applico nell’analisi dello sviluppo dei miei progetti – ma di questo parlerò dopo.

Lasciando stare le considerazioni più intime ed emotive, ci sono anche un paio di fattori decisamente più oggettivi per la scelta di questo genere: ad esempio,la possibilità di trascurare il lato grafico permette di concentrarsi sul cuore del gioco, sulle meccaniche da implementare e sulle interazioni possibili all’interno del gameplay.
Consideriamo inoltre che un gioco a turni permette di organizzare in maniera migliore l’analisi e la reazione del gioco all’intervento del giocatore, in quanto due stati separati che agiscono separatamente. Potremmo paragonare (con qualche lieve attrito) un roguelike ad una partita scacchi, enormemente più complessa, nella quale non ci sono limiti di tempo per scegliere la propria mossa.

Ma più di tutto, programmare per conto proprio è un metodo per fare esperienza, per sperimentare tecniche o soluzioni alternative che magari non è possibile implementare sul posto di lavoro (per chi, come me, lavora pure nello stesso linguaggio), per entrare in uno stato mentale più consono allo sviluppo. Ed alle volte può essere anche rilassante, com’è sempre fare qualcosa che è in linea con i nostri interessi personali.

02 giu 2010

Cambio di Rotta

BeeTLe BeTHLeHeM | Comunicazioni di Servizio | Programmazione

Come al solito, ogni pausa (anche se lunga) giunge al termine.
In quest’ultimo caso, la mia assenza è stata causata non solo da impegni ben più pressanti sul fronte della Vita Reale, ma anche da una certa quantità di riflessioni sul rapporto tra me, il NeuRoGRiLL e l’impostazione attuale.
Forse è il bisogno di dare al blog un’impronta più personale, alla quale mi senta più legato, forse è il raggiungimento di un livello di saturazione nell’inseguire e riportare le notizie, anche se curiose o intriganti, che mi ha fatto venire a nausea questo tipo di attività.
Sicuramente uno dei motivi è il rinnovamento periodico del mio entusiasmo nel programmare, o nel tentare di programmare, videogiochi.

Questi mesi sono stati molto prolifici, sotto il profilo della programmazione, dato che hanno visto il risorgere dei miei propositi di realizzare un roguelike, e in quest’ennesima reiterazione riesco finalmente a vedere la concretizzazione dei miei sforzi. E solo adesso, purtroppo, mi rendo conto che avrei potuto trasformare il NeuRoGRiLL in un development blog in cui riportare i passi compiuti nel progetto.

Beh, poco male: la trasformazione avviene ora.