From 84d9ed671f6a30ae83bac4082f61efbedb763d31 Mon Sep 17 00:00:00 2001 From: Rike-Benjamin Schuppner Date: Tue, 26 May 2015 23:33:04 +0200 Subject: [PATCH] WIP: Preliminary woring version. --- Pelita.ipynb | 315 ++++++++++++++++++++---------- pelita/ipython/__init__.py | 37 +--- pelita/ipython/_static/index.html | 43 ++-- 3 files changed, 239 insertions(+), 156 deletions(-) diff --git a/Pelita.ipynb b/Pelita.ipynb index c508c6d6e..5efedfe25 100644 --- a/Pelita.ipynb +++ b/Pelita.ipynb @@ -1,15 +1,39 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Pelita Notebook\n", + "Defining a player and running a Pelita game from inside IPython" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First: some basic imports" + ] + }, { "cell_type": "code", "execution_count": 1, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ - "%load_ext autoreload\n", - "%autoreload 2" + "import pelita\n", + "from players import FoodEatingPlayer\n", + "from pelita.game_master import GameMaster\n", + "from pelita.player import AbstractPlayer, SimpleTeam" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The player which we define is the `SmartRandomPlayer`, which is also shown on the homepage. Nothing too fancy here…" ] }, { @@ -20,116 +44,161 @@ }, "outputs": [], "source": [ - "import pelita.ipython" + "from pelita import datamodel\n", + "class SmartRandomPlayer(AbstractPlayer):\n", + " def get_move(self):\n", + " dangerous_enemy_pos = [bot.current_pos\n", + " for bot in self.enemy_bots if bot.is_destroyer]\n", + " killable_enemy_pos = [bot.current_pos\n", + " for bot in self.enemy_bots if bot.is_harvester]\n", + "\n", + " smart_moves = []\n", + " for move, new_pos in list(self.legal_moves.items()):\n", + " if (move == datamodel.stop or\n", + " new_pos in dangerous_enemy_pos):\n", + " continue # bad idea\n", + " elif (new_pos in killable_enemy_pos or\n", + " new_pos in self.enemy_food):\n", + " return move # get it!\n", + " else:\n", + " smart_moves.append(move)\n", + "\n", + " if smart_moves:\n", + " return self.rnd.choice(smart_moves)\n", + " else:\n", + " # we ran out of smart moves\n", + " return datamodel.stop" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We define our" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { - "collapsed": false + "collapsed": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Listening on 0.0.0.0, port 46668\n" - ] - } - ], + "outputs": [], + "source": [ + "team = SimpleTeam(\"My winning team\", SmartRandomPlayer(), SmartRandomPlayer())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, "source": [ - "application, sockets = pelita.ipython.printit()" + "… and the enemy’s team." ] }, { "cell_type": "code", "execution_count": 4, "metadata": { - "collapsed": false + "collapsed": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "'ipc:///tmp/pelita.140416746065592'" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "application.path" + "enemy = SimpleTeam(\"Enemy team\", FoodEatingPlayer(), FoodEatingPlayer())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We set-up a maze" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { - "collapsed": false, - "scrolled": false + "collapsed": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "http://0.0.0.0:46668/static/index.html\n" - ] - }, - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/plain": [ - "" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "from IPython.display import IFrame\n", - "url = \"http://%s:%i/static/index.html\" % sockets[0].getsockname()\n", - "print(url)\n", - "IFrame(url, width=600, height=300)" + "layout = \"\"\"\n", + "##################################\n", + "#... # .# # # 3#\n", + "# ## # # ### # # #####1#\n", + "#. # # # . # ## #\n", + "#.# # . # . # #########\n", + "# ## # ## #### # ##. . . .#\n", + "#.. . . #. . #. # # ## ##### #\n", + "# ## #### #.## # # . . . ..#\n", + "#.. .. # # # # ##### #####\n", + "##### ##### # # # # .. ..#\n", + "#.. . . . # # ##.# #### ## #\n", + "# ##### ## # # .# . .# . . ..#\n", + "#. . . .## # #### ## # ## #\n", + "######### # . # . # #.#\n", + "# ## # . # # # .#\n", + "#0##### # # ### # # ## #\n", + "#2 # # #. # ...#\n", + "##################################\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now it’s time for some interaction with IPython. Basically, we hijack IPython’s tornado application and use this for our own websockets and small file server." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { - "collapsed": false + "collapsed": true + }, + "outputs": [], + "source": [ + "import pelita.ipython\n", + "from IPython.display import IFrame" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Register our application:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "WebSocket opened\n" + "Listening on 0.0.0.0, port 52588\n" ] } ], "source": [ - "from subprocess import Popen" + "application, sockets = pelita.ipython.init_app()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This ipc socket is a subscriber sink for a Pelita zmq publisher socket:" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 8, "metadata": { "collapsed": false }, @@ -137,90 +206,130 @@ { "data": { "text/plain": [ - "" + "'ipc:///tmp/pelita.4360207608'" ] }, - "execution_count": 11, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "Popen([\"/home/schuppner/Projects/pelita/pelitagame\", \"--null\", \"--publish\", application.path])" + "application.path" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We create a publisher which will act as a viewer for the Pelita process and send all data. (Every application should have only one publisher, otherwise it might not work.)" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": { - "collapsed": false + "collapsed": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Listening on 0.0.0.0, port 36979\n" - ] - } - ], + "outputs": [], "source": [ - "application2, sockets2 = pelita.ipython.printit()" + "from pelita.simplesetup import SimplePublisher" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": { - "collapsed": false + "collapsed": true + }, + "outputs": [], + "source": [ + "publisher = SimplePublisher(application.path)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we’ll get the HTML output prepared in an iframe. This will accept data over a websocket and start displaying our little game once the data arrives." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "scrolled": true }, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "This iframe is also available as: http://0.0.0.0:52588/static/index.html\n" + ] + }, { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ - "" + "" ] }, - "execution_count": 12, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "IFrame(\"http://%s:%i/static/index.html\" % sockets2[0].getsockname(), width=800, height=500)" + "url = \"http://%s:%i/static/index.html\" % sockets[0].getsockname()\n", + "print(\"This iframe is also available as: {url}\".format(url=url))\n", + "IFrame(url, width=600, height=300)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we set up a game with the given layout and teams. Remember to always connect to the publisher before starting the game. Otherwise, there’ll be no output." ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "WebSocket opened\n" + ] } ], "source": [ - "Popen([\"/home/schuppner/Projects/pelita/pelitagame\", \"--null\", \"--publish\", application2.path])" + "gm = GameMaster(layout, [team, enemy], 4, 100)\n", + "gm.register_viewer(publisher)\n", + "gm.play()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The most likely outcome is, that we lose badly against the FoodEatingPlayers." ] }, { @@ -249,7 +358,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.2" + "version": "3.4.3" } }, "nbformat": 4, diff --git a/pelita/ipython/__init__.py b/pelita/ipython/__init__.py index f0db631c9..d240a0664 100644 --- a/pelita/ipython/__init__.py +++ b/pelita/ipython/__init__.py @@ -19,15 +19,6 @@ import json -class WebWrapper: - def __init__(self): - pass - - def show(self): - pass - - - class ZMQPubSub: def __init__(self, callback): self.callback = callback @@ -46,23 +37,12 @@ class Application(tornado.web.Application): def __init__(self): self.path = 'ipc:///tmp/pelita.%i' % id(self) handlers = [ - (r"/", HomePageHandler), (r"/static/(.*)", tornado.web.StaticFileHandler, {'path': os.path.join(os.path.dirname(__file__), '_static')}), (r"/ws-echo", EchoWebSocket, {'path': self.path}) ] tornado.web.Application.__init__(self, handlers, debug=True) -# Handle the home page/index request. -# @route("/"). -class HomePageHandler(tornado.web.RequestHandler): - def get(self): - # self.render("index.html") - self.render_string("index.html") - self.write("hi") - class EchoWebSocket(tornado.websocket.WebSocketHandler): - - def initialize(self, path): self.path = path self._walls = None @@ -79,7 +59,6 @@ def open(self): def on_message(self, message): pass - # self.write_message(u"You said: " + message) def on_close(self): print("WebSocket closed") @@ -111,8 +90,11 @@ def on_data(self, data): bot_data = bot.current_pos bots.append(bot_data) - teams = [{"name": game_state["team_name"][idx], "score": t.score} - for idx, t in enumerate(universe.teams)] + if game_state: + teams = [{"name": game_state["team_name"][idx], "score": t.score} + for idx, t in enumerate(universe.teams)] + else: + teams = [] data = {'walls': self._walls, 'width': width, @@ -123,15 +105,9 @@ def on_data(self, data): 'state': game_state } data_json = json.dumps(data) - # print data_json self.write_message(data_json) - -IFRAME = """ - -""" - -def printit(): +def init_app(): application = Application() sockets = tornado.netutil.bind_sockets(0, '', family=socket.AF_INET) server = tornado.httpserver.HTTPServer(application) @@ -140,5 +116,4 @@ def printit(): for s in sockets: print('Listening on %s, port %d' % s.getsockname()[:2]) -# tornado.ioloop.IOLoop.current().start() return application, sockets diff --git a/pelita/ipython/_static/index.html b/pelita/ipython/_static/index.html index 4c8172806..64c853039 100644 --- a/pelita/ipython/_static/index.html +++ b/pelita/ipython/_static/index.html @@ -2,7 +2,6 @@ Pelita - @@ -18,27 +17,27 @@

Score A : Scor