The Game's Afoot - the indie Volity dev blog

Volity is a new up-and-coming platform that enables people to play casual games (the "old fashioned" card/board/dice kind) over the internet. This blog is a place where independent developers of Volity games can discuss their development efforts.

Saturday, June 24, 2006

A (hopefully) simple guide to getting ready to develop for volity on a windows box

This post contains the aforementioned Step 0: preparing to develop Volity games using python, and developing UI files for same, on a Windows box.

Part 1: Download all necessary software.

You will need the following software packages to develop using python:

  • A python interpreter (and if you're like me, an integrated development environment to develop in).  I went for the Activestate freely downloadable version because I knew where to find it and knew it would be a low-maintenance install process, but the canonical Windows version is at www.python.org.  Python.org's Windows version is also packaged in an installer and should not present any difficulty with respect to installation or configuration either (though I have yet to test it).

-- See http://www.python.org for download

  • The python Volity framework, which includes:
  1. The Volity game server source code in Python (currently the file volity-162.tar.gz)
  2. The script that sets up and initializes the Volity game server (currently volityd.py)
  3. The Zymb library, which the Volity Game server uses to communicate with the outside world
-- See http://www.eblong.com/zarf/volity/index.html (which also has sample code for games you can use to test your setup) and  http://www.eblong.com/zarf/zymb/index.html (for zymb) for downloads.

  • A program capable of extracting unix/linux zip (.gz) files.  I downloaded 7-zip for this purpose.  Its interface is a bit odd (it is like a parallel universe version of Windows Explorer), but it'll do the job.  A recent version of WinZip will also do this, but I was too cheap to get and register it.
-- see http://www.7zip.org for downloads

  • The volity testbench software, which will allow you to view and test your SVG User interface files.

-- See http://www.volity.org/projects/gamut/releases/latest/ to download testbench.

  • A recent version of the Java Runtime Environment to run testbench with; if you already have Gamut installed, you should have this already.  Even if you don't have Gamut installed you may be OK here. 

-- See http://java.sun.com if you want to go looking for the latest version of Java

You may want to download the following additional software:

  • Inkscape is a drawing program which has been designed specifically to use the SVG format which Volity uses (and extends).  Inkscape does not implement the interactive extensions Volity uses to create user interfaces, but it does allow you to create graphics, then examine and extract the underlying XML text used to store the graphics you have drawn.  You can then bring this text over into your UI files; your UI will then be able to draw the corresponding SVG graphics using the text you added to the file. 

-- See http://www.inkscape.org for download.

Part 2: Unzip and Install stuff

Install python.  Install your .gz capable unzipper, if needed.  Install Java, if needed.  Unzip the Zymb and Volity .gz files.  Extract the testbench.jar file from thedownloaded file and put it somewhere.

Part 3: Set up the python code to run

Find Python's Library folder.  (It will most likely be something along the lines of C:\python24\Lib (which is what mine was).)  Copy the zymb and volity folders from your unzipping in the previous step into this folder.  I also copied the volityd.py loader file here as well.

Part 3b: Handle some windows-specific issues in the python code

If you're developing under windows, (as I am) a little patching is currently necessary, at least until a couple of changes propagate through the python volity framework.  This step will hopefully become optional very soon.

The first change is required is necessary because sockets, as I understand it, behave in a non-standard way on Windows compared to anywhere else in the known computing universe.  (Bill Gates, if you're reading this, it's all *your* fault!!)  To be specific, there is a Windows-specific error that has to be explicitly ignored.  To patch for this, open the tcp.py file in the Lib\zymb\ folder, and find line 129. 

It should say:

if (errnum == errno.EAGAIN)

You should change this to:

if (errnum == errno.EAGAIN or errnum == errno.WSAEWOULDBLOCK)

(Python is indentation-sensitive, so be sure that you leave the indentation as is when you do this.)

The other thing I had to do when setting up and testing was compensate for my python implementation's lack of an SSL module, and for that the volity code itself has to be patched.  There will be a command line switch in a future version of the framework files - because you wouldn't necessarily want to operate that way consistently, but if you need to boot volity for testing on a PC, you just plain need to get things running.  (Aside: I've gone looking for a canonical SSL module for python 2.4 for Windows and failed to find one - which is part of what delayed this post, BTW.  Successfully finding and setting up an SSL module for python 2.4 would also solve this second issue.)

The edit you'll need is on line 83 of volent.py in the code in the volity folder.  It should say:

        self.conn = jabber.client.JabberAuthResource(self.jid, self.password, host=host)

To unilaterally disable SSL (as was necessary to get the framework running for me), you would change this to:

        self.conn = jabber.client.JabberAuthResource(self.jid, self.password, host=host, secure=jabber.client.SECURE_NONE)
 
Once these issues are corrected in a future release - It was the framework's author that heard me out and suggested these changes, so you know they'll be in an upcoming update - no patching should be necessary.

Part 4: Get the Python stuff running

In this step, you test to ensure you can run the framework - and a sample game server - successfully.

What I did for testing purposes was to create a subfolder in the lib folder called games, and move the python files for whatever games I wanted to test into that folder so that python cound find them easily. Once I did that (and in combination with my previous setup steps), I could open a DOS window, change folders to the Lib folder (where I have everything set up) and type:

python volityd.py --jid [redacted]@volity.net --password [Redacted] --game games.rps.RPS

... where [redacted] replaces things that I don't want you to see.  :-)

You can also create a shortcut to do the same thing, as long as you ensure that python and volityd.py are both findable by Windows when it goes looking.  A well-behaved version of python handles this automatically for python; I set the folder to start in to where volityd.py was, and everything worked fine.

While I'm talking about all of this, I should mention that, until you start registering your referees (more on this later), you have to terminate instances of them running in python by navigating to their window and pressing ctrl-c.  This is very useful knowledge to have.  :-)

Part 5: Get the Java testench stuff working

Set up a shortcut to run testbench with the UI framework you wish to develop.

This is straightforward enough to be done in a shortcut also.  I used this for my shortcut's target:

C:\WINDOWS\system32\java.exe -jar Testbench.jar test.svg

Then I set the folder to start in to the location of the test svg file, and everything worked well.

Next steps:

Currently, referees are generally debug the most easily by getting the UI running first and testing in that way, although Volity's

maintainers have show in interest in getting something released that allows for direct debugging.  Until then, anyway, the next

step is to start iterative development of the UI and get it working.  I've already done a bit of that, and intend to do a bit more

of that soon.  Hopefully you'll be seeing some of the fruits of that labor in a new post next weekend.

Wednesday, June 07, 2006

Basic referee code for Spoons (but no plumbing yet)

I'm still working on being able to test my game referee python code with full Volity plumbing - I'm running into what looks to be a network error or something - but because the mechanics of the game of spoons are so simple, a large portion of the rest of the game referee code is ready and has passed some basic testing. Now all that's needed before I can get it up and running is to be able to hook it up to the Volity RPC stuff. (Next week, I hope...)



# This python code is copyright (c) 2006 by Craig Kasper
# It is provided here for educational use and may be used freely
# for any non-commercial purpose.

# First steps in implementing Spoons for voility:
# passing cards around between hands with python, and grabbing spoons

# At this point, basic card passing and spoon grabbing functionality is present.
# However, much of the error-checking and all of the volity-related plumbing is missing
# because I still don't have all of the packages for developing for voility with python
# downloaded and ready for use in testing.

# Use a list for each hand and a list to hold all of the hands

import random

# Declare our global list of hands.
Hand_list = []

# Have a separate list to hold cards passed from hand to hand

Passed_list = ["","","",""]

# For the spoons, add players to the list as they grab the spoons
Spoons_list = []

# We need an actual player count to handle grabbing of the spoons; we'll set it to zero for now
# and set it at the start of the actual game.
Player_count = 0

def start_game(count_param):
# intialize the card stack
   
# Novice python programmer pitfall: access to global variables within a function definition
# usually requires use of the "global" pitfall

    global Player_count
    global Hand_list
    Player_count = count_param      # Set the global player count
    card_count = count_param * 4    # We need to count off four cards for each player before shuffling
    master_card_list = ["1C", "1D", "1H", "1S", "2C", "2D", "2H", "2S", "3C", "3D", "3H", "3S", "4C", "4D", "4H", "4S", "5C", "5D", "5H", "5S"]
    #Enough cards for 5 players so far, but we can up this later
    card_list=master_card_list[:card_count]
    # Slice off the exact number of cards we need from the start of the card array
    random.shuffle(card_list)
    # Python's random class makes the shuflfing easy

    # start with an empty hand list   
    Hand_list=[]
    while len(card_list) > 0:       # While there are cards left to deal
        Hand_list.append(card_list[:4]) # Add the first four cards to the list of hands as a list
        card_list=card_list[4:]         # remove the first four cards from the card list so they can't get dealt again

def pass_card(player_num, card_num):
# Pass one of the four cards (indexed from 0 to 3) in a player's hand to the next player
# Returns 0 if successful or -1 if the pass could not be completed.

# In theory, we only need full error checking in only the referee code or only the player code;
# In practice, we're going to put it into both sets of code to make it more robust

    if card_num < 0 or card_num > 3:    # Bounds check to ensure that the card number is valid
        return -1
    else:
        if Passed_list[player_num - 1] <> "": # Has this player passed a card that hasn't been picked up yet?
            return -1
            #the player is not allowed to pass more than one card at a time
        else:
            if len(Hand_list[player_num - 1]) <4:
                # The player is not allowed to pass a card twice in a row without picking up in between
                return -1
            else:
                Passed_list[player_num - 1]=Hand_list[player_num - 1][card_num]
                # Copy the passed card into the passed card list
                del Hand_list[player_num - 1][card_num]
                # Erase the passed card from the player's hand
                return 0

def receive_card(player_num):
#Receive the card passed by the previous player
#Returns 0 if successful or -1 if the pick-up could not be completed
   
    if Passed_list[player_num - 2] == "":
        return -1
        #the player cannot receive a card if none is available from a previous player passing it
    else:
        if len(Hand_list[player_num - 1]) >3:
            # The player is not allowed to receive a card with a full hand of 4 cards
            return -1
        else:
            Hand_list[player_num - 1].append(Passed_list[player_num - 2])
            # add the passed card to the player's hand
            Passed_list[player_num - 2]=""
            # erase the passed card from the passed card list
            return 0

#The above functions should successfully pass cards from one hand to another
#with an intermediate stop on the table in between, as with the real game of spoons

#To do: bounds checking on the player number


def end_of_round():
    print "End of game round here"

def end_of_game():
    print "End of game code here"

def grab_spoon(player_num):
    # We're going to grab spoons by adding the grabbing player to a list of spoon-grabbers
    # rather than by removing the spoons from a list because this approach allows us to
    # keep track of who has a spoon (for if and when that player tries to return the spoon)
    if player_num in Spoons_list:
        #One spoon per customer
        return -1
    else:
        if len(Spoons_list) == Player_count - 1:
            return -1
        else:           
            Spoons_list.append(player_num)
            print Spoons_list, Player_count
            if len(Spoons_list) == Player_count - 1:
                end_of_round()

def return_spoon(player_num):
    if len(Spoons_list) == Player_count - 1:
        return -1
    else:
        if player_num in Spoons_list:
            del Spoons_list[Spoons_list.index(player_num)]
            return 0
        else:
            return -1
       

Thursday, June 01, 2006

Current Projects now on the Wiki

Despite the fact that this Wednesday failed to be used for Volity development because a birthday party took a large chunk out of my evening, I have nonetheless accomplished something Volity-related.  The Volity Wiki now has a "current projects" page where developers can actually indicate what they're up to, and indeed I've listed my projects so far there.  I encourage you to list your projects there, as it gives Volity developers a single-page place to see if any other developers are working on their your pet project, and if collaborations are available.

(That's all for now; I will return to our regularly scheduled development discussion format in my next post.)

Craig

Wednesday, May 24, 2006

Step 1: Find Plans!

It's Wednesday, and time for me to sit down and officially get both ready started on implementing Spoons for Volity. (This is also known as getting your act together.)

Because Volity games involves users connecting to a server, a game developer needs to write two separate pieces of software for a Volity game. One piece of software runs on the user's machine to create the game window and is usually called the user interface, or UI; the other piece is called the referee and runs on the server and runs the actual game. Both of these pieces of software plug into other pieces of software which do the heavy lifting for you, allowing you to focus on the important parts: the user interface, and the logic behind the game.

The architecture which does this is smartly designed and works well for the casual user, but does pitch a few curveballs at the casual developer. Most notable among these is the fact that while the user interface is put together using a XML-based technology very similar to HTML+JavaScript (though better suited to graphically -oriented layout), the referee must currently be written in either Perl or Python. This is very nearly the programmer's equivalent to the separation of church and state; you must be platform-agnostic to some degree to fit in well in the Volity universe, regardless of whether you're more comfortable with the client side or the server side coding.

So, step 1 in any volity project (I'll cover step 0 - getting your computer set up for development - in another admittedly out-of-sequence post) is to figure out three things: what the user interface needs to do, what the referee needs to do, and how the two of them need to communicate. These three things will vary depending on the rules of the game you're implementing, as they will essentially be modeling the play (in the UI) and the rules (in the referee) as well as the interaction between the two.

So, to plan out how the game of Spoons is going to be developed, we need to figure out how to model the play from the player's perspective, and we also need to model the interactions between players that the rules prescribe.

From the player's perspective the play is not at all complicated. The player is dealt a starting hand of four cards, from a deck with four identical number cards for each player. With this hand, the player alternates between passing a card to the player on his/her right, and picking up the card passed by the player on his/her left. Turns do not exist, so a player can pass a card as long as the player to the right has received it, and can pick up card any time after the the player to the left has passed it. When the player has four of a kind he/she can grab a spoon out of the pile, at which point all other players must attempt to grab a spoon. The player left without a spoon gets a mark against him or her; when the player has reached the prescribed number of marks, that player is out of the game. A player may also bluff by grabbing a spoon without four of a kind, but if that player doesn't let go of the spoon quickly enough, he or she may regret it: if all the spoons are grabbed but no-one has four of a kind, everyone except the player without a spoon gets a mark. The last player not eliminated wins.

Okay, that's a nice brief rule set (at least compared to Puerto Rico or Settlers of Cataan), and it gives us a fairly basic set of possible moves to send to the referee:
  • Pass a card. This is allowed when the game is in play, and the player the card is passed to does not have any passed cards that have not been picked up, and there or no cards waiting that have been passed to the player.
  • Pick up a card. This is allowed when the game is in play, and the player has three cards, rather than the usual four, in his or her hand (which will happen every time a card is passed out of the player's hand).
  • Grab a spoon. This is allowed when the game is in play, there are spoons remaining, and the player does not already have a spoon.
  • Let go of a spoon. This is allowed when the game is in play, and the player already has a spoon.
The user interface will also need to display the current user's hand of three or four cards, the cards being passed in or out of the hand (face down, of course) and the spoons. Everything else will be taken care of by the referee. Because the referee enforces the rules in addition to handling all communication between players, the referee needs to know everything going on within the game; the players' UI components do not, and indeed, things will be easier for the programmer in most cases if the UI only knows how to draw the screen and send back the player's responses anyway.

This does mean, however, that the referee in this case has a fair amount to keep track of: the hands each player holds, the cards being passed from one player to another, and who has grabbed a spoon and who hasn't. Each player's move will change the game status for two of the players (passing cards) or all players (grabbing a spoon or letting go of it), and the changes will occur in no predictable order. As a well-designed Volity UI should allow for a whole-board redraw at any point in the game anyway (to facilitate people who come in late to watch, or start sharing a seat with a player halfway through a round), it makes a certain amount of sense to have the player expect a single whole-board update from the referee rather than separate updates for the cards and the spoons.

So, we have an early architecture mapped out: in addition to the standard plumbing for joining, leaving, and pausing games, we need to have the UI be able to tell the referee that the user is passing a card, that the user is receiving a passed card, that the user is taking a spoon, and that the user is putting a spoon back, and we need to have the referee be able to tell the UI the current state of the table so that the UI can re-draw the table to reflect the current state of the game. The mechanisms used for the UI to tell the referee to perform a players move and for the referee to tell the UI to redraw the current game are called Remote Procedure Calls (or RPC's for short) in the Volity documentation. The software frameworks supporting both the UI and the referee handle the gory details of this, but the programs will still need to send the RPCs at the appropriate time.

So, now we know where we're going. Tune in in future weeks for Steps 0, 2, and beyond.

Monday, May 22, 2006

Setting up shop

Hello, and welcome.

This blog is the complementary blog to the developers' blog at volity.net. (Volity is a new super-nifty open-source casual gaming platform, with nifty things like a Fluxx implementation, and more planned.)

This blog is meant to be a place where people programming games for use with the volity framework can post questions and comments about volity programming, get help troubleshooting, look for collaborators, or publicize their latest and greatest work.

I'm also hoping that some useful example and/or tutorial material will begin
to accumulate here. To that end I intend to spend Wednesdays (wednesdays being the official day to gather, play existing games, and test new games at volity) working towards a working implementation of "Spoons" (also known as "Pig", apparently). People are welcome to collaborate with me on this project, as I will be posting code as I generate it

If you would like to be able to post to the blog, rather than simply commenting on it, please e-mail me at c r a i g k a s (at) m y w a y (dot) c o m. Note that you may need to be a registered Blogger user to actually do so.

One more thing: if and when there is suitable demand, I'll set up a player blog as well (though if the demand exists, I'll see how the nice people at volity feel about web forums first).

That's all for now...

Craig