inglesp / botany Goto Github PK
View Code? Open in Web Editor NEWPyCon UK 2018 bot tournament
PyCon UK 2018 bot tournament
When you look at the full list of games between bots, the opponent bot names are mangled. For example, on my recent bot list at https://botany18.pyconuk.org/bots/155/games/, I see
As bot2 against Martijn Pieters : : anarchist.py (bot2 won)
As bot1 against house : : anarchist.py (bot1 won)
and
As bot1 against Jon Bannister : : anyboot.py (bot1 won)
As bot2 against Martijn Pieters : : anyboot.py (bot2 won)
My bot was not bot2 against Martijn Pieters : : anarchist.py or Martijn Pieters : : anyboot.py; that should be Jon Bannister : : anarchist.py, respectively.
Would it be more appropriate (and specific, so more helpful to the client) to use 401 status when we're unable to validate the API token?
With the botany client, you can print messages to the console.
Could be interesting to add the possibility for the bot to communicate via the web page.
This could be done via the return of the function get_next_move, adding a 3rd variable after state.
get_next_move would then return (move, state, message).
Currently, individual games are rendered as a series of tables, fully displaying the board for each step.
Can the move list be added for easy re-use? I want to be able to re-create games locally for better analysis and stepping through manually is a bit of a pain.
A simple 0-based numerical list would be great. ๐
It would be helpful for bot writers to know whether their bot has exceeded the opcode limit by a little or a lot.
The runner should let a bot exceed the limit, up to a higher hard limit. This would still cause the bot to fail, but it would allow us to report to the user how much the limit had been exceeded.
When I play a single game between the attached bots, my bot (error_unable_to_connect4) always hits the opcode limit. In a tournament my bot only fails some of the time, even though the moves are identical.
Steps to reproduce:
Download and extract the bots from bots.zip and run the following games
$ botany play error_unable_to_connect.py loser.py
$ botany tournament error_unable_to_connect.py loser.py
I've used the state variable to track the highest number of opcodes used by my bot in any turn. You can get the botany client to report this info by adding one line to botany_core/runner.py, at the end of the run_game
function:
winner = game.check_winner(board)
if winner is not None:
+ print("Winning bot's state:", state)
assert winner == token
return build_result(ResultType.COMPLETE, winning_scores[player_ix])
The opcode count appears to spike the first time the bot plays first and second, but it settles down to 20761 for the final 4 games of the 10. Given both bots follow predictable algorithms (neither use random) I'd expect the opcodes to be completely consistent?
In the client, allow to impose a set a moves when using "botany play" (via --list_moves). But this would not work for state bots.
It is possible to do with via the web.
Restriction is that the number of moves submitted needs to be even (otherwise you would need to change bot1 and bot2).
When using /play//human/, human is always the first player.
The client submits bots to the server as application/x-www-form-urlencoded
data; this is a limited format that Django rightly restricts with a size limit.
However, that leaves bot files with limited space in the module. If the server were to accept bots as files however, larger modules could be submitted.
The client code would need to switch to using the files
parameter:
submit_url = utils.get_setting("origin") + "/api/submit/"
bot_name = os.path.basename(path)
# optionally: verify bot code first, before submission
# utils.read_bot_code(path)
data = {
"api_token": utils.get_setting("api_token"),
"bot_name": bot_name,
}
with open(path) as bot_file:
files = {'bot_code': bot_file}
rsp = requests.post(submit_url, data=data, files=files)
and the server would need to use request.FILES['bot_code']
to access the uploaded bot code.
The online play-vs-bot feature assumes that the state
object returned by bots is JSON serialisable. Make this explicit in the documentation.
(My bot produces a Position()
instance which is not seralisable but could be made to be)
Reproduce using django shell:
$ python manage.py shell
>>> from botany.actions import create_user, create_bot, set_bot_active, mark_bot_failed
>>> test_user = create_user("[email protected]", "Test User")
>>> bot1 = create_bot(test_user, "todo.py", "# TODO")
>>> mark_bot_failed(bot1)
>>> bot1.state
'failed'
>>> set_bot_active(bot1, test_user)
Traceback [...] assert bot.is_under_probation or bot.is_inactive [...]
>>> bot1.state
'failed'
>>> bot2 = create_bot(test_user, "todo.py", "# TODO")
>>> set_bot_active(bot2, test_user)
>>> bot1.refresh_from_db()
>>> bot1.state
'inactive'
>>> set_bot_active(bot1, test_user)
>>> bot1.state
'active'
I believe this process can be replicated via the website's UI.
Should be simple to fix, I'll have a look at it later
My long term goal is to make the server code an app that can be added to another project's INSTALLED_APPS
.
This will include:
This could be done with rank()
.
When debugging or when encountering a bug, Python wants to load the original source file to show you the relevant source lines. But bots are compiled without a reference to the source file, so debugging and analysing tracebacks is way harder than it needs to be.
I hacked up my botany_client and botany_core packages to pass along the path and use that when compiling:
# botany_core.loader
def create_module_from_str(name, code, path=None):
mod = ModuleType(name)
if path is not None:
mod.__file__ = path
code = compile(code, path, 'exec')
exec(code, mod.__dict__)
return mod
and
# botany_client.utils
def create_bot_module(name, path):
bot_code = read_bot_code(path)
return loader.create_module_from_str(name, bot_code, path)
Currently, you must run bots locally with a tracer (when using Python 3.7 at least), which slows execution down and hinders debugging.
I hacked up my client to accept a negative opcode limit, to turn off the tracer altogether:
if opcode_limit is None:
opcode_limit = utils.get_setting("botany_opcode_limit")
if opcode_limit < 0:
opcode_limit = None
This isn't the cleanest approach, but illustrates an approach.
From server settings.py
file:
# TODO read this from environment (and make optional)
BOTANY_TOURNAMENT_CLOSE_AT = datetime(2018, 9, 18, 14, 30, tzinfo=bst)
Development is much easier with this set based on a relative date or disabled. What env variable did you have in mind? Perhaps set a 'DEPLOYMENT` variable that defaults to 'production' and when set to 'development' instead the above is set to a relative date with an optional override?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.