2003/druzil.r

001/****************************************************************************/
002/*                                                                          */
003/*  Torneo di CRobots di IoProgrammo (2003)                                 */
004/*                                                                          */
005/*  CROBOT: Druzil.r                                                        */
006/*                                                                          */
007/*  CATEGORIA: 2000 istruzioni                                              */
008/*                                                                          */
009/*  AUTORE: Daniele Nuzzo                                                   */
010/*                                                                          */
011/****************************************************************************/
012 
013/*
014 
015SCHEDA TECNICA:
016   
017  Le differenze rispetto a Elminster sono la FASE 3 e quindi anche il f2f e una
018  FASE 1 un po' piu' lunga.
019  Inizialmente il robot calcola alcuni parametri e si reca velocemente nell'angolo
020  piu' vicino (FASE 0).
021   
022  Quindi esegue in sequenza 3 strategie di gioco distinte (se il combattimento e'
023  un f2f passa direttamente all'ultima fase di gioco).
024   
025 
026FASE 1: 
027   
028  La FASE 1 di gioco prevede un comportamento estremamente cauto e difensivo.
029   
030  Il movimento nell'angolo ricorda quello di Drizzt e si basa su oscillazioni
031  brevi verso i due angoli adiacenti rimanendo in prossimita' dei bordi
032  dell'arena.
033  Ci sono tuttavia notevoli differenze rispetto ai robottini dello scorso anno:
034   
035    1) Le oscillazioni non sono alternate verso i due angoli adiacenti, ma sono
036       determinate in ogni oscillazione da una scelta ben precisa: la direzione
037       e' quella dell'avversario piu' distante. L'idea e' quella di far variare
038       il piu' possibile l'angolo di scansione dell'avversario piu' vicino e di
039       allontanarsi risultando un bersaglio difficile da trovare. 
040    2) Nell'avvicinamento verso l'avversario piu' distante il robot non si ferma
041       sempre in prossimita' dell'angolo iniziale: se l'avversario piu' distante
042       e' molto lontano il robot si avvicina fino a una "distanza di sicurezza"
043       da cui decide se sparare contro l'altro robot che era piu' vicino e da cui
044       si e' allontanato oppure se creare un fuoco di sbarramento verso il robot
045       verso cui si e' avvicinato nel caso in cui risulti l'avversario piu' vicino.   
046    3) In questa fase non si perde piu' tempo a contare gli avversari, ma si
047       utilizzano criteri differenti per decidere se passare alla fase successiva.
048     
049  Controlli per decidere se passare alla fase successiva:
050   
051    1) Dopo 260 oscillazioni si passa comunque alla fase 2;
052    2) Se prima delle 140 oscillazioni subisce un certo danno (70%) allora cambia
053       subito tattica, perche' probabilmente la difesa non paga;
054    3) Da 140 oscillazioni in poi, se non vede avversari nell'angolo opposto allora
055       passa alla seconda fase poiche' immagina che sicuramente c'e' un avversario
056       in meno e almeno un secondo e' in difficolta';
057    4) Se in uno degli angoli adiacenti non trova un avversario controlla nell'altro
058       angolo adiacente e se non c'e' un avversario neanche li o se si e' allontanato
059       dall'angolo per recarsi in quello opposto allora passa alla fase 2.
060        
061  La routine di fuoco utilizzata in questa fase di gioco non esegue correzioni sulla
062  distanza poiche' si adatta al movimento del robot che tende ad allontanarsi o a
063  mantenere una distanza di sicurezza dagli avversari. Le correzioni sull'angolo
064  sono determinate invece da scansioni con risoluzione limitata in quanto gli
065  avversari probabilmente sono ben distanti e quindi l'angolo non deve variare molto.
066         
067FASE 2: 
068   
069  La FASE 2 di gioco prevede un comportamento estremamente offensivo dall'angolo e
070  contemporaneamente dinamico in quanto prevede cambi di angolo.
071   
072  Il robot controlla i due angoli adiacenti: se trova un avversario lo attacca finche'
073  non subisce danni altrimenti prova a cambiare angolo.
074  L'attacco dall'angolo e' effettuato tramite un triangolo (dopo i quadrati di Fizban e
075  i rettangoli di Zorn non potevano mancare i triangoli) molto allungato in direzione
076  dell'avversario e schiacciato lungo il bordo dell'arena. L'idea e' quella di
077  allontanarsi eventualmente da un secondo avversario, provare ad avvicinarsi il piu'
078  possibile verso il bersaglio, eludere le routine di fuoco cambiando una volta la
079  direzione in avvicinamento e riallontanarsi a massima velocita'. Vengono registrati
080  inoltre i danni subiti durante l'attacco preferendo la direzione in cui si subiscono
081  meno danni.
082  Il cambio di angolo viene effettuato solo dopo alcuni controlli ridondanti e piu'
083  accurati verso il quadrante di destinazione.
084  Dopo il cambio dell'angolo il robot aspetta un certo numero di iterazioni (che variano
085  in base al tempo gia' trascorso e ai danni subiti) prima di riproporre l'attacco a
086  triangolo. Durante i cambi di angolo si controlla anche che non sia rimasto un unico
087  avversario; in tal caso, a meno di non aver subito danni notevoli (90%), si passa alla
088  fase 3.   
089   
090  Durante l'attacco a triangolo il robot fissa la direzione di fuoco sull'avversario e
091  la routine di fuoco non perde mai il bersaglio, invece durante i cambi d'angolo la
092  routine di fuoco cambia bersaglio quando quello puntato diventa troppo distante.
093   
094  La routine di attacco a triangolo si e' dimostrata molto efficace soprattutto con
095  i robot piu' recenti, ma soffre i robot che attendono molto nell'angolo e che utilizzano
096  le toxiche (spero che quest'anno siano veramente pochi!); in particolare volevo fare i
097  complimenti ad Andrea Creola che con il suo Pippo2a vera bestia nera nei test dello scorso
098  anno insieme a Stanlio: senza questi due nei test Elminster ottiene il 76,5% e Druzil il
099  79%! Di sicuro almeno pippo3 quest'anno sara' molto ostico per i miei robottini, quindi
100  nonostante i report ottimi da 2k1 in avanti, di punti deboli ce ne sono e la competizione
101  sara' durissima come sempre.
102   
103 
104FASE 3:
105   
106  La routine offensiva della fase 3 e' molto semplice: fino al 50% di danno esegue un
107  quadrato minimo al centro dell'arena, dopo il 50% di danni il quadrato si allarga
108  di 200 unita' in tutte le direzioni e l'oscillazione e' quindi molto lunga.
109     
110  Questa routine rende un po' meno nei test del 2k2, ma credo che sia piu' adatta
111  per il nuovo torneo soprattutto come FASE 3 del 4vs4.
112   
113  Soffre le toxiche ovviamente!
114 
115ROUTINE DI FUOCO:
116 
117  La routine di fuoco e' derivata da un mix di quelle dello scorso anno con quelle
118  di Zorn e Rudolf di Alessandro Carlin.
119   
120    1) La temporizzazione non � ottimale come lo scorso anno, ma in compenso la
121       precisione � migliorata grazie al puntamento primario delle routine di Ale
122       che ho modificato lievemente per renderle piu' veloci nell'esecuzione e
123       piu' precise nella prima correzione dell'angolo (ho aumentato a 10 la
124       risoluzione del primo scan).
125    2) Il puntamento secondario rimane ampio (10) anche nelle correzioni dell'angolo
126       seguendo in maniera efficiente anche i nemici vicini.
127    3) In un'unica chiamata (Fire) vengono scansionati 160 gradi e non piu' 180, per creare
128       una piccola intersezione dell'area di scansione tra 2 chiamate successive.
129    4) Nel f2f non viene mai perso il nemico puntato, nel 4vs4 invece la scelta del cambio
130       del bersaglio in caso di distanza eccessiva e' determinata dalla variabile chdeg.
131 
132 
133RINGRAZIAMENTI:
134 
135Un ringraziamento a tutti i "veterani" che continuano ad alimentare con i loro
136robot, le loro utilities e soprattutto con la loro passione questo gioco meraviglioso:
137in particolare a Simone Ascheri, Michelangelo Messina, Alessandro Carlin, Maurizio
138Camangi e Andrea Creola che sono anche sempre presenti nella ML e che costituiscono di
139fatto lo "sponsor umano" di Crobots.
140Un grazie anche alle nuove "matricole", che quest'anno hanno contribuito a stabilire un
141nuovo record di affluenza al torneo, e che spero continuino a partecipare ai prossimi
142tornei e soprattutto si divertano.
143 
144In bocca al lupo a tutti e buon torneo 2k3!
145 
146*/
147 
148 
149/*********************/
150/* Variabili globali */
151/*********************/
152 
153int deg,rng,dir,odeg,orng,dam,t;
154int xs,ys,en,xd,yd,zd,xmd,ymd,ez;
155int timer,dmin,dmax,xdam,ydam,xyl,xyh,xyel,xyeh,chdeg,dd,dd2,tx;
156 
157 
158/****************************************/
159/* Routines di movimento e di scansione */
160/****************************************/
161 
162 
163Up(d) { while(loc_y()<d) Fire(drive(90,100));  drive(90,0);  }
164Dw(d) { while(loc_y()>d) Fire(drive(270,100)); drive(270,0); }
165Dx(d) { while(loc_x()<d) Fire(drive(0,100));   drive(0,0);   }
166Sx(d) { while(loc_x()>d) Fire(drive(180,100)); drive(180,0); }
167 
168Ymin(d1,d2) {while(loc_y()<d1) Fire(drive(d2,100)); drive(d2,0); }
169Ymax(d1,d2) {while(loc_y()>d1) Fire(drive(d2,100)); drive(d2,0); }
170Xmin(d1,d2) {while(loc_x()<d1) Fire(drive(d2,100)); drive(d2,0); }
171Xmax(d1,d2) {while(loc_x()>d1) Fire(drive(d2,100)); drive(d2,0); }
172 
173Look(d) { return (scan(d-10,10)+scan(d+10,10)); }
174 
175 
176/**********************/
177/* ROUTINE PRINCIPALE */
178/**********************/
179 
180 
181main()
182{
183 
184/****************************************************/
185/* FASE 0: Calcolo parametri e ritirata nell'angolo */
186/****************************************************/
187 
188  chdeg=1; 
189 
190  if (xs=loc_x()>499) Dx(900); else Sx(100);
191  if (ys=loc_y()>499) Up(880); else Dw(120);
192   
193  Params();
194   
195  xyl=95; xyh=905; xyel=55; xyeh=945; chdeg=0; t=40;
196   
197  Radar();
198   
199/******************************/
200/* FASE 1: Difesa nell'angolo */
201/******************************/
202 
203  if (en>1) {
204    while (++timer<260) {
205      if (tx) {
206      
207      if (xs) {
208        Run(180); while (loc_x()>950) LookX(); Stop(180);
209        Run(0);   while (loc_x()<955) ; Stop(0);
210      } else {
211        Run(0);   while (loc_x()<50) LookX(); Stop(0);
212        Run(180); while (loc_x()>45)  ; Stop(180);
213      }
214       
215      } else {
216       
217      if (ys) {
218        Run(270); while (loc_y()>950) LookY(); Stop(270);
219        Run(90);  while (loc_y()<955) ; Stop(90);
220      } else {
221        Run(90);  while (loc_y()<50) LookY(); Stop(90);
222        Run(270); while (loc_y()>45) ;  Stop(270);
223      }
224       
225      }
226    }
227    if (damage()<40) t=25;
228    if (timer<300) t-=20;
229  }
230     
231  if (en>1) Radar();
232     
233/***********************************************/
234/* FASE 2: Attacco dall'angolo e cambio angolo */
235/***********************************************/
236 
237  while(en>1) {
238    while (scan(xd,10) && (xdam<3)) {
239      deg=xd;
240      dam=damage();
241      if (xs) {
242        if (ys) { Ymax(845,210); Ymin(945,150); } else { Ymin(155,150); Ymax(55,210); }
243        Dx(900);
244      } else {
245        if (ys) { Ymax(845,330); Ymin(945,30); } else { Ymin(155,30); Ymax(55,330); }
246        Sx(100);
247      }
248      xdam=damage()-dam;
249    }
250    if ((ydam-=3)<0) ydam=0;
251    if (!Look(xd)) {
252      chdeg=1; 
253      if (xs=!xs) { Dx(300); if (!Look(xmd)) Dx(900); else { deg=xmd; Sx(100); xs=!xs; chdeg=0; } } else { Sx(700); if (!Look(xmd)) Sx(100);  else { deg=xmd; Dx(900); xs=!xs;  chdeg=0; } }
254      --t;
255      if (chdeg) {
256        Params();
257        if (!Look(yd)) Radar();
258        chdeg=0;
259        if ((t>1)) ydam=5;
260      }
261      xdam=0;
262    }
263 
264    
265    while (scan(yd,10) && (ydam<3)) {
266      deg=yd;
267      dam=damage();
268      if (ys) {
269        if (xs) { Xmax(845,240); Xmin(945,300); } else { Xmin(155,300); Xmax(55,240); }
270        Up(900);
271      } else {
272        if (xs) { Xmax(845,120); Xmin(945,60); } else { Xmin(155,60); Xmax(55,120); }
273        Dw(100); 
274      }
275      ydam=damage()-dam;
276    }
277    if ((xdam-=3)<0) xdam=0;
278    if (!Look(yd)) {
279      chdeg=1; 
280      if (ys=!ys) { Up(300); if (!Look(ymd)) Up(900);  else { deg=ymd; Dw(100); ys=!ys; chdeg=0; } } else { Dw(700); if (!Look(ymd)) Dw(100);  else { deg=ymd; Up(900); ys=!ys; chdeg=0; } }
281      --t;
282      if (chdeg) {
283        Params();
284        if (!Look(xd)) Radar();
285        chdeg=0;   
286        if ((t>1)) xdam=5;
287      }
288      ydam=0;
289    }
290      
291  }
292/****************************************/
293/* FASE 3: Attacco al centro dell'arena */
294/****************************************/
295 
296  chdeg=0; 
297  
298  while(damage()<50) {
299      while (loc_x()<500) Fire(drive(0,100));
300      Fire(drive(90,0)); 
301      while (loc_y()<500) Fire(drive(90,100));
302      Fire(drive(180,0));
303      while (loc_x()>499) Fire(drive(180,100));
304      Fire(drive(270,0));    
305      while (loc_y()>499) Fire(drive(270,100));
306      Fire(drive(0,0)); 
307  }
308 
309 while(1) {
310      while (loc_x()<700) Fire(drive(0,100));
311      Fire(drive(90,0)); 
312      while (loc_y()<700) Fire(drive(90,100));
313      Fire(drive(180,0));
314      while (loc_x()>300) Fire(drive(180,100));
315      Fire(drive(270,0));    
316      while (loc_y()>300) Fire(drive(270,100));
317      Fire(drive(0,0)); 
318  }
319 
320}
321 
322 
323/*******************************/
324/* Routine di fuoco principale */
325/*******************************/
326 
327Fire()
328{
329  if (chdeg) if (rng>880) { rng=700; return deg+=120; }
330  if (rng=scan(odeg=deg,10))
331  {   
332    if (scan(deg-13,10))  { if (scan(deg-=5,2)) ; else deg-=4; return(cannon(deg+(deg-odeg),2*scan(deg,10)-rng)); }
333    if (scan(deg+13,10))  { if (scan(deg+=5,2)) ; else deg+=4; return(cannon(deg+(deg-odeg),2*scan(deg,10)-rng)); }
334    if (scan(deg,10))     { if (scan(deg-=2,2)) ; else deg+=4; return(cannon(deg+(deg-odeg),2*scan(deg,10)-rng)); }
335     
336  } else {
337   
338    if (rng=scan(deg+=340,10)) return cannon(deg,rng);
339    if (rng=scan(deg+=40,10))  return cannon(deg,rng);
340    if (rng=scan(deg+=300,10)) return cannon(deg,rng);
341    if (rng=scan(deg+=80,10))  return cannon(deg,rng);
342    if (rng=scan(deg+=260,10)) return cannon(deg,rng);
343    if (rng=scan(deg+=120,10)) return cannon(deg,rng);
344    if (rng=scan(deg+=220,10)) return cannon(deg,rng);
345   
346    deg+=230;
347   
348  }
349}
350 
351 
352/**********************************/
353/* Routine di conteggio avversari */
354/**********************************/
355 
356Radar()
357{
358  if (damage()>90) return (en=3);
359  en=0;
360  while (dmin<=dmax) en+=(scan(dmin+=20,10)>0);
361  dmin=zd-60;
362}
363 
364/*********************************************/
365/* Routine per calcolo parametri dell'angolo */
366/*********************************************/
367 
368Params()
369{
370  xd=180*xs;
371  dmax=(dmin=(zd=(yd=90+180*ys)-45+90*(xs^ys))-60)+100;
372  if (xs) {
373    if (ys) { xmd=210; ymd=240; } else { xmd=150; ymd=120; }
374  } else {
375    if (ys) { xmd=330; ymd=300; } else { xmd=30; ymd=60; }
376  }
377}
378 
379/*********************************/
380/* Routines utilizzate in FASE 1 */
381/*********************************/
382 
383LookX()
384{
385  LookZ(deg=yd);
386  if (dd=scan(xd,10)) {
387    if ((dd<(dd2=scan(yd,10))) || (!dd2)) { deg=xd; tx=!tx; }
388  } else LookAgain(xd,xmd);
389}
390 
391LookY()
392{
393  LookZ(deg=xd);
394  if (dd=scan(yd,10)) {
395    if ((dd<(dd2=scan(xd,10))) || (!dd2)) { deg=yd; tx=!tx; } 
396  } else LookAgain(yd,ymd);
397}
398 
399LookZ()
400{
401  if (timer>140) { if (!Look(zd)) timer=10000; } else if (damage()>70) timer=10000;  
402}
403 
404LookAgain(d1,d2) { if (!Look(d1) && !scan(d2,10)) timer=10000; }
405 
406Run(d)
407{
408  drive(d,100);
409  while(speed()<70) drive(d,100);  
410}
411 
412Stop(d)
413{
414  if (d==deg) while (scan(d,10)>840) ;
415  drive(d,0);
416 
417  if (!((rng=scan(odeg=deg,10)) && rng<880))
418    if (!(rng=scan(deg+=340,10)))
419      if (!(rng=scan(deg+=40,10))) { while(speed()>59) drive(d,0); return; }
420     
421     
422  if (scan(deg+10,10)) deg+=3; else deg+=357;
423  if (scan(deg+350,10)) deg+=358; else deg+=2;
424  if (scan(deg+10,10)) deg+=1; else deg+=359;
425     
426  cannon(deg,rng);
427     
428  while(speed()>59) drive(d,0);    
429}