lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I am planning to write a game for a competition where people can code
bots (artificial intelligences, AI). Contrary to the coding
competition AI games that I know (robocode for example), I want to
limit the number of instructions that each AI has - so that every AI
has the same amount of instructions per round. This should simulate
the realtime behaviour of real robots where each CPU has a limited
number of instructions per second. I would endorse this solution since
I have seen efficient clever yet simple solution that got beaten by
complex and inefficient solutions even though it was obvious, that the
clever solution would have been better in means of execution time.
Another benefit is, that this approach allows me to naturally force
users to write AIs that can be presented in realtime. Setting
execution time limits in seconds has proven to be not working
reliable.

Fortunately, Lua supports debug hooks with instruction counters - so I
can yield the program execution after a certain amount of instructions
and let other AIs run until I perform a new step in the simulated
physical world.
Unfortunately, this works only without problems as long as no
coroutines are used by the coders.

The idea is, that the debug hook yields when the instruction limit is
reached and the yield goes back to the initial kickoff for the running
AI, so the next AI code can be executed. This works fine, even if
multiple coroutines are used -  I rewrote the coroutine.resume
function so that it yields (and resumes) over all the AI coroutines
from my hook's yield back to the kickoff and back again when the
execution should be continued. All fine here.

However, there is another problem that I did not foresee: When a new
coroutine is resumed and I set a new hook for that coroutine, the
instruction counter starts with 0 again.
So for example: I want to yield my execution each 100 instructions.
The code creates a new coroutine at instruction 30. I set a new hook
for the new coroutine (must do). Again with a instruction limit of
100. The coroutine however performs only 90 instructions and finishes.
My AI has now used up 120 instructions in total but no hook call was
involved. This can be repeated until one coroutine reaches the limit
of 100. So an "evil" AI could easily use up nearly an infinite amount
of instructions without ever getting interrupted, just by creating new
coroutines everytime when it is running out of instructions.

I don't know now how to tackle this... I would prefer a solution that
does not involve C coding (though it could be done). The right way
would be to sum the used instructions from all coroutines together
when setting a new debug hook and setting the number of remaining
instructions as debug hook count limit for the new coroutine. When a
coroutine finishes, I read out the number of used instructions and set
a new hook for the running coroutine with the remaining instructions
as count limit again. But since I can't read out the instruction
counter from Lua, I can't do this (is this possible in C? I haven't
checked). In my opinion, it would make sense if debug.gethook would
return the instruction counter if an instruction limit is set. If this
information would be included, the problem could be solved correctly.

Alternative workaround solutions could be:
* Set the number of instructions so low that it is impossible to use
coroutines to increase the number of allowed instructions (bad
performance)
* Yield the execution if a new coroutine is invoked (call the hook)
(using coroutines in AIs would be ineffective)

I wished I could simply set one hook for all coroutines, but it looks
like that this is not possible - and I don't believe that this is
"need to have" feature for Lua, since this is quite a special
situation.

What would you suggest?

Eike