1-- Dies ist der BlobbyVolley2 Bot "Hyperion"
2-- geschrieben und getestet wurde der Bot mit der SVN-Version
3-- Die Version Blobby0.6 hatte verschiedene Bugs, unter anderem bei der oppx() und der estimate() Funktion
4--
5-- Hyperion ver. 0.6
6
7-- <Abschnitt 1> - Einige Konstanten die die physikalische Welt in BlobbyVolley2 beschreiben
8
9g=0.28
10g_p=0.88
11v0=14.5
12v_p=4.5
13jb_p=0.44
14r1=31.5
15
16-- </Abschnitt 1>
17
18
19-- <Abschnitt 2> - kleine unkomplizierte Hilfsfunktionen die ich benötige
20
21function max(a,b)
22	if (a>b) then
23		return a
24	else
25		return b
26	end
27end
28
29function min(a,b)
30	if (a<b) then
31		return a
32	else
33		return b
34	end
35end
36
37function y_b(y,vy,t)
38-- Eingabe: Position und Geschwindigkeit des Balles, Zeitpunkt an dem man die y-Koordinate des Balles wissen möchte
39-- Ausgabe: Höhe des Balles nach der Zeit t
40	return y+(vy-g/10)*t-1/2*g*t^2
41end
42
43function peak(y,vy)
44	return vy/g-1/10
45end
46
47function ymax_b(y,vy)
48	return y_b(v,vy,peak(y,vy))
49end
50
51function move(x)
52	if (posx()<x) and (math.abs(posx()-x)>2.6) then right()
53	elseif (posx()>x) and (math.abs(posx()-x)>2.6) then left()
54	end
55end
56
57function t1_y(y,vy,height)
58-- Eingabe: Position und Geschwindigkeit des Balles, Höhe die der Ball erreichen soll
59-- Ausgabe: Ausgabe der Zeit bis zur Höhe height
60	if (vy^2/g^2-vy/(5*g)+1/100+2*(y-height)/g<0) then
61		return -1
62	else
63		return -1/10+vy/g-math.sqrt( vy^2/g^2-vy/(5*g)+1/100+2*(y-height)/g )
64	end
65end
66
67function t2_y(y,vy,height)
68-- Eingabe: Position und Geschwindigkeit des Balles, Höhe die der Ball erreichen soll
69-- Ausgabe: Ausgabe der Zeit bis zur Höhe height
70	if (vy^2/g^2-vy/(5*g)+1/100+2*(y-height)/g<0) then
71		return -1
72	else
73		return -1/10+vy/g+math.sqrt( vy^2/g^2-vy/(5*g)+1/100+2*(y-height)/g )
74	end
75end
76
77function y_p(y,t)
78-- Eingabe: Position und Geschwindigkeit des Players, Zeitpunkt an dem man die y-Koordinate des Players wissen möchte
79-- Ausgabe: Höhe des Players nach der Zeit t
80	return y+(v0+jb_p/2+g_p/10)*t-1/2*(g_p-jb_p)*t^2
81end
82
83tp_peak=(14.5+0.44/2+0.88/10)/(0.88-0.44)
84yp_max=y_p(144.5,tp_peak)
85
86function time(t)
87	return 1/5*math.ceil(5*t)
88end
89
90function t2_yp(y,vy,height)
91y=144.5
92	return (v0+jb_p/2+g_p/10)/(g_p-jb_p)+math.sqrt((v0+jb_p/2+g_p/10)^2/(g_p-jb_p)^2+2*y/(g_p-jb_p))
93end
94-- </Abschnitt 2>
95
96
97-- <Abschnitt 3> - Komplizierte Funktionen die die Game-Engine nachbilden und so Einschlagpunkte, etc. berechnen.
98
99function collide(x,y,vx,vy,x2,y2,r2)
100-- Berechnet, ob und nach welcher Zeit der Ball im Zustand (x,y,vx,vy) mit der Kugel an (x2,y2) mit Radius r2 kollidiert
101local leftb=x2-r2-r1
102local rightb=x2+r2+r1
103local lowerb=y2-r2-r1
104local upperb=y2+r2+r1
105
106local txlb=time((leftb-x)/vx) -- Zeit zur linken Begrenzung
107local txrb=time((rightb-x)/vx) -- Zeit zur rechten Begrenzung
108local tyla=time(t1_y(y,vy,lowerb)) --untere Grenze steigend (ascending)
109local tyld=time(t2_y(y,vy,lowerb)) --untere Grenze fallend (descending)
110local tyua=time(t1_y(y,vy,upperb)) --obere Grenze steigend (ascending)
111local tyud=time(t2_y(y,vy,upperb)) --obere Grenze fallend (descending)
112local tp=time(vy/g-1/10) -- Zeit bis die Ballkurve auf dem Höhepunkt ist (kann in der Vergangenheit liegen)
113
114local t1,t2,t_coll=0,0,-1
115
116if (vx>0) then
117		t1=max(max(txlb,tyla),0)
118		t2=min(txrb,tyld)
119	else
120		t1=max(max(txrb,tyla),0)
121		t2=min(txlb,tyld)
122end
123
124if (t1<t2) and (t1<300) and (math.abs(t1-t2)<100) then
125	for t=t1,t2,0.2 do
126		local xnew,ynew=x+vx*t,y_b(y,vy,t)
127		if ((xnew-x2)^2+(ynew-y2)^2<(r1+r2)^2) then
128			t_coll=t
129			break
130		end
131	end
132end
133
134return t_coll
135end
136
137function estimate_t(x,y,vx,vy,height)
138-- schätzt den Ort des Balles bei der Höhe height fallend und die Zeit bis dahin
139
140local collision=1
141local t_wall,t_net,t_netsphere=0,0,0
142local t_ret,x_ret,y_ret,vx_ret,vy_ret=0,0,0,0,0
143local t_height=0
144while(collision==1) do
145	t_netsphere=collide(x,y,vx,vy,400,316,7)
146	if (vx>0)
147		then
148		t_wall=time((768.5-x)/vx)
149		t_net=time((361.5-x)/vx)
150		else
151		t_wall=time((31.5-x)/vx)
152		t_net=time((438.5-x)/vx)
153	end
154	local t=10000
155	if ((t_netsphere>0) and (t_netsphere<t)) then t=t_netsphere end
156	if (((t_net>0) and (t_net<t)) and (y_b(y,vy,t_net)<316)) then t=t_net end
157	if ((t_wall>0) and (t_wall<t)) then t=t_wall end
158	t_height=time(t2_y(y,vy,height))
159	if (t_height>t) then
160		if (t==t_netsphere) then
161			t_ret=t_ret+t
162			vx_ret=0
163			vy_ret=0
164			x_ret=400
165			y_ret=316
166			collision=0
167		end
168		if (t==t_net) or (t==t_wall) then
169			t_ret=t_ret+t
170			x=x+vx*t
171			y=y_b(y,vy,t)
172			vx=-vx
173			vy=vy-g*t
174			collision=1
175		end
176	else
177		t_ret=t_ret+t_height
178		vx_ret=vx
179		vy_ret=vy-g*t_height
180		x_ret=x+vx*t_height
181		y_ret=y_b(y,vy,t_height)
182		collision=0
183	end
184
185
186end -- while Ende
187return x_ret,y_ret,vx_ret,vy_ret,t_ret
188end
189
190
191
192
193function impact(x,y,vx,vy,xpos,ypos)
194-- schätzt den Einschlagsort des Balles wenn er mit dem Blobby an Position xpos kollidiert ist und dann losfliegt.
195-- Funktioniert mit minimalem Fehler
196
197r1=31.5
198r2=25
199--local x,y,vx,vy,t1=estimate_t(x,y,vx,vy,(ypos+19+25)+31.5) Die Wete haben schon nahe genug zu sein
200local t=time(collide(x,y,vx,vy,xpos,ypos+19,25))
201if(t>0) then
202	x=x+vx*t
203	y=y_b(y,vy,t)
204	dx=x-xpos
205	dy=y-(ypos+19)
206	l=math.sqrt(dx^2+dy^2)
207	vx=dx/l
208	vy=dy/l
209	x=x+vx*3
210	y=y+vy*3
211	vy=vy*13.125
212	vx=vx*13.125
213--	x=x+vx/5
214--	y=y+vy/5
215	x,y,vx,vy,t=estimate_t(x,y,vx,vy,220.5)
216	return x,y,vx,vy,t
217else
218	return -1,-1,-1,-1,-1
219end
220
221end -- Funktionsende
222
223function xtoplayto(target,height)
224
225local x,y,vx,vy,t=estimate_t(ballx(),bally(),bspeedx(),bspeedy(),height+(25+19)+31.5+5)
226local xpos=estimate_t(ballx(),bally(),bspeedx(),bspeedy(),height+(25+19)+31.5)
227local sgn=0
228if (x<target) then sgn=-1 else sgn=1 end
229local imp=0
230local oldimpact=-1000
231
232for pos=xpos,xpos+sgn*30,sgn*2.5 do
233	imp=impact(x,y,vx,vy,pos,height)
234	if (math.abs(imp-target)<math.abs(oldimpact-target)) then
235		oldimpact=imp
236	else
237		xpos=pos-sgn*2.5
238		break
239	end
240end
241
242return xpos
243end
244
245
246-- </Abschnitt 3>
247
248-- <Abschnitt 4> - High-Level Funktionen die bestimmen wo man s
249
250function stellen(tox,height)
251--t2_yp
252--t2_y
253if (tox<390) then
254
255elseif (390<tox) and (tox<410) then
256
257elseif (tox>410) then
258
259end
260
261move(xplayto(tox,posy()))
262end
263
264
265function schmettern()
266
267end
268
269function ueberspielen()
270
271end
272
273
274
275-- </Abschnitt 4>
276
277-- <Abschnitt 5> - Die Hauptfunktionen des Spiels
278function OnOpponentServe()
279end
280
281function OnServe(ballready)
282if (math.abs(math.floor(posx()/4.5)-posx()/4.5)<0.4)
283	then
284		if(math.abs(180-posx())<2) then jump() else moveto(180) end
285	else
286		moveto(400)
287	end
288	old=5
289end
290
291function OnGame()
292
293
294
295
296x1=ballx()
297y1=bally()
298vx1=bspeedx()
299vy1=bspeedy()
300x2=oppx()
301y2=163.5
302r2=25
303
304xe=estimate_t(x1,y1,vx1,vy1,220.5)
305--debug(xe)
306-- debug(x2)
307xr,yr,vxr,vyr,tr=impact(x1,y1,vx1,vy1,x2,144.5)
308
309
310-- debug(xr)
311-- debug(0)
312
313
314if (xe<400) then
315
316		if (touches()==0) then
317		test=xtoplayto(320,144.5)
318		move(test)
319		else
320		test=xtoplayto(400,144.5)
321		move(test-3.1)
322		end
323
324
325elseif (xe==400) then
326	move(180)
327else
328	move(180)
329end
330old=touches()
331end