{ *************************************************************************** * Estratégia para o compilador oficial da FIRA para a categoria MiroSot * * Medium League ("5" contra "3"). * * Elaborada por Marcelo Gomes em 11.08.2004 * * Escola de Engenharia Mauá - Instituto Mauá de Tecnologia * * Alterado por João Carlos G. Conde Filho 04.09.2005 * ***************************************************************************} Library Team1; Uses SysUtils, Classes, Types, Math, Forms, Dialogs, DateUtils, //Milisecondbetween, pra calcular o tempo Simulador in 'Simulador.pas', Unit1 in 'Unit1.pas' {Form2}; //Declarações utilizadas pelo simulador //const //t=0.5; {$R *.res} var //Variável que indica posição destino aux:Trobot; //Variável de estratégia aleatória temp:array [0..10] of integer; boo1,boo2:boolean; bolax_ant:double; bolay_ant:double; bola_ant:Tball; bola_prev:Tball; Cont:integer; //time:TDatetime; procedure Transmissao(var robot:TRobot;angd:double); const vmax = 120; var ango,dif:double; vl,vr:double; begin ango:=robot.rotation; dif:=angd-ango; while dif>180 do dif:=dif-360; // Form1.Label2.Caption:=FloatToStrF(dif,ffFixed,5,2); if ABS(dif)<90 then begin If dif > 0 then begin //Sentido Horário vl:=vmax-abs(dif)*vmax/90; vr:=vmax; // Form1.Label1.Caption:='1'; end else begin //Sentido Anti-Horário vl:=vmax; vr:=vmax-abs(dif)*vmax/90; // Form1.Label1.Caption:='2'; end; end else begin If dif > 0 then begin //Sentido Horário vl:=-vmax+(180-abs(dif))*vmax/90; vr:=-vmax; // Form1.Label1.Caption:='3'; end else begin //Sentido Anti-Horário vl:=-vmax; vr:=-vmax+(180-abs(dif))*vmax/90; // Form1.Label1.Caption:='4'; end; end; robot.velocityLeft:=Round(vl); robot.velocityRight:=Round(vr); end; procedure Position(var robot:TRobot;x,y:Double); var desired_angle:integer; dx, dy:Double; begin dx:=x - robot.pos.x; dy:=y - robot.pos.y; if dx = 0 then desired_angle:=90 else desired_angle:=round(180 / PI * ArcTan2(dy,dx)); desired_angle:=(desired_angle+720) mod 360; Transmissao(robot,desired_angle); end; Function Posiciona(var robot:Trobot;var env:TEnvironment;x,y,prec:double):boolean; begin if ((robot.pos.xx-prec))and ((robot.pos.yy-prec)) then begin robot.velocityLeft:=0; robot.velocityRight:=0; posiciona:=true; end //Posiciona no destino else Begin Position(robot,x,y); posiciona:=false; End; end; procedure Sai_do_canto(var env:Tenvironment;robot:Trobot); Begin if (robot.pos.y>72) then Begin Cont:=Cont+1; if (Cont>25)then Begin Cont:=0; robot.rotation:=robot.rotation+170; Posiciona(robot,env,robot.pos.x,71,1); End; End; if (robot.pos.y<8) then Begin Cont:=Cont+1; if (Cont>25)then Begin Cont:=0; robot.rotation:=robot.rotation-170; Posiciona(robot,env,robot.pos.x,9,1); End; End; if (robot.pos.x>90)then Begin Posiciona(robot,env,50,50,1); End; if (robot.pos.x<9)then Begin Cont:=Cont+1; if (Cont>25)then Begin Cont:=0; robot.rotation:=robot.rotation+170; Posiciona(robot,env,10,robot.pos.y,1); End; End; End; //Gira para o angulo escolhido procedure Gira(var robot:Trobot;var env:TEnvironment;Angulo:double); Begin //Converte angulo para "positivo" if (robot.rotation < 0.001) then robot.rotation:=robot.rotation+360; //Converte angulo para faixa de 0..360º if (robot.rotation > 360.001) then robot.rotation:=robot.rotation-360; //Rotaciona para chegar ao angulo if (robot.rotation > (Angulo+0.5)) then robot.velocityLeft:=robot.velocityLeft+abs(robot.rotation-Angulo) else if (robot.rotation < (Angulo-0.5)) then robot.velocityRight:=robot.velocityRight+abs(robot.rotation-Angulo); End; //Gira no eixo até chegar no angulo escolhido procedure Angulo_Destino(var robot:Trobot;var env:TEnvironment;Angulo:double); Begin //Converte angulo escolhido para "positivo" if (Angulo < 0.001) then Angulo:=Angulo+360; //Converte angulo escolhido para faixa de 0..360º if (Angulo > 360.001) then Angulo:=Angulo-360; //Converte angulo do robo para "positivo" if (robot.rotation < 0.001) then robot.rotation:=robot.rotation+360; //Converte angulo do robo para faixa de 0..360º if (robot.rotation > 360.001) then robot.rotation:=robot.rotation-360; //Se chegar no angulo pára if (robot.rotation>Angulo-1)and(robot.rotation (Angulo+1)) then begin robot.velocityLeft:=10; robot.velocityRight:=-10; end else begin if (robot.rotation < (Angulo-1)) then Begin robot.velocityLeft:=-10; robot.velocityRight:=10; End; end; End; End; //Calcula distância entre dois pontos function distancia(P1,P2:TVector3D):real; begin distancia:=sqrt(sqr(P2.X-P1.X)+sqr(P2.Y-P1.Y)); end; procedure Previsao_Bola(coef:double; var env:TEnvironment); begin if (bolax_ant<>env.currentBall.pos.x)or(bolay_ant<>env.currentBall.pos.y)then Begin bola_ant.pos.x:=bolax_ant; bola_ant.pos.y:=bolay_ant; bolax_ant:=env.currentBall.pos.x; bolay_ant:=env.currentBall.pos.y; //time:=now; End; if (bola_ant.pos.x<>env.currentBall.pos.x)or(bola_ant.pos.x<>env.currentBall.pos.y)then Begin if ((bola_ant.pos.yenv.currentBall.pos.x))then //2 Begin bola_prev.pos.x:=env.currentBall.pos.x-coef*abs(bola_ant.pos.x-env.currentBall.pos.x); bola_prev.pos.y:=env.currentBall.pos.y+coef*abs(bola_ant.pos.y-env.currentBall.pos.y); End else if ((bola_ant.pos.y>env.currentBall.pos.y)and(bola_ant.pos.x>env.currentBall.pos.x))then //3 Begin bola_prev.pos.x:=env.currentBall.pos.x-coef*abs(bola_ant.pos.x-env.currentBall.pos.x); bola_prev.pos.y:=env.currentBall.pos.y-coef*abs(bola_ant.pos.y-env.currentBall.pos.y); End else if ((bola_ant.pos.y>env.currentBall.pos.y)and(bola_ant.pos.xenv.currentBall.pos.x))then //5 Begin bola_prev.pos.x:=env.currentBall.pos.x-coef*abs(bola_ant.pos.x-env.currentBall.pos.x); bola_prev.pos.y:=env.currentBall.pos.y; End else if ((bola_ant.pos.y=env.currentBall.pos.y)and(bola_ant.pos.xenv.currentBall.pos.y)and(bola_ant.pos.x=env.currentBall.pos.x))then //8 Begin bola_prev.pos.x:=env.currentBall.pos.x; bola_prev.pos.y:=env.currentBall.pos.y-coef*abs(bola_ant.pos.y-env.currentBall.pos.y); End; End; {if ((env.currentBall.pos.xbola_prev.pos.x-0.05))or ((env.currentBall.pos.ybola_prev.pos.x-0.05))then Begin Showmessage(floattostr(1000*millisecondsbetween(now,time))); End; } end; //Procedimento chutar a bola procedure Chuta_bola(var robott:Trobot;var destino:Trobot;var env:TEnvironment;aux:integer); var distx,disty: double; begin //Váriavel auxiliar (aux) para tocar numa diagonal deslocada para o jogador que //recebe a bola, neste caso deslocamento será nulo //Base para o calculo (metodo de semelhança de triangulo) distx:=abs(env.currentBall.pos.x-destino.pos.x); disty:=abs(env.currentBall.pos.y-destino.pos.y); //Se o destino estiver acima da bola será um equação diferente para o //cálculo da trajetória if (destino.pos.y>env.currentBall.pos.y)and(destino.pos.x=(env.currentBall.pos.x+SQRT(49/(sqr(disty/distx)+1)))-2)and (robott.pos.y<=((env.currentBall.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux)+2))and (robott.pos.y>=((env.currentBall.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux)-2))then Begin //Para robô robott.velocityLeft:=0; robott.velocityRight:=0; Position(robott,destino.pos.x,destino.pos.y); end //Se nao atingiu, ajusta a posição Else Begin Position(robott,bola_prev.pos.x+SQRT(49/(sqr(disty/distx)+1)),bola_prev.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux); End; End; if (destino.pos.y=(env.currentBall.pos.x+SQRT(49/(sqr(disty/distx)+1)))-2)and (robott.pos.y<=((env.currentBall.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux)+2))and (robott.pos.y>=((env.currentBall.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux)-2))then Begin //Para robô robott.velocityLeft:=0; robott.velocityRight:=0; Position(robott,destino.pos.x,destino.pos.y); end //Se nao atingiu, ajusta a posição Else Begin Position(robott,bola_prev.pos.x+SQRT(49/(sqr(disty/distx)+1)),bola_prev.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux); End; End; if (destino.pos.yenv.currentBall.pos.x)then Begin //Se atingiu a posição atrás da bola para toque...para e toca if (robott.pos.x<=(env.currentBall.pos.x-SQRT(49/(sqr(disty/distx)+1)))+2)and (robott.pos.x>=(env.currentBall.pos.x-SQRT(49/(sqr(disty/distx)+1)))-2)and (robott.pos.y<=((env.currentBall.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux)+2))and (robott.pos.y>=((env.currentBall.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux)-2))then Begin //Para robô robott.velocityLeft:=0; robott.velocityRight:=0; Position(robott,destino.pos.x,destino.pos.y); end //Se nao atingiu, ajusta a posição Else Begin Position(robott,bola_prev.pos.x-SQRT(49/(sqr(disty/distx)+1)),bola_prev.pos.y+SQRT(49/(sqr(distx/disty)+1))-aux); End; End; if (destino.pos.y>env.currentBall.pos.y)and(destino.pos.x>env.currentBall.pos.x) then Begin //Se atingiu a posição atrás da bola para toque...para e toca if (robott.pos.x<=(env.currentBall.pos.x-SQRT(49/(sqr(disty/distx)+1)))+2)and (robott.pos.x>=(env.currentBall.pos.x-SQRT(49/(sqr(disty/distx)+1)))-2)and (robott.pos.y<=((env.currentBall.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux)+2))and (robott.pos.y>=((env.currentBall.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux)-2))then Begin //Para robô robott.velocityLeft:=0; robott.velocityRight:=0; Position(robott,destino.pos.x,destino.pos.y); end //Se nao atingiu, ajusta a posição Else Begin Position(robott,bola_prev.pos.x-SQRT(49/(sqr(disty/distx)+1)),bola_prev.pos.y-SQRT(49/(sqr(distx/disty)+1))+aux); End; End; end; //Procedimento que não deixa jogadores do mesmo time bater entre si procedure Afasta(var robotc:Trobot;var robota:Trobot;var env:TEnvironment); Begin if (robotc.pos.x>robota.pos.x) then Position(robotc,robota.pos.x-10,robota.pos.y); if (robotc.pos.xrobota.pos.y) then Position(robotc,robota.pos.x,robota.pos.y+10); if (robotc.pos.y 85)then Begin //Se estiver acima da linha horizontal superior da área if (env.currentBall.pos.y > 55)then Begin Posiciona(robot_gol,env,90.4616,48,0.25); End Else Begin //Se estiver abaixo da linha inferior horizontal da área if (env.currentBall.pos.y < 25) then Begin Posiciona(robot_gol,env,90.4616,35,0.25); End else //Se estiver dentro da área Begin //Se estiver muito próximo da bola, chuta if (env.currentBall.pos.y >= 30)and(env.currentBall.pos.y <= 50)and (env.currentBall.pos.x >= 87)then Begin if (distancia(env.currentBall.pos,robot_gol.pos)<=2) then Position(robot_gol,bola_prev.pos.x,bola_prev.pos.y) else //Se não, só acompanha Begin Posiciona(robot_gol,env,90.4616,bola_prev.pos.y,0.25); End; End; End; End; End //Se não estiver próximo da área Else Begin if ((env.currentBall.pos.y >= 35)and(env.currentBall.pos.y <= 50))then Begin Posiciona(robot_gol,env,90.4616,bola_prev.pos.y,0.25); End Else Begin //Se estiver abaixo da linha horizontal da trave inferior if (env.currentBall.pos.y<35)then Begin Posiciona(robot_gol,env,90.4616,35,0.25); End Else //Se estiver acima da linha horizontal da trave superior Begin Posiciona(robot_gol,env,90.4616,48,0.25); End; End; End; End; End //Se a bola estiver atrás do goleiro Else Begin //Se estiver perto da linha do gol if (env.currentBall.pos.y >= 35)and(env.currentBall.pos.y <= 50)and (env.currentBall.pos.x >= 87)then Begin //Se a bola estiver em uma faixa de "Y" e não estiver colado na bola if (env.currentBall.pos.yrobot_gol.pos.y-1)and (distancia(env.currentBall.pos,robot_gol.pos)>3)then Begin //Se a bola estiver um pouco abaixo escapa por cima if (env.currentBall.pos.y3)then Begin //Se a bola estiver um pouco abaixo if (env.currentBall.pos.yrobot_gol.pos.y-5)and (distancia(env.currentBall.pos,robot_gol.pos)>5)then Begin //Se a bola estiver um pouco abaixo escapa por cima if (env.currentBall.pos.y5)then Begin //Se estiver abaixo da linha horizontal da trave inferior if (env.currentBall.pos.y<35)then Begin Posiciona(robot_gol,env,90.4616,35,0.25); End //Se estiver abaixo da linha horizontal da trave inferior Else Begin if (env.currentBall.pos.y>55)then Begin Posiciona(robot_gol,env,90.4616,55,0.25); End Else //Caso contrário posiciona no meio Position(robot_gol,90.4616,42.2002); End; End //Se estiver colado na bola else Position(robot_gol,bola_prev.pos.x - 5,bola_prev.pos.y+10); End; End; if (robot_gol.pos.y>55)or(robot_gol.pos.y<35)then Position(robot_gol,90.4616,42.2002); End; End; //Procedomento que controla o robô zagueiro procedure Zagueiro(var robot_zag,robot_at,robot_gol:TRobot;var env:TEnvironment); Begin Sai_do_canto(env,robot_zag); //Se tiver próximo ao atacante, se afasta if (distancia(robot_zag.pos,robot_at.pos)<8) then Afasta(robot_zag,robot_at,env) else Begin //Se tiver próximo ao goleiro, se afasta if (distancia(robot_zag.pos,robot_gol.pos)<8) then Afasta(robot_zag,robot_gol,env) else Begin //Posição de cruzamento if (temp[1]=1)then Begin if (env.currentBall.pos.y<55)and(env.currentBall.pos.y>25)then Begin aux.pos.x:=7.664; aux.pos.y:=40; Chuta_Bola(robot_zag,robot_at,env,1); End Else Posiciona(robot_zag,env,50,42,1); if (env.currentBall.pos.x>45)or(env.currentBall.pos.x<10) then Begin temp[1]:=0; boo2:=false; End End Else //Não está em posição de cruzamento Begin //Se a bola estiver na área de cobertura do goleiro if ((env.currentBall.pos.x>55.3632)and(env.currentBall.pos.x<80.3632))or ((env.currentBall.pos.x>55.3632)and(env.currentBall.pos.y>55.3632))or ((env.currentBall.pos.x>55.3632)and(env.currentBall.pos.y<25.3632))then Begin If (robot_zag.pos.x 70.3632) and (robot_zag.pos.x < 80.3632) then Begin Posiciona(robot_zag,env,75.3632,bola_prev.pos.y,1); end else //Posiciona o robô para um faixa em que protege a bola Posiciona(robot_zag,env,75.3632,bola_prev.pos.y,1); End; End; End; End; End; //Procedimento que controla atacante procedure Atacante(var robot_at,robot_zag:TRobot;var env:TEnvironment); begin if (temp[1]=1) then Begin if ((env.currentBall.pos.y>70)and(robot_at.pos.y>70))or ((env.currentBall.pos.y<10)and(robot_at.pos.y<10))then Gira(robot_at,env,robot_at.rotation+180) else Begin if (env.currentBall.pos.y>60)then Begin if (robot_at.pos.x>env.currentBall.pos.x-1)and(robot_at.pos.xenv.currentBall.pos.x-1)and(robot_at.pos.x20)and(env.currentBall.pos.y<60)then Begin robot_at.velocityLeft:=0; robot_at.velocityRight:=0; End; End; End Else Begin //Se a bola estiver na defesa if (env.currentball.pos.x>50) then Begin //Se a bola estiver nesta faixa de valores if (env.currentball.pos.y<50)and(env.currentball.pos.y>35)then Begin //Se a bola estiver acima do zagueiro, posiciona para cima if (env.currentball.pos.y>robot_zag.pos.y)then Position(robot_at,30,60) //Caso contrário, posiciona para baixo else Position(robot_at,30,25); End Else Begin //Se estiver acima if (env.currentball.pos.y>50)then Position(robot_at,30,25) //Se estiver abaixo else Position(robot_at,30,60); End; End //Se bola estiver no ataque Else Begin if (robot_at.pos.x>50) then Begin aux.pos.x:=7.664; aux.pos.y:=40; Chuta_bola(robot_at,aux,env,0); End Else Begin //Se o atacante estiver na ponta superior if (robot_at.pos.y>42) then Begin if (env.currentBall.pos.y<60)then Begin aux.pos.x:=7.664; aux.pos.y:=40; Chuta_bola(robot_at,aux,env,0); End Else //Se não irá cruzar Begin temp[1]:=1;//Variável de auxilio para o cruzamento End; End Else //Se o atacante estiver na ponta inferior Begin if (env.currentBall.pos.y>20)then Begin aux.pos.x:=7.664; aux.pos.y:=40; Chuta_bola(robot_at,aux,env,0); End Else //Se não, irá cruzar Begin temp[1]:=1;//Variável de auxilio para o cruzamento End; End; End; End; End; End; //Os três procedimentos a seguir devem ser implementados procedure Create(var env:TEnvironment);stdcall; begin bolax_ant:=50; bola_ant.pos.x:=50; bolay_ant:=41; bola_ant.pos.y:=41; bola_prev.pos.x:=50; bola_prev.pos.y:=41; end; procedure Destroy(var env:TEnvironment);stdcall; begin bolax_ant:=50; bola_ant.pos.x:=50; bolay_ant:=41; bola_ant.pos.y:=41; bola_prev.pos.x:=50; bola_prev.pos.y:=41; boo2:=false; Cont:=0; end; procedure Strategy(var env:TEnvironment);stdcall; begin case env.gameState of NORMAL_GAME : begin if (boo2=false) then Begin temp[0]:=Random(100); boo2:=true; End; previsao_Bola(2,env); env.lastBall.pos.x:=50; env.lastBall.pos.y:=41; Goleiro (env.home[0],env.home[1], env); //Zagueiro(env.home[1],env.home[3],env.home[0],env); //Atacante(env.home[3],env.home[1], env); //Sai_do_canto(env,env.home[1]); { Goleiro (env.home[0],env.home[1], env); if (temp[0]>=25)and(temp[0]<50)then begin Estrategia_Inicio1(env.home[3],env.home[1],env); end; if (temp[0]<25)then begin Estrategia_Inicio2(env.home[1],env.home[3],env); end; if (temp[0]>=50)and(temp[0]<75)then begin Estrategia_Inicio3(env.home[3],env.home[1],env); end; if (temp[0]>=75)then begin Estrategia_Inicio4(env.home[1],env.home[3],env); end; if (boo1=true)then Begin boo2:=false; Zagueiro(env.home[1],env.home[3],env.home[0],env); Atacante(env.home[3],env.home[1], env); End; } end; FREE_BALL : begin env.lastBall.pos.x:=50; env.lastBall.pos.y:=41; Goleiro (env.home[0],env.home[1], env); end; PLACE_KICK : begin end; PENALTY_KICK : begin {if ((robot_gol.pos.x<91.4616)and(robot_gol.pos.x>89.4616))and ((robot_gol.pos.y<49)and(robot_gol.pos.y>47)) then begin robot_gol.velocityLeft:=0; robot_gol.velocityRight:=0; end else begin //Posiciona no destino Position(robot_gol,90.4616,48); end;} end; FREE_KICK : begin end; GOAL_KICK : begin end; end; end; // torna os procedimentos visíveis externamente exports Create, Destroy, Strategy; begin // Form2:=TForm2.Create(Application); // Form2.Show; end.