Menu

[3722f3]: / bin / modules / lea / lea.lua  Maximize  Restore  History

Download this file

257 lines (230 with data), 10.0 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
-- Podball Project https://sourceforge.net/projects/podball/
-- This is Lea, an example of a Lua control script.
-- You may use this code freely, as a base for your own control scripts.
-- We import the vector module.
-- Note that vector.lua is in the same directory as this file.
-- This works because Podball sets the Lua package path to the path given in match.info.
local vector = require "vector"
-- Module wide variables
-- These are part of the Podball API
local PB = {}
PB.GAME = {}
PB.MATCH = {}
-- Enumeration constants for convenience
PB.NO_TEAM = -1
PB.OUR_TEAM = 0
PB.OTHER_TEAM = 1
PB.ACTION_NOTHING = 0
PB.ACTION_MOVE = 1
PB.ACTION_SHOOT = 2
PB.BALL_FREE = 0
PB.BALL_CONTROLLED = 1
-- These are for this module only
local GOAL_KEEPER_POSITION = vector(-0.45, 0)
local FIELD_POSITIONS = {}
local FORWARD_POSITION = vector(0.45, 0)
local GOAL_POSITION = vector(0.5,0)
-- Last ball owning team
local last_owningteam = PB.OTHER_TEAM
-- Some useful physical constants.
-- They will be calculated during initMatchTeam.
-- Distance the ball travels until loosing half of his velocity.
local pass_distance
-- Time this will take.
local pass_time
-- The pod that wants to get the ball.
local acting_pod
----------------------------------------
-- Podball API function.
-- This stateless function should return static info about the module.
function getModuleInfo()
local t = {}
t["name"] = "Lea" -- The module's name
t["version"] = "1.1" -- A version number of the module
t["author"] = "Me" -- The author of the module
t["date"] = "2018-02-19" -- The release date of this module
t["min_pods"] = 1 -- The minimum number of pods per team this module supports
t["max_pods"] = 12 -- The maximum number of pods per team this module supports
return t
end
----------------------------------------
-- Podball API function.
-- Called for every new match and once per team.
-- For parameter gameSettingsParam, see struct GAMEINFO defined in podtypes.h.
-- For parameter matchSettingsParam, see struct CMatchSettings defined in PB.h.
function initMatchTeam(gameSettingsParam, matchSettingsParam)
PB.GAME = gameSettingsParam
PB.MATCH = matchSettingsParam
if PB.MATCH.debug then
print("Lea: init.")
-- The config string provided via the match settings. (Not used here)
print("Lea: Config: " .. PB.MATCH.strConfig)
-- Your script shouldn't be too verbose when PB.MATCH.debug == false !
print("Lea: Debug Mode: " .. tostring(PB.MATCH.debug))
end
pass_distance = 1.0 * PB.GAME.SHOOT_FORCE / PB.GAME.BALL_FRICTION
--print(pass_distance)
pass_time = -1 * (PB.GAME.BALL_MASS / PB.GAME.BALL_FRICTION) * math.log(0.5)
--print(pass_time)
acting_pod = 0
for i=1,PB.GAME.NPODS do
FIELD_POSITIONS[i] = vector(-math.cos(i*2*math.pi/PB.GAME.NPODS)*0.28,
math.sin(i*2*math.pi/PB.GAME.NPODS)*0.22)
end
end
----------------------------------------
-- Helper function.
-- This function returns the (normalized) direction [pod] needs to shoot to
-- when we want the [ball] to go off to direction [d].
-- It compensates for the shooting pod's proper motion.
function getShootDirection(pod, ball, d)
setmetatable(d, getmetatable(vector.zero))
local v0 = (d * PB.GAME.SHOOT_FORCE / PB.GAME.BALL_MASS):normalize_inplace()
return ((v0 - pod.v) * ball.mass):normalize_inplace()
end
----------------------------------------
-- Helper function.
-- If the [origin] object wants to move in the direction of the [target] object,
-- then given [origin] and [target]'s proper motions and inertia,
-- this function returns the direction of the acceleration force that [origin] needs to provide.
-- The function takes into account a first order lead pursuit course,
-- i.e. assuming the [target] will stay at its current velocity.
function getAccelDirectionToMovingTarget(origin, target)
-- Maximum velocity with which [origin] can travel.
local v_max = PB.GAME.ACCEL_FORCE / origin.fric;
-- Distance to target.
local d = (target.q - origin.q):len()
-- Time in which we can make the distance to [target] with that velocity.
-- This will be the time for which we predict the movement.
local t = d/v_max;
-- Predcited positions.
local target_pos = target.q + (target.v*t)
local origin_pos = origin.q + (origin.v*t)
return (target_pos - origin_pos):normalize_inplace()
end
----------------------------------------
-- Podball API function.
-- Called for every time step the engine needs a control module action for a team.
-- Input: world - The state of the game world containing all object positions among others.
-- See WORLDSTRUCT in podtypes.h.
-- NOTE: In order to respect common habits of Lua, pod indices go from 1 to NPODS.
-- This includes the variable world.ball.owningpod.
-- Return value: Actions of all the pods of the own team:
-- A table podActions[1..NPODS] with a vector "a" and the action "action" to perform.
-- action is one of 0-do nothing; 1-move; 2-shoot
function getTeamActions(world)
--print(world.time)
-- 'vectorize' some of the tables.
setmetatable(world.ball.q, getmetatable(vector.zero))
setmetatable(world.ball.v, getmetatable(vector.zero))
setmetatable(world.ball.f, getmetatable(vector.zero))
for i=1,PB.GAME.NPODS do
setmetatable(world.team.pods[i].q, getmetatable(vector.zero))
setmetatable(world.team.pods[i].v, getmetatable(vector.zero))
setmetatable(world.team.pods[i].f, getmetatable(vector.zero))
setmetatable(world.otherteam.pods[i].q, getmetatable(vector.zero))
setmetatable(world.otherteam.pods[i].v, getmetatable(vector.zero))
setmetatable(world.otherteam.pods[i].f, getmetatable(vector.zero))
end
-- Initialize return values.
local podActions = {}
for i=1,PB.GAME.NPODS do
podActions[i] = {}
podActions[i].action = PB.ACTION_NOTHING
podActions[i].a = vector()
end
-- The hard work starts here...
if world.ball.owningteam == PB.OUR_TEAM then
last_owningteam = PB.OUR_TEAM
elseif world.ball.owningteam == PB.OTHER_TEAM then
last_owningteam = PB.OTHER_TEAM
end
-- Find the pod which is nearest to the ball.
if acting_pod == 0 or last_owningteam == PB.OTHER_TEAM then
local nearest_pod = 0
local nearest_d = 9.9
for this_pod=1,PB.GAME.NPODS do
-- predict 50 timesteps ahead
local d = vector.zero.dist(world.team.pods[this_pod].q, world.ball.q + world.ball.v * 50.0)
if d < nearest_d then
nearest_d = d
nearest_pod = this_pod
end
end
acting_pod = nearest_pod
end
-- Do the same thing for every pod ...
for this_pod=1,PB.GAME.NPODS do
-- Does our team have the ball?
if last_owningteam == PB.OUR_TEAM then
-- Does this pod have the ball?
if world.ball.owningpod == this_pod and world.ball.status == PB.BALL_CONTROLLED then
-- Check if we can shoot on goal
if vector.zero.dist(GOAL_POSITION, world.team.pods[this_pod].q) < pass_distance then
podActions[this_pod].a = getShootDirection(world.team.pods[this_pod], world.ball, GOAL_POSITION - world.team.pods[this_pod].q)
podActions[this_pod].action = PB.ACTION_SHOOT
else
-- Check if we can pass the ball to someone in a forward position
for other_pod=1,PB.GAME.NPODS do
if other_pod ~= this_pod then
if world.team.pods[other_pod].q.x > world.team.pods[this_pod].q.x
and vector.zero.dist(world.team.pods[other_pod].q, world.team.pods[this_pod].q) < pass_distance then
podActions[this_pod].a = getShootDirection(world.team.pods[this_pod], world.ball, world.team.pods[other_pod].q - world.team.pods[this_pod].q)
podActions[this_pod].action = PB.ACTION_SHOOT
acting_pod = other_pod
break
end
end
end
end
-- If we haven't decided to shoot yet ...
if podActions[this_pod].action ~= PB.ACTION_SHOOT then
-- then move to goal
podActions[this_pod].a = FORWARD_POSITION - world.team.pods[this_pod].q
podActions[this_pod].a:normalize_inplace()
podActions[this_pod].action = PB.ACTION_MOVE
end
else
-- No, then move ...
if this_pod == acting_pod then
podActions[this_pod].a = getAccelDirectionToMovingTarget(world.team.pods[this_pod], world.ball)
podActions[this_pod].action = PB.ACTION_MOVE
else
-- No, then go offensive position.
podActions[this_pod].a = FIELD_POSITIONS[this_pod] + vector(0.1,0) - world.team.pods[this_pod].q
podActions[this_pod].a:normalize_inplace()
podActions[this_pod].action = PB.ACTION_MOVE
end
end
elseif last_owningteam == PB.OTHER_TEAM then
-- If I am the nearest pod, go for the ball!
if this_pod == acting_pod then
podActions[this_pod].a = getAccelDirectionToMovingTarget(world.team.pods[this_pod], world.ball)
podActions[this_pod].action = PB.ACTION_MOVE
else
-- otherwise, go defensive positions
podActions[this_pod].a = FIELD_POSITIONS[this_pod] - vector(0.1,0) - world.team.pods[this_pod].q
podActions[this_pod].a:normalize_inplace()
podActions[this_pod].action = PB.ACTION_MOVE
end
end
end
if PB.MATCH.debug then
-- Example for using the built-in debug drawing interface
-- You must use "--debug" on command line AND "debug 1" in team control settings for this to work.
if acting_pod > 0 then
drawCross(world.team.pods[acting_pod].q, 0.02) -- draw a cross of radius 0.02 (arena units) around acting_pod
end
--drawCircle(world.team.pods[2].q, 0.05) -- draw a circle of radius 0.05 (arena units) around pod[2]
--drawLine(world.team.pods[1].q, world.team.pods[2].q) -- draw a line between the two pod positions
end
return podActions
end
----------------------------------------
-- Podball API function.
-- Called once at the end of a match.
function disposeMatchTeam()
if PB.MATCH.debug then
print("Lea: dispose.")
end
end
Oh no! Some styles failed to load. 😵 Please try reloading this page