Old version page
Crobots Tox Theory
Sebbene sicuramente non sia la persona più indicata per spiegarvi il significato di certi numeri nelle funzioni di fuoco, tuttavia tenterò di rendervi partecipi delle idee che mi sono fatto su tali formule che, in effetti, ad una prima occhiata sembrano qualcosa di assurdo e incomprensibile!!
Ovviamente le conclusioni a cui sono giunto non 
saranno del tutto esatte (tutt'altro) per cui prego coloro che hanno 
maggiore esperienza di me a correggere tutti gli errori che ci saranno nella mia 
interpretazione!
Leggendo le mail degli ultimi giorni mi sono reso 
conto che alcuni di voi si sono posti le stesse domande che mi sono posto 
io lo scorso ottobre leggendo il codice dei Crobots dell'anno 
scorso!
Un esempio eclatante può essere quello riportato 
in una delle mail precedenti:
cannon((oang+(ang-oang)*3-(sin(ang-dir)/19500)),(range*200/(200+orange-range-(cos(ang-dir)/4167)))); 
Vediamo come si potrebbe giungere ad un risultato 
del genere:
Cosa deve fare una buona funzione di fuoco? 
Ovviamente colpire l'avversario con maggiore 
precisione e velocità possibile!
Per la velocità, a quanto ho capito, bisogna 
lavorare parecchio per ottenere buoni risultati. Questo perché sono 
innumerevoli i fattori che influenzano tale parametro:
per prima cosa il fatto che la funzione CANNON ha 
bosogno di un tot di cicli virtuali per ricaricarsi. Quindi è necessario 
impiegare bene il tempo che per forza di cose deve intercorrere fra un 
colpo e il successivo! Tale intervallo tra un colpo e un 
altro tuttavia non è sempre uguale! Infatti nel frattempo il robot deve 
anche spostarsi e compiere qualunque altro tipo di controllo abbiamo ritenuto 
necessario inserire nel codice! Questo porta ad una difficoltà oggettiva nel 
riuscire a trovare la famosa e agognata routine di fuoco a cicli fissi che 
porterebbe a non perdere neanche un attimo fra la ricarica della funzione cannon 
e il fuoco successivo!
Tuttavia è possibile avvicinarsi a tale risultato 
almeno in due modi totalmente diversi:
Il primo: Routine di puntamento molto breve e 
veloce che si ripete più e più volte in attesa che la cannon si 
ricarichi!
Il secondo: Routine di puntamento molto lunga che 
impieghi invece tutti i cicli necessari alla ricarica della cannon in modo 
proficuo (praticamente cercando di approssimare al meglio la posizione 
dell'avversario)!
[Ovviamente è possibile realizzare routines che 
impieghino circa la metà o un terzo del tempo di ricarica, ma bisogna fare in 
modo che esse sieno ben sincronizzate col resto del codice, cosicchè al momento 
in cui la cannon è pronta a sparare, si sia giunti nell'esecuzione del codice 
il più vicino possibile al successivo comando Cannon!]
Sulla velocità di fuoco abbiamo l'onore di 
avere dei maestri qui il ML!! Ricordo il mio stupore nella lettura dei codici 
dei Robot di Simone Ascheri o Daniele Nuzzo! (non me ne vogliano 
gli altri ma mica potevo leggere tutti i sorgenti :) Questi ho letto:) ) In 
tali robot le funzioni erano scritte seguendo tali principi! 
Ricordo altresi' (non vorrei sbagliarmi ma l'ho 
provato solo una volta) che il famoso Tox invece aveva una funzione che puntava 
bene l'avversario ma lasciava a desiderare per quanto riguarda la velocità di 
sparare i colpi!
Veniamo adesso alla precisione (che era anche il 
motivo per cui volovo scrivere questa mail):
I paramentri che dobbiamo tenere in considerazione 
quando tentiamo di colpire un avversario sono i seguenti:
Moto dell'avversario.
Moto del proprio robot.
Tempo che passa da quando scanniamo la prima volta 
a quando scanniamo la volta successiva.
Tempo che passa da quando scanniamo l'ultima volta 
a quando facciamo partire il colpo.
Tempo che passa da quando parte il colpo a quando 
arriva il colpo!
Riferendomi per prima cosa alla seconda parte della 
formula (correzione di gittata):
Gittata=range*200/(200+orange-range-(cos(ang-dir)/4167))
(Per la correzione di angolo si possono fare le 
stesse considerazioni ovviamente modificando parametri e costanti!)
Moto dell'avversario: scanniamo due volte in modo 
da trovare la differenza di distanza! 
    Chiamiamo orange il risultato 
