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 |
029 | LA STORIA |
030 | ========= |
031 |
032 | Son-Goku un bel giorno decide di partecipare al grande torneo TenKaiChi. |
033 | Salta quindi sulla sua nuvoletta Speedy, regalo del vecchio Muten (il genio |
034 | delle tartarughe di mare), e va alla pugna. |
035 | Attacca i nemici con tre tipi di colpi : |
036 | il GreatSayian, (il piu' preciso), il Sayian (un compromesso tra precisione |
037 | e velocita') e l' onda KameAmeA (la piu' veloce, ma di scarsa precisione). |
038 |
039 | COMPORTAMENTO |
040 | ============= |
041 | La strategia di Goku e' abbastanza complicata. |
042 | Il crobot infatti puo' adottare diverse tattiche a seconda della posizione, |
043 | del tempo trascorso, dei danni subiti ed infine del caso. |
044 | La parte piu' difficile di tutto il lavoro e' stata la ricerca del giusto |
045 | equilibrio tra le varie parti di Goku. Quello attuale sembra funzionare |
046 | discretamente, ma e' ben lungi dall' essere quello ideale. |
047 |
048 | Fase Iniziale |
049 | ------------- |
050 | All' inizio del Match Goku cerca un angolo libero, cominciando da quello piu' |
051 | vicino, e (non troppo) prontamente lo raggiunge. |
052 | A 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 | |
063 | Le 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 |
071 | Goku e' un po' misantropo. |
072 | Se infatti si accorge di condividere il suo bell' angoletto con un altro |
073 | crobottino cambia posizione. |
074 |
075 | Movimento |
076 | --------- |
077 | La routine e' unica per tutte le posizioni dello schermo e per due dei tre |
078 | attacchi finali. |
079 | Calcola la distanza (al quadrato, evitando cosi' una radice) rispetto ad un |
080 | punto dato [(20,20)(980,20) (980,980)(20,980)], trova l' angolo necessario per |
081 | raggiungerlo e infine inizia a muoversi in quella direzione. Quando arriva a |
082 | destinazione si ferma. |
083 | Sceglie una direzione parallela ad uno dei lati e si avvia, camminando fino a |
084 | quando non si trova alla massima distanza stabilita dal punto. |
085 | Inverte quindi il movimento e riinizia dal principio. |
086 | Dopo un certo numero di cicli il movimento diventa prima una L e infine |
087 | perpendicolare a quello iniziale. |
088 | Parte quindi la routine di attacco finale. |
089 |
090 | Fase Finale |
091 | ----------- |
092 | Dopo 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 | |
115 | CONSIDERAZIONI |
116 | ============== |
117 | Il Crobot gia' si comporta male con gli avversari di quest' anno, figuriamoci |
118 | con quelli del prossimo torneo. |
119 | La routine di movimento e' molto generica e si puo' adattare a quasi ogni |
120 | schema di gioco. |
121 |
122 | Purtroppo il suo maggior pregio e' anche il suo limite principale. |
123 | Dalla sua ha infatti la compattezza del codice, che consente di dedicare molto |
124 | spazio alla parte offensiva del gioco. |
125 | Per contro pero', tale compattezza e' ottenuta a prezzo di una maggior lentezza: |
126 | il controllo della distanza dai bordi infatti richiede almeno 16 istruzioni, |
127 | contro le tre necessarie normalmente. |
128 | Questo rende il povero Goku molto piu' vulnerabile degli altri al fuoco nemico. |
129 | In una partita media di 100000 cicli si perde l' 11% del tempo per il controllo |
130 | della posizione, contro il 2% altrimenti necessario. |
131 | |
132 | Inoltre, poiche' Goku non ha (ovviamente) modo di sapere quanto e' forte |
133 | l' ultimo superstite, e poiche' renderlo in grado di riconoscere il tipo di |
134 | movimento del nemico avrebbe richiesto routine troppo ingombranti, il |
135 | mix delle varie tattiche disponibili e' stato stabilito empiricamente. |
136 | Dopo numerosi tentativi l' efficienza del frugoletto e' passata dal 17.8% al |
137 | 43.7% in un mini-torneo a 8 giocatori. Non e' pero' detto che risultato |
138 | ottenuto sia il migliore possibile. Anzi, nella peggiore delle ipotesi il |
139 | crobot potrebbe prendere in ogni occasione la decisione meno adatta. |
140 |
141 |
142 | Il programma e' abbastanza commentato, nel caso improbabile qualcuno si prendesse |
143 | il disturbo di leggerlo. |
144 | Per la spiegazione delle routine di fuoco rimando ai crobot citati, o ai loro |
145 | eventuali ispiratori. Io le ho prese come parti pre-fabbricate.... funzionano |
146 | e tanto mi basta. |
147 |
148 | RINGRAZIAMENTI |
149 | ============== |
150 |
151 | Un sentito grazie a Tom Poindexter (per averci donato Crobots) a Maurizio |
152 | 'JOSHUA' Camagni (per le sue indispensabili utilities) e a tutti coloro che, |
153 | con i loro robots, hanno reso possibile l' esistenza di Goku (...in qualche |
154 | caso, piu' che di semplice ispirazione, si e'trattato di un vero e proprio |
155 | furto). |
156 |
157 | Un enorme ringraziamento ad AKIRA TORIYAMA per aver creato DragonBall e |
158 | DragonBall Z. |
159 |
160 | */ |
161 |
162 | int timmax, max, min, ang, ang2, dx, dy, qsiete, dsiete; |
163 | int ncmplt, dan, xx, yy, park, ango, oang, range, orange; |
164 | int flag4, flag2, flag1, flag; |
165 |
166 | main() |
167 | { |
168 |
169 | /*Inizializzazione variabili*/ |
170 |
171 | min=10000; /*Distanza minima dalla destinazione*/ |
172 | max=90000; /*Ampiezza del movimento*/ |
173 | |
174 | ang2=(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 |
180 | Go(); |
181 | timmax=55+1400*(ncmplt=(dan<5)); /*Numero di cicli prima del movimento finale*/ |
182 |
183 | /*Restiamo fermi*/ |
184 |
185 | while (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 |
196 | flag4=timmax; /*Sceglie il tipo di movimento finale*/ |
197 |
198 | /*Ciclo principale*/ |
199 |
200 | while (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 |
233 | timmax=12; |
234 |
235 | if ((!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 |
272 | NuvolaSpeedy(tx,ty) |
273 | int 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 |
283 | Trova(mx,my) |
284 | int 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 |
291 | Dista(nx,ny) |
292 | int nx, ny; |
293 | { |
294 | return (((nx-=loc_x())*nx+(ny-=loc_y())*ny)); |
295 | } |
296 |
297 | /*Valuta se un angolo e' libero*/ |
298 |
299 | Go() |
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 |
310 | OooHoo() |
311 | { |
312 | park=dy; |
313 | dy=dx; |
314 | dx=1000-park; |
315 | ang2+=90; |
316 | } |
317 |
318 | /*Conta i superstiti*/ |
319 |
320 | Reeft() |
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 |
331 | GreatSayian() |
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 |
355 | KameAmeA(vel) |
356 | int 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 | |
364 | Sayian(muovi) |
365 | int 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 |
388 | ObaBa() |
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 | } |