/* MM MM MMMM MMMM MM MM MM MM MM MM MM MM rr rr MM MMM MM rr rrrr MM MM rrr MM MM rr .. MM MM rrrr .. SSSSSSSSSSS AAAAAAAAAAA TTTTTTTTTTTTT AAAAAAAAAAA NNN NN SSSSSSSSSSSSS AAAAAAAAAAAAA TTTTTTTTTTTTT AAAAAAAAAAAAA NNNNN NN SS SS AA AA TTT AA AA NN NN NN SS AA AA TTT AA AA NN NN NN SSSSSSSSSSS AAAAAAAAAAAAA TTT AAAAAAAAAAAAA NN NN NN SSSSSSSSSS AA AA TTT AA AA NN NN NN SS SS AA AA TTT AA AA NN NNNN SSSSSSSSSSSSS AA AA TTT AA AA NN NNN GSSSSSSSSSS AA AA TTT AA AA NN NN Nome : MrSatan.r (29-10-2000) Autore : Simone Ascheri Scopo : E' convinto di essere l'uomo piu' forte del pianeta, e quindi si e' offerto di sconfiggere Cell. LA STORIA ========= Sconfitto Freezer Goku inizia il viaggio di ritorno sulla Terra. Purtroppo impiega piu' tempo del previsto e il nemico, sotto forma di Metal Freezer, lo precede sul pianeta, insieme al padre Cold, per vendicarsi. Tutto e' perduto? Nemmeno per sogno, poiche' arriva un misterioso guerriero che, trasormatosi in SuperSayian, distrugge con facilita' i due. All'arrivo di Goku si rivela come Trunks, figlio di Vegeta, tornato indietro nel tempo per avvisare la squadra Z di una nuova minaccia (i cyborg del dottor Gelo) e dare una medicina a Ka_aroth. Questi infatti morira' di un attacco di cuore nel futuro, prima di poter affrontare i nemici. Questi non troveranno resistenza alcuna e stermineranno la razza umana. La squadra Z inizia subito gli allenamenti, ma il viaggio a ritroso di Trunks ha gia' cambiato il corso della storia, che non si sviluppa piu' come il Sayian aveva predetto. Infatti dal futuro arriva un nuovo Cyborg del dottor Gelo, completamente sconosciuto per il giovane Trunks. Ha viaggiato nel tempo con lo scopo di trovare C17 e C18, i primi due androidi, che nella sua epoca Vegeta aveva distrutto (altro cambio delle ramificazioni storiche). Dopo averli assorbiti si trasforma nell'essere perfetto, pronto a distruggere l'universo. Ne' Trunks, ne' Crilin, ne' Junior ne' Vegeta sembrano in grado di tenergli testa, ma prima che Goku possa iniziare a battersi sale sul ring un nuovo, fortissimo (almeno cosi' lui si crede) atleta.......... MrSatan:-) COMPORTAMENTO ============= Data la mancanza di tempo, il robot e' esattamente uguale a Vegeth.r, con la sola eccezione della routine d'attacco finale e dello spostamento di angolo in angolo, che non sempre avviene con moto epilettico. Fase Iniziale ------------- All' inizio del Match MrSatan cerca un angolo libero, cominciando da quello piu' vicino, e (non troppo) prontamente lo raggiunge (in particolare ho notato che, prima che il mio crobot spari un colpo, gli avversari ne hanno gia' esplosi due). Conta quindi gli avversari, e se ne trova solo uno lo attacca con il SuperVegeth, per l'occasione ribattezzato MalDiPancia. Altrimenti inizia a muoversi parallelamente ad un lato e a sparare. La scelta della direzione in cui oscillare dipende da alcuni fattori: A) Se i danni sono inferiori all'80%: ================================== Se sono presenti avversari statici: =================================== -MrSatan li cerca innanzitutto nell' angolo seguente, e in caso affermativo li attacca... -Altrimenti guarda nell' angolo precedente e li attacca... Altrimenti controlla presenza e distanza dei nemici negli angoli adiacenti e: ============================================================================= - Se e' all'inizio del match si dirige vero l'angolo libero oppure attacca l'avversario piu' lontano (in caso non vi fossero angoli vuoti) - Se sono trascorsi almeno 100000 cicli attacca sempre l'avversario piu' vicino. Se i danni sono superiori all'80%: ================================== - Oscilla sulla bisettrice del quadrante con brevi movimenti: in pratica si tratta della mia personalissima versione del vincitore dello scorso anno, con la differenza che MrSatan utilizza, in questa situazione, la routine di fuoco piu' precisa di cui dispone: la sfera GenkiDama(). In ogni caso, se MrSatan subisce troppi danni o ha un nemico troppo vicino cambia posizione. Fase Finale ----------- Ogni 10000 cicli circa MrSatan conta gli avversari: 1 * Se c' e' piu' di un superstite continua il movimento cambiando angolo se ha subito troppi danni. 2 * Se invece si accorge di avere solo piu' un avversario parte con l'attacco finale, il CalcioInFaccia. Si tratta della mia visione del movimento di Satana.r, che sembra dare risultati migliori del SuperVegeth/MalDiPancia in torneo9198. Routine di Movimento -------------------- La routine e' unica per tutte le posizioni dello schermo. Calcola la distanza (al quadrato, evitando cosi' una radice) rispetto ad un punto dato [(20,20)(980,20)(980,980)(20,980)], trova l' angolo necessario per raggiungerlo e infine inizia a muoversi in quella direzione. Quando arriva a destinazione si ferma. Sceglie una direzione parallela ad uno dei lati con il sistema visto precedentemente e si avvia, camminando fino a quando non si trova alla massima distanza stabilita dal punto. Inverte quindi il movimento e riinizia dal principio. NOTE TECNICHE ============= Il robot utilizza quattro diverse routine di fuoco: - Il KaiOKen() e' l'ormai nota variante della routine di fuoco di Arale: presenta la particolarita' di cambiare il tipo di puntamento dopo i 140000 cicli di cpu virtuale. - La KameAmeA() e' la routine di sempre, con marginali modifiche. - Il SuperSayan() e' quasi completamente nuovo: 1 - ho eliminato completamente i blocchi di puntamento della toxica base, sostituiti da altri a tempo di esecuzione costante; 2 - ho ricalibrato tutti i parametri usando le divisioni (piu' personalizzabili) al posto degli shift; 3 - la correzione avviene ora sul primo angolo di scansione, non piu' sull'ultimo. - La GenkiDama() e' la routine piu' precisa di cui dispone MrSatan. Purtroppo la sua efficacia e' massima quando la velocit… del robot e' compresa tra i 30 e i 60 metri, per cui e' usata solo nelle oscillazioni stile Dav46.r e negli attacchi finali. E' una rielaborazione della fire di Jaja.r. In particolare: 1 - ho modificato la find() riducendola a circa 1/3 della sua lunghezza; 2 - ho inserito dei correttivi per i tiri a breve distanza. Lo spostamento da un angolo all'altro avviene, a differenza che in Vegeth, muovendosi in linea retta. L'ampiezza dell'oscilazione base e' di circa 250 unita', ma puo' allungarsi o accorciarsi a seconda dei danni subiti nell'unit… di tempo. RINGRAZIAMENTI ============== Un sentito grazie a: - Tom Poindexter (per averci donato Crobots [pero' .... questi sorgenti....]). - Maurizio 'JOSHUA' Camangi per le tonnellate di e-mail che ci siamo scambiati. - Il 'misterioso benefattore' per aver innalzato il limite di istruzioni di crobots. - Michelangelo Messina per aver gentilmente assecondato tutte le mie richieste di modifica al suo Torneo2k e aver sviluppato ECAT. - Marco Pranzo, per l'insostituibile CrobotsHelper 2.0 e per gli irresistibili commenti ai suoi robot. - Tutti coloro con i quali ho scambiato pareri in questi mesi. Un enorme ringraziamento ad AKIRA TORIYAMA per aver creato DragonBall e DragonBall Z. INSULTI ======= Una nutrita serie di improperi va chi ha deciso di trasmettere i Cavalieri dello Zodiaco al posto di DragonBall il sabato e la domenica. SCUSE ===== Mi scuso in anticipo con i pochi che cercheranno di leggere il sorgente: non solo e' molto intricato, ma quest'anno non ho proprio avuto il tempo di commentarlo a dovere.... e' anche possibile che vi siano ancora riferimenti a SonGohan.r Mi scuso inoltre per gli eventuali strafalcioni nella documentazione di cui sopra: il robot (attacco finale a parte) era pronto 3 mesi fa, e da allora l'ho riguardato pochissimo. Potrei aver confuso un po' le cose. */ int park, ux, uy, dx, dy; /*Variabili posizionali*/ int flag, vang, ang, ang2; /*Variabili direzionali*/ int dan, timmax; /*Variabili temporali*/ int dir, ango, oang, range, orange; /*Variabili balistiche*/ int dang, alfa, corr, anco, nrg, rg; int att, max, clock, gira, time, klik, scn; main() { /*Calcola coordinate iniziali e agolo principale*/ ang2=(Trova((dy=980-(loc_x()>500)*960), (1000-(dx=(loc_y()>500)*960+20)))/90*90); while (Ricerca(Trova(OooHoo(ang2+=90),dy=park))>400); NuvolaSpeedy(dx,dy); max=57000; if (Reeft(ang2,37)<3) MalDiPancia(); while (timmax+=6) /*Ciclo principale*/ { while (--timmax) /*Movimento oscillatorio*/ { /*Decide se e' il momento di cambiare angolo, in base ai danni e alla posizione del nemico*/ if ((dan60)) max=30000; else if ((time>10)&&(damage()<40)) max=70000; if (damage()>80) { dan=damage(); while (dan==damage()) Senzu(); } else { if (orange=Ricerca(ang2+630)) { while (speed()); if ((orange=Ricerca(ang2+630))&&(Ricerca(ang2+630)==orange)) flag=630; } if (!flag) { if (Ricerca(ang2)) { while (speed(flag=630)); if ((range=Ricerca(ang2))&&(Ricerca(ang2)==range)) flag=0; else if (!orange) { if (time>11) flag=0; } else if (range>orange) flag=0; } else if ((orange)&&(time>11)) flag=630; } drive (ang=(ang2+flag),100); /*Si allontana dall' origine*/ while ((Dista(dx,dy)18))) /*Controlla quanti sono i sopravvissuti*/ CalcioInFaccia(); else if ((park==2)&&(dan10000) fuoco(Trova(dx,dy)); if (scn5200)&&(speed())) if (h<25000) KaiOKen(); else SuperSayian(); return KameAmeA(); } Trova(mx,my) /*Individua l' angolazione necessaria per raggiungere un punto dato*/ int mx, my; { return (ang=(360+((mx-=loc_x())<0)*180+atan(((my-loc_y())*100000)/mx))); } Dista(nx,ny) /*Calcola la distanza rispetto ad un punto dato*/ int nx, ny; { return (((nx-=loc_x())*nx+(ny-=loc_y())*ny)); } OooHoo() /*Effettua la rotazione degli angoli da controllare*/ { park=dx; return(dx=(1000-dy)); } Ricerca(an) int an; { return (scan(an+350,10))+(scan(an+10,10)); } KameAmeA() /*Procedura di rallentamento standard*/ { drive(ang,0); TrovaAura(); if ((range=scan(ango,10))&&(range<850)) cannon (ango,range); else Ceck(ang); } Stop() /*Procedura di rallentamento speciale*/ { drive (dir,40); ango+=10; while(!scan(ango+=21,10)); KaiOKen(); } Reeft(dsiete,dand) /*Conta i superstiti*/ int dsiete, dand, qsiete; { while (--dand) qsiete+=(scan(dsiete+=20,10)!=0); return (qsiete); } MalDiPancia() int z; { NuvolaSpeedy(time=500,500); vang=((ango+180)/90)*90; while (fuoco(vang+50)) { fuoco(vang-50); if (((loc_x()%750)<250)||(z=((loc_y()%750)<250))) { if (nrg) cannon(ango+(ango-oang)*3,nrg); vang=180*(!z)*(loc_x(gira=3)>500)+(90+180*(loc_y()>500))*z; } else { if (--gira); else { vang=((ango+180)/90)*90; gira=3; if ((nrg>350)||(!nrg)) { dan=damage(); while (dan==damage()) { fuoco(vang-90); fuoco(vang+90); } } } } } } CalcioInFaccia() int z; { NuvolaSpeedy(time=500,500); vang=((ango+180)/90)*90; while (drive(ang=vang,att=100)) { SuperSayian(); if (--gira) { if (((loc_x()%700)<300)||(z=((loc_y()%700)<300))) vang=180*(!z)*(loc_x(gira=3)>500)+(90+180*(loc_y()>500))*z; } else { vang=(((ango+180)/90)+(clock^=1))*90; gira=3; } if ((gira==3)&&(ang!=vang)) KameAmeA(); } } TrovaAura() { if (TrovaB()) return 1; if (TrovaB(ango-=19)) return 1; if (TrovaB(ango+=38)) return 1; return 0; } TrovaB() { if ( nrg = scan(ango,10) ) { if ( scan(ango+6,5) ) { if ( scan(ango+2,2) ) { if ( scan(ango+4,1) ) { if ( scan(ango+3,0) ) ango+=3; else ango+=4; } else if ( scan(ango+2,0) ) ango+=2; else ango+=1; } else { if ( scan(ango+8,1) ) { if ( scan(ango+7,0) ) ango+=7; else ango+=9; } else if ( scan(ango+6,0) ) ango+=6; else ango+=5; } } else { if ( scan (ango-1,2) ) { if ( scan(ango-3,1) ) { if ( scan(ango-2,0) ) ango-=2; else ango-=3; } else if ( scan(ango-1,0) ) ango-=1; else ango-=0; } else { if ( scan(ango-4,1) ) { if ( scan(ango-5,0) ) ango-=5; else ango-=4; } else if ( scan(ango-6,1) ) ango-=6; else ango-=8; } } return 1; } return 0; } /*Procedure di fuoco*/ fuoco(a) int a; { drive (dir=a,100); if (TrovaAura()) { drive(dir,100); GenkiDama(); } else Stop(); } GenkiDama() { if (TrovaAura(oang=ango)) { drive (dir,40); if (nrg<130) { if (nrg<50) return cannon(ango+(ango-oang)*3,2*scan(ango,10)-nrg); return KaiOKen(); } corr=cos(alfa=(ango-dir)-((ango-dir)/360)*360); dang=ango+(ango-oang)*3-sin(alfa)/17600; if (rg=scan(ango,10)) cannon (dang,rg*350/(350+nrg-rg-corr/3000)); else Ceck(oang); } else Stop(); } /*Spara con media precisione*/ KaiOKen() { if((orange=scan(ango,10))&&(orange<850)) { if (time>13) return cannon (ango+=5-10*(scan(ango-5,5)>0),2*scan(ango,10)-orange); if (range=scan(ango+353,4)) cannon(ango+=353,range); else if (range=scan(ango,3)) cannon(ango,range); else if (range=scan(ango+7,4)) cannon(ango+=7,range); } else if((range=scan(ango+=339,10))&&(range<770)) cannon(ango,range); else if((range=scan(ango+=42,10))&&(range<770)) cannon(ango,range); else return (ango+=40); } Ceck(direz) int direz; { if (range=scan(ango+=340,10)); else if (range=scan(ango+=40,10)); else if (range=scan(direz,10)) ango=direz; else return (ango+=40); return cannon(ango,2*scan(ango,10)-range); } /*Spara con buona precisione sia da fermo che in movimento*/ SuperSayian() { if (TrovaAura()) { if ((nrg>700)&&(!att)) return KaiOKen(); else if (nrg<150) { cannon (ango,nrg); } else { if (orange=scan(oang=ango,10)) { TrovaB(); if (range=scan(ango,10)) cannon((oang+(ango-oang)*3-(sin(ango-ang)/19500)),(range*160/(160+orange-range-(cos(ango-ang)/4167)))); } else return Ceck(ang); } } else Ceck(ang); }