1998/son-goku.r

001/*               SSSSSSSSSSS       OOOOOOOOOOO    NN       NN
002                SSSSSSSSSSSSS     OOOOOOOOOOOOO   NNNN     NN
003                SS         SS     OO         OO   NN NN    NN
004                SS                OO         OO   NN  NN   NN
005                 SSSSSSSSSSS      OO         OO   NN   NN  NN
006                   SSSSSSSSSS     OO         OO   NN    NN NN
007                SS         SS     OO         OO   NN     NNNN
008                SSSSSSSSSSSSS     OOOOOOOOOOOOO   NN      NNN
009                 GSSSSSSSSSS       OOOOOOOOOOO    NN       NN
010 
011       GGGGGGGGGGG       OOOOOOOOOOO      KK       KK     UU         UU
012      GGGGGGGGGGGGG     OOOOOOOOOOOOO     KK      KK      UU         UU
013      GG         GG     OO         OO     KK     KK       UU         UU
014      GG         GG     OO         OO     KK    KK        UU         UU
015      GG                OO         OO     KKKKKKK         UU         UU
016      GG       GGGG     OO         OO     KK    KK        UU         UU
017      GG         GG     OO         OO     KK     KK       UU         UU
018      GGGGGGGGGGGGG     OOOOOOOOOOOOO     KK      KK      UUUUUUUUUUUUU
019       GGGGGGGGGGG       OOOOOOOOOOO      KK       KK      UUUUUUUUUUU
020 
021   Nome      : Son-Goku.r  (13-09-98)
022 
023   Allenatore: Muten - Il genio delle tartarughe di mare -
024 
025   Autore    : Simone Ascheri
026 
027   Scopo     : Partecipare all' VIII torneo di Crobots di MC
028 
029LA STORIA
030=========
031 
032Son-Goku un bel giorno decide di partecipare al grande torneo TenKaiChi.
033Salta quindi sulla sua nuvoletta Speedy, regalo del vecchio Muten (il genio
034delle tartarughe di mare),  e va alla pugna.
035Attacca i nemici con tre tipi di colpi :
036il GreatSayian, (il piu' preciso), il Sayian (un compromesso tra precisione
037e velocita') e l' onda KameAmeA (la piu' veloce, ma di scarsa precisione).
038 
039COMPORTAMENTO
040=============
041La strategia di Goku e' abbastanza complicata.
042Il crobot infatti puo' adottare diverse tattiche a seconda della posizione,
043del tempo trascorso, dei danni subiti ed infine del caso.
044La parte piu' difficile di tutto il lavoro e' stata la ricerca del giusto
045equilibrio tra le varie parti di Goku. Quello attuale sembra funzionare
046discretamente, ma e' ben lungi dall' essere quello ideale.
047 
048Fase Iniziale
049-------------
050All' inizio del Match Goku cerca un angolo libero, cominciando da quello piu'
051vicino, e (non troppo) prontamente lo raggiunge.
052A questo punto controlla i danni e decide:
053 
054 1 * Se ne ha subiti meno del 5% si ferma e spara ai crobot che gli capitano
055     a tiro. Si comporta come NCMPLT.R fino a quando non subisce un altro 6%
056     di danni. Seleziona quindi il movimento finale a rombo e pasa al punto
057     due.
058     Se invece trascorrono pacificamente circa 100000 cicli di CPU inizializza
059     il movimento finale in diagonale e passa direttamente ai movimenti
060     conclusivi.
061 2 * Cambia angolo, inizia a muoversi parallelamente ad un lato e a sparare.
062   
063Le routine di fuoco sono tre, tutte spudoratamente copiate:
064 
065 A * Mentre si allontana dagli angoli usa la routine di DIABOLIK.R
066     (GreatSayian, edizione integrale)
067 B * Quando ritorna verso gli angoli si appropria del codice di COLOSSUS.R
068     (Sayian, leggermente modificato)
069 C * Quando decelera spara senza correzione (KameAmeA)
070 
071Goku e' un po' misantropo.
072Se infatti si accorge di condividere il suo bell' angoletto con un altro
073crobottino cambia posizione.
074 
075Movimento
076---------
077La routine e' unica per tutte le posizioni dello schermo e per due dei tre
078attacchi finali.
079Calcola la distanza (al quadrato, evitando cosi' una radice) rispetto ad un
080punto dato [(20,20)(980,20) (980,980)(20,980)], trova l' angolo necessario per
081raggiungerlo e infine inizia a muoversi in quella direzione. Quando arriva a
082destinazione si ferma.
083Sceglie una direzione parallela ad uno dei lati e si avvia, camminando fino a
084quando non si trova alla massima distanza stabilita dal punto.
085Inverte quindi il movimento e riinizia dal principio.
086Dopo un certo numero di cicli il movimento diventa prima una L e infine
087perpendicolare a quello iniziale.
088Parte quindi la routine di attacco finale.
089 
090Fase Finale
091-----------
092Dopo circa 100000 cicli Goku conta gli avversari:
093 
094 1 * Se c' e' piu' di un superstite continua il movimento cambiando di angolo
095     ogni 12 oscillazioni:
096        - Fino a che i danni sono inferiori al 20% il moto rimane parallelo
097          ad un lato dell' arena.
098        - Dopo di che oscilla perpendicolarmente alla bisettrice dell' angolo.
099 2 * Se i crobot sono invece rimasti in due Son-Goku sceglie una di queste tre
100     strategie:
101 
102   A * Se i danni sono maggiori dell' 80% si sposta di angolo libero in angolo
103       libero cercando di colpire il crobot superstite, oscillando
104       perpendicolarmente alla bisettrice del quadrante.
105   B * Si muove lungo una diagonale (come Drago6.r) con cambio di diagonale ogni
106       volta che l' angolo base e' occupato (raro).
107       Tale schema viene ripetuto dodici volte, per poi passare al punto C.
108   C * Adotta un movimento a rombo con vertici nei punti medi dei lati della
109       arena (come Diabolik.r), alternato con movimento a girandola con
110       vertici negli stessi punti (sempre se il movimento precedente era a 45
111       gradi).
112       Questo schema puo' essere scelto direttamente o come appendice al punto
113       B.
114  
115CONSIDERAZIONI
116==============
117Il Crobot gia' si comporta male con gli avversari di quest' anno, figuriamoci
118con quelli del prossimo torneo.
119La routine di movimento e' molto generica e si puo' adattare a quasi ogni
120schema di gioco.
121 
122Purtroppo il suo maggior pregio e' anche il suo limite principale.
123Dalla sua ha infatti la compattezza del codice, che consente di dedicare molto
124spazio alla parte offensiva del gioco.
125Per contro pero', tale compattezza e' ottenuta a prezzo di una maggior lentezza:
126il controllo della distanza dai bordi infatti richiede almeno 16 istruzioni,
127contro le tre necessarie normalmente.
128Questo rende il povero Goku molto piu' vulnerabile degli altri al fuoco nemico.
129In una partita media di 100000 cicli si perde l' 11% del tempo per il controllo
130della posizione, contro il 2% altrimenti necessario.
131          
132Inoltre, poiche' Goku non ha (ovviamente) modo di sapere quanto e' forte
133l' ultimo superstite, e poiche' renderlo in grado di riconoscere il tipo di
134movimento del nemico avrebbe richiesto routine troppo ingombranti, il
135mix delle varie tattiche disponibili e' stato stabilito empiricamente.
136Dopo numerosi tentativi l' efficienza del frugoletto e' passata dal 17.8% al
13743.7% in un mini-torneo a 8 giocatori. Non e' pero' detto che risultato
138ottenuto sia il migliore possibile. Anzi, nella peggiore delle ipotesi il
139crobot potrebbe prendere in ogni occasione la decisione meno adatta.
140 
141 
142Il programma e' abbastanza commentato, nel caso improbabile qualcuno si prendesse
143il disturbo di leggerlo.
144Per la spiegazione delle routine di fuoco rimando ai crobot citati, o ai loro
145eventuali ispiratori. Io le ho prese come parti pre-fabbricate.... funzionano
146e tanto mi basta.
147 
148RINGRAZIAMENTI
149==============
150 
151Un sentito grazie a Tom Poindexter (per averci donato Crobots) a Maurizio
152'JOSHUA' Camagni (per le sue indispensabili utilities) e a tutti coloro che,
153con i loro robots, hanno reso possibile l' esistenza di Goku (...in qualche
154caso, piu' che di semplice ispirazione, si e'trattato di un vero e proprio
155furto).
156 
157Un enorme ringraziamento ad AKIRA TORIYAMA per aver creato DragonBall e
158DragonBall Z.
159 
160*/
161 
162int timmax, max, min, ang, ang2, dx, dy, qsiete, dsiete;
163int ncmplt, dan, xx, yy, park, ango, oang, range, orange;
164int flag4, flag2, flag1, flag;
165 
166main()
167{
168 
169/*Inizializzazione variabili*/
170 
171min=10000;                                /*Distanza minima dalla destinazione*/
172max=90000;                                /*Ampiezza del movimento*/
173                                           
174ang2=(Trova((dy=980-(loc_x()>500)*960),   /*Cerca le posizioni sullo schermo*/
175     (1000-(dx=(loc_y()>500)*960+20)))    /*e trova l' angolo di oscillazione*/
176     /90*90);                            
177 
178/*Trova un angolo libero e lo raggiunge*/
179 
180Go();
181timmax=55+1400*(ncmplt=(dan<5));          /*Numero di cicli prima del movimento finale*/
182 
183/*Restiamo fermi*/
184 
185while (ncmplt)       
186     {
187       if (((--timmax)<28)|(dan<damage()-6))
188         {
189           if ((timmax=timmax/27)>1)
190             Go();
191           ncmplt=0;
192         
193         else Sayian(0);
194      }
195 
196flag4=timmax;                             /*Sceglie il tipo di movimento finale*/
197 
198/*Ciclo principale*/
199 
200while (1)                                        
201   {
202 
203/*Movimento oscillatorio*/
204 
205     while (--timmax)
206       {
207         drive (ang=(ang2+flag)%360,100);             
208         while (Dista(dx,dy)<max)
209            {
210              if ((flag==225)|(flag==315))
211                 GreatSayian();
212              else Sayian(1);      
213            }  
214 
215            KameAmeA(49);
216 
217            if (scan(ang+=180,10))
218              Go();
219            else
220                 {
221                  drive (ang,100);                
222                  while (Dista(dx,dy)>min)
223                       GreatSayian();
224                  }                   
225         if (((++flag1)%38>18)&&(flag!=225))
226            flag=630-flag;
227 
228  KameAmeA(49);
229        }
230 
231/*Movimento finale*/
232 
233timmax=12;
234 
235if ((!Reeft())&&(damage()<80))
236  {         
237      if (flag4<5)                                 /*Attacco diagonale*/
238         {
239          min=15000;
240          max=1350000;
241          flag4=flag=315;                          /*Nuovo angolo di oscillazione*/
242         }
243         else                                      /*Attacco romboidale*/
244        {
245         while (1)
246           {
247            NuvolaSpeedy(500,50);
248            NuvolaSpeedy(950-(flag2=450-flag2),500+flag2);
249            NuvolaSpeedy(500+flag2,950-flag2);
250            NuvolaSpeedy(50,500);           
251           }
252         }
253      }  
254   else
255     {
256        if ((flag4<220)&&(damage()>20))              /*Movimento a 45 gradi contro i bordi*/
257          {
258           dy+=16500000/sin(ang2);
259           dx+=16500000/cos(ang2);
260           flag4=flag=225;
261           max=25600;
262          }
263      Go();
264     }
265   }    
266}
267 
268/*Operazioni di servizio*/
269 
270/*Routine di spostamento verso coordinate date*/
271 
272NuvolaSpeedy(tx,ty)
273int tx, ty;
274   {
275    drive(ang=Trova(tx,ty),100);
276    while ((Dista(tx,ty)>5000)&&(speed()))
277         GreatSayian();
278    KameAmeA(49);
279   }
280 
281/*Individua l' angolazione necessaria per raggiungere un punto dato*/
282 
283Trova(mx,my)
284int mx, my;
285  {
286    return (180+((mx-=(loc_x()))>0)*180+atan(((my-loc_y())*100000)/mx));
287  }
288 
289/*Calcola la distanza rispetto ad un punto dato*/
290 
291Dista(nx,ny)
292int nx, ny;
293  {
294    return (((nx-=loc_x())*nx+(ny-=loc_y())*ny));
295  }
296 
297/*Valuta se un angolo e' libero*/
298 
299Go()
300  {                                           
301    OooHoo();
302    while (scan(Trova(dx,dy),10)>400)
303         OooHoo();
304    NuvolaSpeedy(dx,dy);
305    dan=damage();
306  }
307 
308/*Sceglie un nuovo angolo*/
309 
310OooHoo()                
311  {
312     park=dy;
313     dy=dx;
314     dx=1000-park;
315     ang2+=90;
316  }                      
317 
318/*Conta i superstiti*/
319 
320Reeft()            
321  {
322    dsiete=ang2+225;
323    qsiete=-1;               
324    while (dsiete<(ang2+360))
325         qsiete+=(scan(dsiete+=21,10)!=0);
326    return (qsiete);
327  }
328 
329/*Procedure di fuoco (spudoratamente copiate)*/
330 
331GreatSayian()
332{
333  if((orange=scan(ango,10))&&(orange<770))
334  {
335   if (range=scan(ango+353,4)) cannon(ango+=350,3*range-2*orange);
336   else if (range=scan(ango,4)) cannon(ango,3*range-2*orange);
337   else if (range=scan(ango+7,4)) cannon(ango+=10,3*range-2*orange);
338   }                                 
339  else
340    if((range=scan(ango-21,10))&&(range<800))
341      cannon(ango-=21,range);
342    else
343      if((range=scan(ango+21,10))&&(range<800))
344        cannon(ango+=21,range);
345      else
346        if((range=scan(ango-42,10))&&(range<900))
347          cannon(ango-=42,range);
348        else
349          if((range=scan(ango+42,10))&&(range<900))
350            cannon(ango+=42,range);
351          else
352            ango+=105;
353}                           
354 
355KameAmeA(vel)
356int vel;
357{
358  drive (ang,0);
359  while (speed()>vel)  
360       if ((range=scan(ango,10))&&(range<770)) cannon (ango,range);
361       else ango+=20;
362}
363  
364Sayian(muovi)
365int muovi;
366{                                  
367     if (!scan(ango,5))
368        if (!scan(ango-=11,5))
369           if (!scan(ango+=22,5))
370              if (!scan(ango-=33,5))
371                 if (!scan(ango+=44,5)) { ango+=40; return; }
372            
373     if (scan(ango,5)>770)
374     {
375      ango+=40;
376      return;
377     }
378 
379       ObaBa();
380       if (orange=scan((oang=ango),5))
381         {
382           ObaBa();
383           if (range=scan(ango,10))
384             cannon((ango+(ango-oang)*((1200+range)>>9)-(sin(ango-ang)>>14)*muovi),(range*160/(160+orange-range-(cos(ango-ang)>>12)*muovi)));
385         }
386}                                        
387 
388ObaBa()
389{
390       if(scan(ango-5,1)) ango-=5;
391       if(scan(ango+5,1)) ango+=5;
392       if(scan(ango-3,1)) ango-=3;
393       if(scan(ango+3,1)) ango+=3;
394       if(scan(ango-1,1)) ango-=1;
395       if(scan(ango+1,1)) ango+=1;
396}