La descrizione operativa del server può essere divisa in tre livelli, che possono essere agevolmente affrontati in maniera distinta. La struttura generale è quella di un server che gestisce un certo numero di giochi (ServerGame) che a loro volta gestiscono una serie di thread (ServerThread) che interagiscono con le connessioni sul socket.
Il server è sempre in ascolto sul socket (ServerSocket) e appena arriva una nuova richiesta di connessione viene svolta una di queste operazioni:
È da notare che il server ha il puntatore solo dell'ultimo gioco creato, e quindi giochi ``pieni'' o già iniziati cominciano a vivere di vita propria; letteralmente, sono oggetti senza piú alcun riferimento.
Immediatamente successiva alla fase di accettazione, avviene la presentazione del giocatore. Un giocatore si presenta quando produce un comando NAME valido. Inoltre, appena presentatosi, un giocatore è abilitato a inviare i comandi START (per far iniziare il gioco) e QUOTE (per inviare messaggi agli altri giocatori). Si considera un giocatore attivo solo un giocatore che si è presentato, ed ovviamente un giocatore non si può presentare due volte.
Un giocatore che si collega ma non si presenta non viene considerato e viene automaticamente scollegato dal server all'avvio del gioco. Un giocatore che si presenta ma, per qualche motivo, si scollega (crash del client o chiusura esplicita dello stesso) a partita non iniziata semplicemente viene rimosso dalla lista dei giocatori e la sua posizione recuperata.
Se è superato un numero minimo di giocatori e uno di questi forza l'inizio, o se si è raggiunto il numero massimo di giocatori attivi connessi il gioco inizia. Il server invia ai client i pezzi e abilita gli stessi giocatori. Un giocatore abilitato e a gioco iniziato può, oltre ai precedenti, inviare anche il comando MOVE per eseguire una mossa.
Da questo momento in poi ogni morte di giocatore viene considerata come un abbandono. Il gioco continua (a meno che non sia rimasto un giocatore ;) tra i giocatori rimasti senza nessun meccanismo particolare (non vengono redistribuiti i pezzi del giocatore morto, semplicemente considerato abbandono volontario).
Il gioco finisce nel caso che rimanga un solo giocatore, o uno dei giocatori abbia finto i pezzi, oppure anche se si è giunti in una situazione di stallo (nessuno dei giocatori può piú muovere). Alla chiusura del gioco i punteggi (numero di pezzi rimasti) vengono inviati ai giocatori sopravissuti e vengono interrotte le comunicazioni e termina l'istanza di gioco correntemente in uso.
Anche la descrizione operativa del client può essere divisa in tre livelli.
Il giocatore deve presentarsi. Solo dopo aver dato il proprio nome è possibile chiedere di giocare. A tale richiesta il client crea una connessione con il server e comunica il nome del proprio giocatore. Se il server non risponde, perché ad esempio non è in funzione, la richiesta di gioco non viene soddisfatta e si resta nella fase di presentazione.
Accettata la richiesta di giocare si passo alla fase di attesa inizio partita.
Da questa fase in poi è sempre possibile abbandonare il gioco e tornare alla fase di presentazione rilasciando le risorse occupate. Se il server muore (per i soliti motivi....) la partita non viene iniziata e si ritorna alla fase di presentazione.
In questa fase e possibile conoscere i nomi dei giocatori in attesa di giocare e scambiare messaggi con gli altri giocatori attraverso il comando QUOTE. Vengono create due finestre, una principale con i nomi dei giocatori ed una con tutte le comunicazioni fra client e server e con i messaggi scambiati fra i giocatori. La finestra principale viene aggiornata su segnalazione del server ogni volta che un nuovo giocatore si inserisce o un giocatore inserito abbandona il gioco.
E' possibile chiedere di dare inizio alla partita, sarà compito del server rispondere se tale richiesta e valida.
Si passa alla fase di gioco. Anche qui se il server muore la partita viene terminata e si ritorna alla fase di presentazione.
La finestra principale, ora, visualizza anche i pezzi posseduti dal giocatore e lo stato della partita con la disposizione sul tavolo dei pezzi posizionati. Facilmente è possibile scegliere un pezzo fra quelli posseduti dal giocatore e posizionarlo sul tavolo utilizzando il tasto sinistro del mouse.
Il tavolo può essere pensato come suddiviso in tanti quadrati posti uno accanto all'altro. Un pezzo viene posizionato sopra due di questi quadrati. Il primo è quello che si trova sotto il mouse, il secondo dipende dalla posizione del mouse all'interno del quadrato. Viene selezionato, tra i quattro ai lati del primo quadrato, quello più vicino al puntatore del mouse.
Alla richiesta da parte del giocatore di muovere il client si comporta in modi differenti a seconda che sia o non sia abilitata la funzione di check. Se questa opzione è disabilitata il client invia la mossa richiesta al server, sarà il server a rispondere se tale mossa è non valida. Se questa opzione è abilitata il client abilita il giocatore a muovere solo nel suo turno e invia al server solo le mossa valide. Questo permette di alleggerire il compito del server spostando una parte dei controlli ai singoli client. Inoltre si riduce il numero di messaggi allo stretto necessario evitando comunicazioni inutili.
Anche il questa fase è possibile inviare messaggi agli altri giocatori attraverso il comando QUOTE.
Come avevamo accennato, la comunicazione avviene attraverso socket, con dei semplici comandi che sono delle stringhe di testo con una particolare sintassi (tipica nei sistemi UNIX). Mentre la gestione dei socket è lasciata al thread, l'interpretazione dei comandi avviene in una istanza di una classe comune, la classe Parser. Una istanza di Parser prende in fase di inizializzazione una definizione di comandi, e poi interpreta le stringhe conseguentemente.
I comandi implementati in server e client sono esposti qui di seguito.
Ovvero quelli inviati dal server e accettati dal client. In ordine:
il server avvisa il client che si è connesso
il server avvisa il client che il giocatore il cui nome e il cui numero sono dati dai due parametri si è presentato correttamente
il server avvisa il client che il giocatore dato dal parametro è morto e va rimosso dalla lista dei giocatori
il server avvisa il client di essere il giocatore dato dal primo parametro, di un numero di giocatori nella partita dato dal secondo parametro
il server invia i pezzi di un giocatore a un client; i due parametri interi rappresentano un pezzo
il server avvisa il client che il gioco è iniziato; praticamente è implicito con il comando PLAY che il gioco è iniziato, ma per iniziare veramente tutti i client devono avere l'informazione di quanti giocatori sono nella partita, il loro numero e i pezzi assegnati: per questo la fase di inizio gioco è composta da una serie di comandi conclusa con START
una mossa; i 5 parametri sono rispettivamente: i primi due rappresentano il pezzo, posizione x, posizione y e rotazione
il server abilita il client a muovere
il giocatore dato dal primo parametro ha prodotto un quote contenuto nel secondo parametro; i quote dal giocatore zero vengono considerati errore e gestiti facendo uscire una finestra di popup.
il server avvisa che il gioco è finito
Se il client è eseguito in modo che eviti i controlli interni sullo stato del gioco, il comando GO è disabilitato e il client può muovere sempre.
Ovvero quelli accettati dal server e inviati dal client; in ordine:
un client si presenta con il nome dato dal parametro
un client chiede di iniziare il gioco
un client chiede di eseguire una mossa; i 5 parametri sono come in precedenza il pezzo (primi due), posizione x, posizione y e rotazione
un client invia un quote al server