1999/ka_aroth.r

001/*
002      KK    KK  AAAAAA  '''   AAAAAA   RRRRRR   OOOOOO  TTTTTTTT HH    HH
003      KK   KK  AAAAAAAA '''' AAAAAAAA RRRRRRRR OOOOOOOO TTTTTTTT HH    HH
004      KK  KK   AA    AA   '' AA    AA RR    RR OO    OO    TT    HH    HH
005      KK KK    AA    AA   '  AA    AA RR    RR OO    OO    TT    HH    HH
006      KKKK     AAAAAAAA      AAAAAAAA RRRRRRRR OO    OO    TT    HHHHHHHH
007      KK KK    AA    AA      AA    AA RR RR    OO    OO    TT    HH    HH
008      KK  KK   AA    AA      AA    AA RR  RR   OO    OO    TT    HH    HH
009      KK   KK  AA    AA      AA    AA RR   RR  OOOOOOOO    TT    HH    HH
010      KK    KK AA    AA      AA    AA RR    RR  OOOOOO     TT    HH    HH
011 
012   Nome        : Ka'aroth.r  (10-05-99)
013 
014   Provenienza : Pianeta Vegeta
015 
016   Razza       : Sayian
017 
018   Scopo       : Difendere la terra degli attacchi dei perfidi Sayian
019 
020   Autore      : Simone Ascheri
021 
022LA STORIA
023=========
024 
025Un brutto giorno gli alieni del pianeta Vegeta, i potentissimi Sayian, arrivano
026sulla Terra per sterminarne gli abitanti e vendere il pianeta al miglior
027offerente.
028Radish, Napa e Vegeta (praticamente e' come se l' imperatore del Giappone si
029chiamasse Giappone) sono quasi invincibili: l' unico che puo' fermarli e'
030Ka'aroth, anch' egli Sayian di nascita, ma terrestre d' adozione.
031Attacca i nemici con tre tipi di colpi :
032- Il SuperSayian:
033  Usato quando si e' a una certa distanza dai bordi, e' il piu' preciso, ma
034  anche il piu' lento. E' una routine di Diabolik.r (e di Tox prima) leggermente
035  modificata, con il blocco di Scan() mutuato da Coppi.r.
036- Il KaiOKen:
037  Compromesso tra precisione e velocita'. Usato in prossimita' dei bordi e
038  nei colpi ravvicinati e' derivato direttamente da Arale.r, robot di cui ho
039  grande stima.
040- L' onda KameAmeA:
041  E' la piu' veloce, ma di scarsa precisione. E' usata nei rallentamenti.
042 
043COMPORTAMENTO
044=============
045 
046La strategia di Ka'aroth e' abbastanza complicata.
047 
048Fase Iniziale
049-------------
050All' inizio del Match Ka'aroth cerca un angolo libero, cominciando da quello
051piu' vicino, e (non troppo) prontamente lo raggiunge.
052Inizia quindi a muoversi parallelamente ad un lato e a sparare.
053Ka'aroth e' un po' misantropo.
054Se infatti si accorge di condividere il suo bell' angoletto con un altro
055crobottino cambia posizione.
056 
057Fase Finale
058-----------
059Dopo circa 150000 cicli Ka'aroth conta gli avversari:
060 
061 1 * Se c' e' piu' di un superstite continua il movimento
062 
063     I  * Con moto a pendolo sulla diagonale, se i danni sono inferiori al
064          40%...
065     II * ...Altrimenti descrivendo dei mini-quadrati nel settore di appartenenza,
066          cambiando angolo ogni volta che i danni subiti sono ingenti.
067 
068 2 * Se invece si accorge di avere solo piu' un avversario Ka'aroth sceglie
069     una delle strategie seguenti:
070 
071   A * Se il movimento precedente era sulla bisettrice e i danni inferiori al
072       60%, inizia a scorrazzare lungo la diagonale, cambiando angolo ogni volta
073       che quello base e' occupato.
074   B * Altrimenti adotta un movimento a rombo con vertici nei punti medi dei
075       lati dell' arena, alternato con movimento a clessidra inclinata con
076       vertici negli stessi punti.
077 
078 3 * In tutti i casi, se ha subito piu' del 78% di danni, Ka'aroth lascia
079     perdere cio' che stava facendo, cerca un angolo libero e ivi si ferma,
080     adottando questo comportamento:
081 
082   1 * Se scopre che c' e' un solo superstite nell' arena, rimbalza di angolo
083       libero in angolo libero per cercare di distruggerlo...
084   2 * ...Altrimenti si ferma in un cantuccio sparando ai cattivi con la massima
085       precisione di cui e' capace e muovendosi solo quando viene colpito.
086 
087     Teoricamente questa tattica dovrebbe aiutarlo a pareggiare l' incontro
088     (Son-Goku.r non ci riusciva quasi mai), ma non so fino a che punto sia
089     efficace.
090 
091Routine di Movimento
092--------------------
093La routine e' unica per tutte le posizioni dello schermo e per tre dei quattro
094attacchi finali.
095Calcola la distanza (al quadrato, evitando cosi' una radice) rispetto ad un
096punto dato [(20,20)(980,20)(980,980)(20,980)], trova l' angolo necessario per
097raggiungerlo e infine inizia a muoversi in quella direzione. Quando arriva a
098destinazione si ferma.
099Sceglie una direzione parallela ad uno dei lati (controllando dove si trova il
100nemico) e si avvia, camminando fino a quando non si trova alla massima
101distanza stabilita dal punto.
102Inverte quindi il movimento e riinizia dal principio.
103 
104CONSIDERAZIONI
105==============
106 
107Il programma e' abbastanza commentato, nel caso improbabile qualcuno si
108prendesse il disturbo di leggerlo.
109Sono partito dalla struttura di base di Son-Goku.r, di cui Ka'aroth.r e'
110(teoricamente) un' evoluzione, ma nel corso del lavoro ho modificato radicalmente
111ogni punto. Infatti alcune procedure sono state riscritte completamente ed altre
112ulteriormente ottimizzate. In piu' e' differente il mix delle varie tattiche e la
113modalita' di scelta della direzione. Ho aggiunto inoltre un' oscillazione in
114diagonale e sostituito l' inefficiente !-like con una Kill!-like. Ho inserito infine
115una routine difensiva auspicabilmente migliore della precedente, mentre ho eliminato
116la fase iniziale di 'studio' degli avversari.
117Per la spiegazione delle routine di fuoco rimando ai crobot citati, o ai loro
118eventuali ispiratori.
119In ogni caso ora Ka'aroth utilizza il piu' possibile la Tox-like, relegando le altre
120due a compiti marginali.
121 
122RINGRAZIAMENTI
123==============
124 
125Un sentito grazie a:
126- Tom Poindexter (per averci donato Crobots)
127- Maurizio 'JOSHUA' Camangi per:
128   * le sue indispensabili utilities
129   * la pazienza dimostrata nel 'guidarmi' alla scoperta di Linux
130   * le tonnellate di e-mail che ci siamo scambiati
131- Michelangelo Messina per aver gentilmente assecondato tutte le mie richieste di
132  modifica alle sue utilities e aver trovato i bugs delle mie
133- Tutti coloro con i quali ho scambiato pareri in questi mesi
134 
135Un enorme ringraziamento ad AKIRA TORIYAMA per aver creato DragonBall e
136DragonBall Z.
137 
138*/
139 
140int timmax, max, min, ang, ang2, dx, dy;
141int dan, park, ango, oang, range, orange;
142int quad, flag3, flag2, flag1, flag;
143 
144main()                           
145{
146ang2=(Trova((dy=980-(loc_x(min=8500)>(flag2=500))*960),
147     (1000-(dx=(loc_y(max=70000)>500)*960+20)))/90*90);
148 
149Go(timmax=80);                                        /*Trova un angolo libero e lo raggiunge*/
150 
151while (timmax+=6)                                     /*Inizia il ciclo principale*/
152   {
153    while ((--timmax)&&(damage()<79))                 /*Movimento oscillatorio*/
154       {
155         if (!(flag%=630))                            /*Se il movimento non e' diagonale...*/
156           if (Ricerca(ang2))                         /*...sceglie la direzione in base alla posizione del nemico*/
157             flag=630;
158         drive (ang=(ang2+flag)%360,100);             /*Si allontana dall' origine*/
159         while ((Dista(dx,dy)<max)&&(speed()))        /*Finche' non e' troppo lontano spara*/
160              SuperSayian(1,1,0);
161 
162         KameAmeA();                                  /*Rallenta*/
163 
164         if (Ricerca(ang+=180))                       /*Controlla se ha un nemico alle spalle:*/
165           Go();                                      /*e cambia angolo..*/
166         else Arrivo(dx,dy,min);                      /*..altrimenti torna all' origine*/
167        }
168 
169/*Comportamenti dopo i primi 100000 cicli o dopo il 78% di danni */
170 
171if (damage(flag1=(Reeft(ang2+205,5)))>78)             /*Gioca in difesa*/
172  {
173    while(Go())                                       /*Cambia di angolo, fermandoti un po' se c'e' piu' di un superstite*/
174         while((dan==damage())&&(flag1))              /*Fai il finto Tox*/
175              SuperSayian(0,0,0);
176  }
177else if (!flag1)                                      /*Controlla quanti sono i sopravvissuti*/
178       {
179         if ((flag==315)&&(damage()<60))              /*Se il movimento era sulla bisettrice allora l' attacco finale e' diagonale*/
180           max=1350000;                               /*Nuova ampiezza dell' oscillazione*/
181         else
182         {
183         while (NuvolaSpeedy(500,60))                 /*Attacco finale romboidale*/
184              {
185                NuvolaSpeedy(flag2,flag2=1440-flag2);
186                NuvolaSpeedy(flag2,1440-flag2);
187                NuvolaSpeedy(60,500);
188              }
189         }
190      }
191   else
192      {
193        if (damage(min=15000)<40)                     /*Pendolo sulla bisettrice: Gundam-like*/
194           {
195             flag=315;
196           }
197        else
198            {
199              while (((dan=damage())<79)&&(Reeft((ang=ang2)+205,5)))             /*Quadrato nell' angolo*/
200                   {
201                     while ((++quad)%5)
202                          {
203                            Arrivo(dx+=26000000/cos(ang),dy+=26000000/sin(ang),8000); /*Calcola di volta in volta le nuve coordinate*/
204                            ang+=270;
205                          }
206                     if (dan<damage()+(timmax=-5)) Go();                         /*Decide se muoversi in un altro angolo*/
207                   }
208            }
209       }
210   }
211}
212 
213/*Operazioni di servizio*/
214 
215/*Routine di spostamento verso coordinate date*/
216 
217NuvolaSpeedy(tx,ty)
218int tx, ty;
219   {
220    Trova(tx,ty);                                     /*Cerca la direzione in cui muoversi*/
221    return Arrivo(tx,ty,6800);
222   }
223 
224/*Vai alla distanza minima dal punto*/
225 
226Arrivo(fx,fy,m)
227int fx, fy, m, h;
228   {
229     drive (ang,100);
230     while (((h=Dista(fx,fy))>m)&&(speed()))
231          SuperSayian(1,0,h<25000);
232     return KameAmeA();
233   }
234 
235/*Individua l' angolazione necessaria per raggiungere le coordinate (mx,my)*/
236 
237Trova(mx,my)
238int mx, my;
239  {
240    return (ang=(360+((mx-=loc_x())<0)*180+atan(((my-loc_y())*100000)/mx)));
241  }
242 
243/*Calcola la distanza rispetto ad un punto dato: si lascia il quadrato per risparmiare tempo*/
244 
245Dista(nx,ny)
246int nx, ny;
247  {
248    return (((nx-=loc_x())*nx+(ny-=loc_y())*ny));
249  }
250 
251/*Valuta se un angolo e' libero*/
252 
253Go()
254  {
255    while (Ricerca(Trova(OooHoo(ang2+=90),dy=park))>400);
256    return(dan=damage(NuvolaSpeedy(dx,dy)));
257  }
258 
259/*Effettua la rotazione degli angoli da controllare*/
260 
261OooHoo()
262  {
263     park=dx;
264     return(dx=(1000-dy));
265  }
266 
267/*Scan allargato a 40 gradi: non cade nel bug di scansione*/
268 
269Ricerca(an)
270int an;
271{
272 return (scan(an+350,10))+(scan(an+10,10));
273}
274 
275/*Conta i superstiti*/
276 
277Reeft(dsiete,dand)
278int dsiete, dand, qsiete;
279  {
280    while (--dand)
281         qsiete+=(Ricerca(dsiete+=40)!=0);
282    return (qsiete>1);
283  }
284 
285/*Procedure di fuoco (spudoratamente copiate)*/
286 
287/*Spara con media precisione*/
288 
289KaiOKen()
290{
291  if((orange=scan(ango,10))&&(orange<770))
292  {
293   if (range=scan(ango+353,4))
294     cannon(ango+=350,3*range-2*orange);
295   else if (range=scan(ango,3))
296          cannon(ango,3*range-2*orange);
297   else if (range=scan(ango+7,4))
298          cannon(ango+=10,3*range-2*orange);
299   }
300  else
301    if((range=scan(ango+=339,10))&&(range<700))
302      cannon(ango,range);
303    else
304      if((range=scan(ango+=42,10))&&(range<700))
305        cannon(ango,range);
306      else
307        if((range=scan(ango+=297,10)))
308          cannon(ango,range);
309        else
310          if((range=scan(ango+=84,10)))
311            cannon(ango,range);
312          else
313            return (ango+=40);
314}
315 
316/*Spara mentre decelera*/
317 
318KameAmeA()
319   {
320     drive(ang,0);
321     while (speed()>49)
322          if ((range=scan(ango,10))&&(range<770))
323            cannon (ango,range);
324          else
325            Ceck();
326   }
327 
328/*Se non ha trovato avversari nella direzione originaria li cerca intorno e nella direzione in cui si sta muovendo*/
329 
330Ceck()
331   {
332          if (range=scan(ango+=340,10));
333          else if (range=scan(ango+=40,10));
334          else if (range=scan(ang,10))
335                 ango=ang;
336          else
337             return (ango+=40);
338          return cannon(ango,2*scan(ango,10)-range);
339    }
340 
341/*Spara con buona precisione sia da fermo che in movimento*/
342 
343SuperSayian(muovi,sposta,no)
344int muovi, sposta, no;
345{
346    if (orange=scan(ango,10))
347      {
348        if ((((orange<400)||(orange>700))&&(sposta))||(no))
349          return KaiOKen();
350        else
351        {
352        if (scan(ango-=5,5));else ango+=10;
353        ObaBa();
354        if (orange=scan(oang=ango,5))
355          {
356            ObaBa();
357            if (range=scan(ango,10))
358              return cannon((ango+(ango-oang)*((980+range)>>9)-(sin(ango-ang)>>14)*muovi),(range*200/(200+orange-range-(cos(ango-ang)>>12)*muovi)));
359          }
360        else
361          return KaiOKen();
362        }
363      }
364    else
365      return Ceck();
366}
367 
368/*Questo viene da Coppi.r*/
369 
370ObaBa()
371{
372  if(scan(ango+354,1)) ango+=354;
373  if(scan(ango+6,  1)) ango+=6;
374  if(scan(ango+356,1)) ango+=356;
375  if(scan(ango+4,  1)) ango+=4;
376  if(scan(ango+358,1)) ango+=358;
377  if(scan(ango+2,  1)) ango+=2;
378}