From 7aa825614c88a2bb73989d8d938f078a6c7391b8 Mon Sep 17 00:00:00 2001 From: Peter Ward Date: Thu, 6 Sep 2012 15:18:18 +1000 Subject: Stuff. --- docs/Makefile | 4 +-- docs/closest_apple.py | 2 +- docs/firstbot.py | 6 ---- docs/firstbot.tex | 73 ++++++++++++++++++++++++++++++++++++++---- docs/introduction.tex | 86 ++++++++++++++++++++++++++++++++------------------ docs/print_bot.py | 6 ---- docs/random_avoid.tex | 12 +++---- docs/random_simple.tex | 2 ++ docs/tutorial.tex | 11 +++++-- snakegame/__init__.py | 3 ++ 10 files changed, 143 insertions(+), 62 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index 0b05cb0..5cd4a7e 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ FILES = $(wildcard *.tex *.py) BUILD_FILES = $(patsubst %,${BUILD_DIR}/%,${FILES}) LATEX=xelatex -LATEX_FLAGS=-shell-escape +LATEX_FLAGS=-shell-escape -interaction=nonstopmode .PHONY: all @@ -13,7 +13,7 @@ all: tutorial.pdf ${BUILD_DIR}: mkdir -p ${BUILD_DIR} -${BUILD_DIR}/%.tex: %.tex ${BUILD_DIR} +${BUILD_DIR}/%.tex: %.tex ./jinja2 --latex < $< > $@ ${BUILD_DIR}/%.py: %.py diff --git a/docs/closest_apple.py b/docs/closest_apple.py index 8f8c560..3696bfa 100644 --- a/docs/closest_apple.py +++ b/docs/closest_apple.py @@ -2,7 +2,7 @@ DIRECTIONS = { 'L': (-1, 0), 'U': (0, -1), 'R': (1, 0), - 'D': (1, 0), + 'D': (0, 1), } def closest_apple_bot(board, position): diff --git a/docs/firstbot.py b/docs/firstbot.py index b7abf4b..6eb8484 100644 --- a/docs/firstbot.py +++ b/docs/firstbot.py @@ -1,8 +1,2 @@ def up_bot(board, position): return 'U' - -if __name__ == '__main__': - from snakegame.engines.pyglet import PygletEngine - engine = PygletEngine(10, 10, 20) - engine.add_bot(up_bot) - engine.run() diff --git a/docs/firstbot.tex b/docs/firstbot.tex index 221928c..7e95b85 100644 --- a/docs/firstbot.tex +++ b/docs/firstbot.tex @@ -1,4 +1,5 @@ \section{Your First Bot} +\label{sec:firstbot} \fasttrack{Always move up.} Alright, let’s get started. @@ -10,13 +11,71 @@ useless as that: our bot is just going to continually move up. Let’s have a look at the code: \pythonfile{firstbot.py} -If you run this script (\texttt{python firstbot.py}), -you should see a nice big board with some apples scattered over it, and a snake -continually moving upwards. -That snake is our bot: each time the game decides that our snake is allowed to -move, it calls the \texttt{up\_bot} function, which immediately returns the -string \mint{python}|'U'|, which means it should move the snake upwards. +Pretty simple, huh? +It’s a function takes as input two parameters, and returns a string. +We’ll have a look at \texttt{board} and \texttt{position} later, +but the important thing here is that the returned value says which direction the +snake should move in. Each time the snake is allowed to make a move, the +function is called, it returns one of \py|'U', 'D', 'L', 'R'| +(indicating up, down, left and right, respectively), and the snake is moved in +that direction. + +\subsection{Running the code} + +Depending on how you have installed SnakeGame, there are a few different ways to +run the code. If you’re in some kind of programming class, ask your instructor +which method to use. + +\subsubsection{Method A: CLI interface} + +If you installed from the repository (using \texttt{pip}), this is the method +you should use. +Assuming you’ve put the \texttt{up\_bot} function in a file called +\texttt{mybot.py}, you can run this command: + +\begin{shell} +$ snakegame mybot:up_bot +\end{shell} + +To use different viewers, you can supply the \texttt{-v VIEWER} argument: +\begin{shell} +$ snakegame -v pyglet mybot:up_bot +$ snakegame -v pygame mybot:up_bot +$ snakegame -v curses mybot:up_bot +\end{shell} + +You can specify multiple bots, and also control the width, height and number of +apples on the board: +\begin{shell} +$ snakegame -w 4 -h 20 -a 30 mybot:up_bot mybot:up_bot mybot:up_bot +\end{shell} + +\subsubsection{Method B: Pyglet / Pygame} + +You can also add some code to the file containing your bot so that you can run +that file as a normal Python program, which will run the game. +At the end of the file, add this: +\begin{pythoncode} +if __name__ == '__main__': + from snakegame.engine import Engine + from snakegame.viewers.pyglet import Viewer + engine = Engine(10, 10, 25) + engine.add_bot(up_bot) + viewer = Viewer(engine) + viewer.run() +\end{pythoncode} + +If you want to use pygame instead, change \texttt{snakegame.viewers.pyglet} to +\texttt{snakegame.viewers.pygame}. + +If neither of these work, there is also a console viewer, which works if you’re +in a terminal (it will not work in IDLE!): +use \texttt{snakegame.viewers.curses}. + +\subsection{Got it running?} + +Great, you should see a nice big board with some apples scattered over it, +and a snake continually moving upwards. -Got all that? Once you’re ready, we’ll move on to something a little more interesting. diff --git a/docs/introduction.tex b/docs/introduction.tex index 3f8d1d8..5a149b7 100644 --- a/docs/introduction.tex +++ b/docs/introduction.tex @@ -1,37 +1,61 @@ \section{Introduction} -I assume you know the basics of Python: -printing stuff, -if/elif/else, -for and while loops and lists. -That’s really all you need to follow along at least the first four sections, -and then dictionaries will start to come in handy. - -If you have no idea what I was just talking about, \emph{don’t panic}. -All that means is that you’re not quite ready for this yet, -and you need to start by learning Python using some of these excellent -resources: +Before starting this tutorial, you should \emph{already} know the basics of +Python. Specifically, you should know these bits of Python: \begin{itemize} - \item \url{http://openbookproject.net/thinkcs/python/english2e/} - \item \url{http://learnpythonthehardway.org/} - \item \url{http://docs.python.org/tutorial/} - \item Anyone you know who knows about Python, or is a programmer. + \item How to \py|print| things + \item \py|if|, \py|elif| and \py|else| + \item \py|for| and \py|while| loops + \item \py|list|s and \py|dict|ionaries + \item functions (\py|def|) \end{itemize} -Don’t be discouraged if it doesn’t immediately make sense: -programming can be difficult and frustrating, -but if you put the effort in, it can also be a very rewarding, interesting and -fun activity. - -If you are stuck with anything, Google it first. - -You’ll need to start by getting the code. -The repository is at -\url{http://hg.flowblok.id.au/snakegame}, -you can install it with pip: -\begin{minted}{sh} + +\subsection{Help! I don’t know what these are…} + +If you have no idea what any of those things are, \emph{don’t panic}. +All that means is that you’re not quite ready to follow this tutorial yet, and +you need to learn the basics of Python first. +There are many excellent \emph{free} resources for doing this: +\begin{itemize} + \item How to Think Like a Computer Scientist \\ + (\url{http://openbookproject.net/thinkcs/python/english2e/}) + \item Learn Python the Hard Way \\ + \url{http://learnpythonthehardway.org/} + \item The official tutorial in the Python documentation \\ + \url{http://docs.python.org/tutorial/} +\end{itemize} + +The most important resource to learn programming, however, are the people you +know who are learning Python with you, already know Python, or some other +programming language. +You can spend hours trying to understand something in books and not get it, +but ask another person to explain it, and it will all suddenly ‘click’ and make +sense. + +\subsection{Yeah, I know what those are.} + +Excellent! Let’s get started then. + +If you’re doing this in some kind of programming class, your instructor may have +provided you with a zip file (or similar) containing SnakeGame and pyglet. +If so, follow their instructions for setting it up, and head straight on to +Your First Bot. + +Otherwise, you’ll need to first install the code. The latest version of +SnakeGame is available in a Mercurial repository at +\url{http://hg.flowblok.id.au/snakegame}. +You can install it using pip: +\begin{shell} $ pip install hg+http://hg.flowblok.id.au/snakegame#egg=SnakeGame -\end{minted} +\end{shell} + +If you wish to have a pretty graphical viewer for watching the game being +played, you will also need to install pyglet\footnoteurl{http://pyglet.org/} +and/or pygame\footnoteurl{http://pygame.org}. + +\subsection{Skipping ahead} -Each section starts with a Fast track note: -if you know what you’re doing, just write a bot which moves according to what it -says in the fast track note, and you can skip that section. +If you already know Python, you will probably want to skip some sections of this +tutorial. To make this easier, there is a \emph{Fast track} note at the start of +each section: if you can write a bot which does what it says, you can safely +skip that section. diff --git a/docs/print_bot.py b/docs/print_bot.py index 8352aec..5adee1f 100644 --- a/docs/print_bot.py +++ b/docs/print_bot.py @@ -1,9 +1,3 @@ def print_bot(board, position): print position print board - -if __name__ == '__main__': - from snakegame.engines.pyglet import PygletEngine - engine = PygletEngine(3, 4, 3) - engine.add_bot(print_bot) - engine.run() diff --git a/docs/random_avoid.tex b/docs/random_avoid.tex index 042c947..90ac183 100644 --- a/docs/random_avoid.tex +++ b/docs/random_avoid.tex @@ -15,7 +15,7 @@ are. But rather than me just telling you what they are, why not have a look yourself? -\pythonfile{print\_bot.py} +\pythonfile{print_bot.py} You should see something like this (on a 4x3 board): \begin{minted}{pytb} @@ -31,15 +31,15 @@ AssertionError: Return value should be a string. \end{minted} Ignore all the Exception stuff, that’s just because we didn’t return one of -\pyinline|'L'|, \pyinline|'U'|, \pyinline|'D'| or \pyinline|'R'|. -The first line is our position: it’s a \pyinline|tuple| of the x and y +\py|'L'|, \py|'U'|, \py|'D'| or \py|'R'|. +The first line is our position: it’s a \py|tuple| of the x and y coordinates of our snake’s head. The second line is the board: it’s a list of each row in the board, and each row is a list of the cells in that row. Notice that if we index the board first by the y coordinate and then by the x coordinate, we can get the character in the board where our snake is: -\pyinline|board[y][x] == board[2][1] == 'A'|. +\py|board[y][x] == board[2][1] == 'A'|. The head of our snake is always an uppercase character in the board, and the rest of our body (the tail) are always lowercase characters. @@ -131,9 +131,9 @@ cell. Remember that our board is a list of rows (stacked vertically), and each row is a list of cells (stacked horizontally). So we need to first find the right row, which we will do by using the y -coordinate: \pyinline|board[y]|. +coordinate: \py|board[y]|. Then we need to find the right cell in the row, using the x coordinate: -\pyinline|board[y][(x + 1) % width]|. +\py|board[y][(x + 1) % width]|. We’re almost at the end: all we need to do is build up a list of each cell we can move into. We know that we can move into cells which are diff --git a/docs/random_simple.tex b/docs/random_simple.tex index 7ccb3a5..a1ff557 100644 --- a/docs/random_simple.tex +++ b/docs/random_simple.tex @@ -7,6 +7,8 @@ The next bot we’ll write is one which instead of moving in just one direction, chooses a direction at random to move in. Go on, try writing it yourself! I’ll wait here until you’re ready. +Hint: check out the \texttt{random} module. + Got it working? Good work! But you’ve probably noticed that there’s a problem: it doesn’t take long for our random bot to die. diff --git a/docs/tutorial.tex b/docs/tutorial.tex index e67b824..a76760b 100644 --- a/docs/tutorial.tex +++ b/docs/tutorial.tex @@ -16,20 +16,24 @@ \usepackage{minted} \usemintedstyle{tango} -\newmint[pyinline]{python}{} +\newmint[py]{python}{} \newminted{python}{} \newmintedfile{python}{} +\newminted[shell]{sh}{} + \setmainfont{Linux Libertine O} \setmonofont[AutoFakeBold]{Inconsolata} \setlength\parskip{2ex} \setlength\parindent{0mm} -\widowpenalty=1000 -\clubpenalty=1000 +%\widowpenalty=1000 +%\clubpenalty=1000 \newcommand\fasttrack[1]{\vspace{-2ex}\hfill\emph{Fast track: #1}\nopagebreak} +\newcommand\footnoteurl[1]{\footnote{\url{#1}}} + \begin{document} \title{Writing SnakeGame bots} @@ -51,6 +55,7 @@ \input{look_ahead.tex} +\break \input{closest_apple.tex} \end{document} diff --git a/snakegame/__init__.py b/snakegame/__init__.py index c4dbc83..be1f7a7 100644 --- a/snakegame/__init__.py +++ b/snakegame/__init__.py @@ -26,14 +26,17 @@ def main(argv=None): parser.add_argument( '-w', '--width', default=30, + type=int, ) parser.add_argument( '-h', '--height', default=20, + type=int, ) parser.add_argument( '-a', '--apples', default=40, + type=int, ) parser.add_argument('bot', nargs='+') args = parser.parse_args(argv) -- cgit v1.2.3