del primo scan, range il risultato del secondo!
    dalla differenza dei due valori 
possiamo scoprire se il rob avversario si avvicina o allontana da 
noi.
Tramite la semplicissima formula 
range*2-orange abbiamo trovato la distanza a cui in 
teoria dovrebbe trovarsi l'avversario esattamente dopo lo stesso tempo 
intercorso tra il primo e il secondo scan! Questo è fondamentale! 
Dobbiamo quindi apportare la prima modifica alla 
gittata trovata dovuta al fatto che il missile impiegherà un tot di tempo ad 
arrivare fino al bersaglio, e tale tempo non è uguale al tempo intercorso tra i 
due scan! Come possiamo trovare tale tempo? Innanzitutto dobbiamo calcolare la 
velocità a cui vanno i missili!! Questo mi ricordo di averlo calcolato facendo 
prove sparando ad una distanza fissa e aiutandomi con routines sincronizzate! 
CMQ, veniva fuori (ovviamente non sono assolutamente sicuro di tali valori!! Si 
tratta di valori empirici!!) che il missile viaggia a 3,333 metri a ciclo! 
Insomma, in 30 cicli fa 100 metri!
Ora possiamo calcolare quanti cicli ci vogliono per 
arrivare al bersaglio! basta dividere la distanza del bersaglio per i metri 
percorsi a ciclio dal missile! Ovviamente la distanza è ancora una incognita! 
Chiamiamola Gittata. Quindi num di 
clicli per arrivare al 
bersaglio=Gittata/3.333.
Abbiamo calcolato quanti cicli ci vogliono per 
arrivare al bersaglio! Sappiamo quanti cicli ci sono tra le due scan (le abbiamo 
scritte noi!).. dividiamo i due valori e otteniamo la costante che ci serve per 
correggere la formula! Questa costante non fa altro che tenere conto del 
movimento del nemico e del tempo che passa da quando lo individuamo a quando il 
colpo arriva sul bersaglio!
Quindi prendiamo la nostra formula 
(Gittata=range*2/orange) e la 
modifichiamo:
< Gittata=(range*2/orange)*((Gittata/3.33)/(num cicli fra 
i due scan))
Tramite semplici passaggi algebrici (portiamo la 
variabile a sinistra:)) otteniamo:
Gittata=(range*j)/(j+orange-range) con 
j costante.
Possiamo vedere subito come questa formula inizi ad 
essere molto simile a quella assurda formula di cui si parlava prima!! Il 
200 della formula è proprio la costante j di questa! Tali costanti devono tener 
conto del numero di cicli fra gli scan etc etc quindi dipenderanno molto dal 
nostro codice! Nel mio Crobot ad esempio questo valore era 60. Ovviamente alla 
fine il modo migliore per trovare tale valore è provare e riprovare tante volte 
fino a quando si ottengono i risultati migliori :))
Non abbiamo ancora considerato tuttavia il moto del 
nostro robot!! Infatti, nel frattempo, anche il nostro robot si è mosso (tranne 
se non avete programmato un pazzo masochista che sta fermo a beccarsi i 
colpi!!)
Adesso il discorso si fa un pò più complicato.. 
almeno per me lo è stato!
Come possiamo considerare il nostro moto? 
Innanzitutto sappiamo in che direzione ci stiamo muovendo(basta salvare su una 
variabile l'angolo quando cambiamo direzione) e possiamo sapere anche a che 
velocità lo stiamo facendo (funzione speed()).
Chiamiamo dir proprio la 
direzione verso cui ci stiamo muovendo!
Adesso sarebbe molto utile un bel disegnino 
esplicativo..
Riflettiamo un attimo.. noi ci avviciniamo al 
nemico se la differenza fra l'angolo in cui abbiamo individuato il 
nemico(chiamiamola ang) e l'angolo verso cui ci 
stiamo muovendo (la nostra dir)è minore di 90 gradi! 
Se tale differenza è maggiore di 90 gradi allora ci stiamo allontanando dal 
nemico! Tra l'altro, minore è questa differenza, maggiore sarà la velocità 
verso cui ci avviciniamo al nemico! Infatti, se la differenza sarà giusto 0, 
vuol dire che ci stiamo muovendo esattamente verso il nemico! Se ci fate 
caso vale anche il contrario: se la differenza è proprio 180 ci stiamo 
dirigendo esattamente dalla parte opposta rispetto al nemico! Per fortuna la 
matematica ci viene (una volta tanto) incontro e ci fornisce una bella funzione 
che risponde a queste nostre esigenze! Ovviamente mi riferisco alla funzione 
COSENO! Tale funzione è esattamente proporzionale alla velocità con cui ci 
avviciniamo o ci allontaniamo dal nemico! Infatti 
cos(ang-dir)=1 per 
ang-dir=0;
cos(ang-dir)=-1 per 
ang-dir=180;
cos(ang-dir)=0 per 
ang-dir=90 o -90;
Cosa possiamo farci con questo 
cos(ang-dir) ? Possiamo moltiplicarlo ad una bella 
costante e aggiungerlo (o meglio sottrarlo visti i segni!) alla nostra 
formula per tenere conto quindi anche del nostro movimento!
Io avevo fatto di più nella mia funzione di fuoco: 
avevo moltiplicato cos(ang-dir) (oltre che alla 
costante) anche allo speed() in quanto anche la nostra 
velocità (e non solo la direzione) influisce sul movimento! tuttavia ritengo 
che si possa soprassedere visto che magari la perdita di cicli dovuti alla 
chiamata di tale funzione fa perdere piuttosto che guadagnare in precisione! 
Meglio considerare la velocità a cui di solito ci muoviamo e aggiungerla alla 
costante!
La nostra costante come deve essere calcolata? 
Semplice: tenendo presente
1) quella che riteniamo la velicità a cui ci 
muoviamo di solito (immagino 100)
2) le solite considerazioni sui cicli!
3) Importantissimo: la scala con cui vengono 
forniti i risultati delle funzioni trigonometriche!!
Poiche la scala è molto alta allora ci conviene 
dividere per l'inverso della costante trovata piuttosto che moltiplicare (visto 
anche che è possibile utilizzare solo numeri interi!) Infatti la costante che 
viene fuori è un num  compreso tra 0 e 1 e tendente allo 
0!
Ed ecco che viene fuori la formula 
finale:
Gittata=(range*j)/(j+orange-range-(cos(ang-dir)/k)) 
dove k è la nuova costante 
trovata!
La formula, a meno delle costanti, è identica a 
quella iniziale!
Ovviamente al posto della / si puo mettere >> 
e al posto del * si può mettere << (operazioni sui bit che, per chi non 
lo sapesse, corrispondono alla divisione o moltiplicazione per le potenze di 2). 
In questo modo le costanti utilizzate possono essere soltanto potenze di due 
(come aveva fatto notare qualche tempo fa credo Daniele).. tuttavia si tratta 
solo di abitudine o preferenze personali perché credo che nel caso di Crobot 
non cambi la velocità di esecuzione fra una divisione normale o uno spostamento 
di bit..:) (ma anche qui potrei sbagliarmi alla grande!)!
Spero di aver chiarito qualche dubbio e vi prego di 
operare tutte le correzioni e aggiunte che vi verranno in mente!
Fate conto che, vista la lunghezza, non mi va di rileggere il tutto :) 
Spero di non aver fatto almeno errori grammaticali!!
Ciao,
Michele Miccar Cardinale.