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.