Jupyter + Archimedes

I have been playing with Jupyter and Calysto Hy recently. When it comes to testing (especially with the tools I’m used to), there’s couple hitches: nosetests aren’t executed automatically and any exception that a cell throws stops execution of whole notebook. Like before, this blog post was originally written with Jupyter, because it just makes so easy to interleave code and prose, while making sure that the code is actually runnable.

Continue reading

Jupyter Lab, Calysto Hy, Archimedes… oh my

I recently came across a really nifty looking set of tools, namely: Jupyter Lab and Calysto Hy. Former is continuation of IPython, a notebook based Python authoring tool. It lets you write notebooks online and mix in Python. As such it’s really nice for writing reports, while doing compations required for that report at the same time. Calypso Hy is metakernel, that allows Jupyter Lab (and Jupyter in general) use Hy.

Here I’m going to give Jupyter Lab and Calysto Hy a little test drive, using some familiar libraries: Hypothesis and Archimedes.

Continue reading

new rat AI in works

AI routines for enemies in Herculeum are nothing fancy, mostly just random movement until the player happens to wander too close. The plan is to have each monster to behave in a semi-predictable, distinct way (think monster in Super Mario Bros.). First guinea pig for AI experimentation will be rat. The plan is to make them search for closest wall and then walk alongside the wall, randomly turning back when they arrive a corner. If player happens to come too close, the rat will attack. I have not yet decided how will they react on ranged attacks, but probably they are going to flee.

To make things more interesting, I’m going to write AI routines using Hy.

As always, I started with little bit doodling and then writing couple of tests:

(import [pyherc.test.builders [LevelBuilder CharacterBuilder]]
	[pyherc.ai.rat [next-to-wall?]]
	[hamcrest [assert-that is- is-not :as is-not- none has-items]])

(defn test-empty-space-is-detected [] 
  "test that an empty space is not reported as wall"
  (let [[character (-> (CharacterBuilder)
		               (.build))]
	[level (-> (LevelBuilder)
               (.with-floor-tile :floor)
		       (.with-wall-tile :empty-wall)
		       (.with-empty-wall-tile :empty-wall)
		       (.with-solid-wall-tile :solid-wall)
		       (.with-character character (, 5 9))
		       (.build))]
	[wall-info (next-to-wall? character)]]
    (assert-that wall-info (is- (none)))))

(defn test-wall-is-detected [] 
  "test that a wall can be detected next to a given point"
  (let [[character (-> (CharacterBuilder)
		               (.build))]
	[level (-> (LevelBuilder)
               (.with-floor-tile :floor)
		       (.with-wall-tile :empty-wall)
	    	   (.with-empty-wall-tile :empty-wall)
    		   (.with-solid-wall-tile :solid-wall)
		       (.with-wall-at (, 4 10))
		       (.with-wall-at (, 5 10))
    		   (.with-wall-at (, 6 10))
	    	   (.with-character character (, 5 9))
		       (.build))]
	[wall-info (next-to-wall? character)]]
    (assert-that wall-info (is-not- (none)))
    (let [[wall-direction (get wall-info :wall-direction)]]
      (assert-that wall-direction has-items [:east :west]))))

The threading macro (->) makes it breeze to use all those builders that I have coded in Python. Without it I would have to write very deeply nested function calls. I’m also very happy about how clean and readable Hamcrest verifications are. It’s really hard to get closer to natural language in a standard programming language.

Tinkering with testing in Hy

I have been playing around with Hy more recently and started liking it a lot. I’m nowhere productive in coding with it, but I’m sure learning all kinds of new things.

Recently I decided to write some tests for Sandvalley project and came up with the following:

(import [sandvalley.tests.helpers [get-in-memory-connection]])
(import [sandvalley.person [save-person load-person]])
(import [sandvalley.database.schema [create-schema]])
(import [hamcrest [assert-that is- equal-to]])

(defn test-save-person []
  (let [[person {"id" None "name" "Pete"}]
        [connection (create-schema (get-in-memory-connection))]
        [saved-person (save-person person connection)]
        [loaded-person (load-person (get saved-person "id") connection)]]
    (assert-that (get loaded-person "name") (is- (equal-to "Pete")))))

(defn test-update-person []
  (let [[person {"id" None "name" "Pete"}]
        [connection (create-schema (get-in-memory-connection))]
        [saved-person (save-person person connection)]
        [loaded-person (load-person (get saved-person "id") connection)]]
    (assoc loaded-person "name" "Uglak")
    (save-person loaded-person connection)
    (let [[updated-person (load-person (get saved-person "id") connection)]]
      (assert-that (get updated-person "name") (is - (equal-to "Uglak"))))))

(if (= __name__ "__main__")
  (test-save-person)
  (test-update-person))

Pretty basic things, we create an empty in-memory database and do some saving, loading and updating on it. Nice thing is that I can use Hamcrest with asserts and the API does not stand out from rest of the code. The part I don’t like is

(assoc loaded-person "name" "Uglak")

, since there I’m changing loaded-person. I’ll probably end up writing a helper function that can combine two dictionaries and use it instead.

However, I haven’t been able to figure out how to run tests with Nose. If I could compile the code to bytecode, it should be possible. Hy project has tests written in Hy and apparently I can even run them with nose. However, when I tried to imitate what they are doing, I ended up getting funny errors deep inside hy2py. So in the meantime, I have settled on running tests from __main__. The drawback of course is that as soon as one of them fails, the execution halts.

Travis CI environment

I recently set up a build in Travis CI environment. It is really cool hosted continuous integration service for the open source community and well integrated with GitHub to boot. Every time I push code into my public repository in GitHub, Travis is notified and will run 3 test builds for me. Each build is done with different version of Python, so I can now easily cover 2.6, 2.7 and 3.2. Especially 3.2 is very good, since I don’t have that set up on my system. If everything goes fine, I don’t even notice the whole process. Only when build breaks, I get an email stating the problem and I can start hunting the error.

Setting up Travis was really easy. I just had to enable hook for it in GitHub and write a simple configuration file:

language: python
python:
  - "2.6"
  - "2.7"
  - "3.2"
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
install: 
 - "easy_install -U mockito"
 - "easy_install -U pyhamcrest"
 - "easy_install -U decorator"
# command to run tests, e.g. python setup.py test
script: nosetests -w ./src/pyherc

The configuration is for running for three versions of Python (2.6, 2.7 and 3.2). At the start of the build, the system will install three libraries (mockito, pyhamcrest and decorator). Builds are always done in a clean environment and all changes are rolled back after finishing the build.

After that the system was more or less working and the only thing I had to do was to fix the codebase to work with Python 3.2.

The system has been set up to run only unit tests from pyherc project (more or less the engine of my game). UI tests I can not run without PyQt being installed and currently that is not provided as a easy install package. CPU time and bandwidth are considerations too, since I don’t want to take too much resources from a free service.

For a single developer working on a hobby project, this is probably a little bit overkill. But I like to tinker with things and try out them in a small software project, where it is easier than on a huge one.