Friday, January 18, 2008

149597870 + 1 = 149597872

Sarò un pò più tecnico del solito, ma ciò che ho passato, per colpa di una somma, merita senz'altro la pubblicazione.
Come detto in precedenza ho deciso di utilizzare la doppia precisione, così da riuscire a gestire sia distanze siderali, che distanze ravvicinate.
Bene: ho posizionato la mia astronave a 1 au di distanza dal sole, ovvero 149597870 km dal sole.
Dopodichè ho impostato la tastiera affinchè premendo il tasto W la posizione aumentasse ogni volta di 1 km.
Provo e.. l'astronave non si muove.
Guardo e riguardo il codice e mi sembra tutto a posto.
A questo punto decido di stampare a video le coordinate per vedere che succede.. e mi accorgo che la prima volta che premo W, il valore diventa 149597872 (!!), e alle seguenti pressioni rimane 149597872.
Cioè, pure una calcolatrice anni '70 sa fare 149597870 + 1, possibile che un dual core con FPU no?
Ovviamente mi dico: "è senz'altro colpa mia, chissà che ho combinato".
Provo a creare un progetto vuoto e ci scrivo quella somma e lancio.
Funziona.
"Come immaginavo, ho sbagliato io"
Torno al mio progetto, eseguo la somma ad inizio programma e nel punto dove sbaglia. Ad inizio programma funziona, nel punto in cui gestisce la pressione del tasto W no.
Comincio a togliere tutto il superfluo per isolare la causa dell'errore.. arrivo a commentare TUTTO, tranne la gestione del tasto W, sparisce tutto quanto, rimangono solo due somme; una all'inizio e una dopo la "se ho premuto W". Nient'altro.
Non va. All'inizio la somma e' corretta, dopo l'if no.
L'informatica è una scienza esatta, almeno fino a ieri lo pensavo.. disperato inizio a chiedere in giro, non riesco davvero a capire.
E una persona, gentilissima, mi rivela l'arcano.

A quanto pare DirectX, quando invocata, si diverte a abbassare la precisione del coprocessore matematico, "dimenticandosi" di risistemarla quando ripassa il controllo al mio programma.
Ergo: il programma parte, la precisione è a posto, e la somma funziona, subito dopo DirectX mette le mani, ed ecco che la seconda non va più.

Pazzesco.

Ad ogni modo, per la cronaca, per risolvere tutto è bastato aggiungere

_control87(_CW_DEFAULT, MCW_PC);

prima della somma.

3 comments:

Kormoran said...

Ciao, sono uno di quelli che ti ha risposto su it.comp.lang.C++ :-)
Ho giocato anch'io a Frontier ai tempi, e penso ancora che sia uno dei migliori giochi mai concepiti (nonostante la marea di bug che lo rendeva ingiocabile... sob).

Ho creato io la versione italiana della Wiki di Vegastrike, è da tanto che pensavo di collaborare al codice per dare una mano a creare un gioco completo, ma è sempre rimasta una pia intenzione. Lode a te che l'hai fatto veramente ^_^

Kormoran said...

Leggendo i commenti lasciati al tuo blog vedo che hai pensato a come implementare i nomi delle stelle. Io a suo tempo mi ero posto lo stesso interrogativo, e avevo pensato di ricorrere al catalogo stellare NGC, che elenca praticamente tutte le stelle VISIBILI vicine al Sole più le stelle più luminose e più distanti (decine di migliaia di oggetti!). Il catalogo è pubblico, avevo anche trovato dove scaricarlo... ma non ricordo più il sito, sob :-(

Per le altre avevo pensato a un meccanismo pseudorandom simile al tuo, con la differenza che le stelle venivano create "on the fly" quando era necessario per riempire i vuoti, e lo stesso per il loro sistema planetario: quando il giocatore visionava la prima volta il sistema planetario della stella avevo creato una serie di funzioni che ricavava il seme pseudorandom dal timer di sistema, LO SALVAVA insieme al riferimento alla stella nei dati di salvataggio del gioco, e con quello creava la congrega di pianeti, lune e asteroidi e oggetti vari. Avevo anche ideato un sistema di nomenclatura per i pianeti "non battezzati": ponendo che la stella si chiamasse Merak, allora "Merak 5" era il quinto pianeta della stella Merak, "Merak 6c" era la terza luna (c) del sesto pianeta, "Merak 2alpha" la prima stazione orbitale del secondo pianeta... per sistemi planetari di stelle doppie (in Frontier esistevano!!) avevo pensato a una nomenclatura come "Merak Aleph 3" per il terzo pianeta nella zona di stabilità interna della prima delle due stelle: le lettere ebraiche identificavano le zone di stabilità interne, mentre nella zona di stabilità esterna, unica per tutto il sistema planetario, vigeva la nomenclatura normale...

Non so se ti può essere utile, se ti piace usala, se no no... l'importante è che riesci a creare sul serio un nuovo Frontier :-)

PdG said...

Grazie kormoran, il tuo suggerimento è in effetti interessante e lo terrò in considerazione non appena mi riapplicherò alla faccenda dei nomi.
Per ora son preso dal difficile compito di riuscire a implementare decentemente una scala che mi rappresenti sia distanzi siderali che distanze di qualche centinaio di metri.