PIMP: the Portable Internet Monopoly Protocol
=============================================

S->A = Server to All clients
S->C = Server to Client
C->S = Client to Server
X->X = Either Client to Server or Server to Client

Player ID 0 is reserved for the server, leaving a maximum of 255
players and observers.

Note: This protocol assumes certain house rules.

Code Ranges
-----------
                                            
0x00 -- 0x0F   Joining game                 
0x10 -- 0x1F   Status of game               
0x20 -- 0x2F   Turn messages                
0x30 -- 0x3F   Property manipulation        
0x40 -- 0x4F   Messages from squares        
0x50 -- 0x5F   Trade: starting              
0x60 -- 0x6F   Trade: setting up            
0x70 -- 0x7F   Trade: concluding            
0x90 -- 0x9F   House construction (including errors)
0x80 -- 0x8F   Informative Cash and Card Changes
0xC0 -- 0xCF   Ownership and other changes  
0xD0 -- 0xDF   Leaving game                 
0xE0 -- 0xEF   Client Errors                
0xF0 -- 0xFE   Errors                       

Message type 0xFF and payload length 255 are reserved for future use.


Reading the Contents column
---------------------------

The fields are the X, Y, Z, W, Q, and N values respectively. Byte
fields usually come first, the player comes first if it is one of the
fields. (One message, PIMP_STATE_PLAYER, has an unusally large number
of fields and does not follow the bytes-first rule.)

bool fields are stored in a byte with the least significant bit
containing the value.

string fields consist of a length byte, then that many bytes of UTF-8
encoded characters. (The length byte is the number of bytes, not the
number of characters. Note that UTF-8 is a varying multibyte
encoding.)

Errors                                                                          CODE CONTENTS
------                                                                          ==== ========

PIMP_ERROR_UNEXPECTED_MESSAGE                                                   0xFE byte
X->X: Unexpected message type X
      Sent when the message that was received is either not expected
      to be sent by that end (e.g. the server sending a handshake
      message) or not expected at that time (e.g. the client saying
      "I'd like to play" out of the blue).

PIMP_ERROR_UNPARSEABLE                                                          0xFD
X->X: Unparseable message
      Sent when the message payload is of an unexpected length.

PIMP_ERROR_INVALID_PAYLOAD                                                      0xFC byte
X->X: Invalid payload in message of type X
      May be sent when the message payload contained an ID (player,
      piece, property, card, square, etc) that wasn't valid.


Handshake
---------

PIMP_HANDSHAKE                                                                  0x00 byte
C->S: Hi, do you speak PIMP version X?
      This can be sent at any time, in order to switch to a higher
      level protocol (if there is one).
      The current version is version 1. There is no version 0.

PIMP_HANDSHAKE_ACKNOWLEDGE                                                      0x01 4 byte unsigned integer
S->C: Hi, yes. We are playing game X.
      The game number must be non-zero.

PIMP_ERROR_UNKNOWN_PROTOCOL                                                     0xF0
S->C: Nope, sorry, I don't speak that protocol.


Joining the game
----------------

PIMP_JOIN                                                                       0x02 byte, bool, string (max length 32)
C->S: I prefer piece X, I'd like to play/observe: Y, my name is Z
      Name must not already be in use and must not be the empty string.

PIMP_QUERY_JOIN_PLAY                                                            0x06 4 byte unsigned integer, string
PIMP_QUERY_JOIN_OBSERVE                                                         0x07 4 byte unsigned integer, string
S=>A: Candidate X with name Y has requested to join/observe, accept?
      As of version 1 of the protocol, the server must only ever have
      one of these queries active at any one time.

PIMP_JOIN_PENDING                                                               0x10
S->C: Hang on, people are voting

PIMP_ACCEPT_JOIN                                                                0x08 4 byte unsigned integer
C->S: Accept candidate X
      Invalid X values are ignored.

PIMP_REFUSE_JOIN                                                                0x09 4 byte unsigned integer
C->S: Refuse candidate X
      Invalid X values are ignored.

PIMP_JOIN_REFUSED                                                               0x0F 4 byte unsigned integer, string
S->A: Candidate X, name Y, was refused

PIMP_ERROR_TOO_MANY_USERS                                                       0xF1
S->C: Too many users already, sorry

PIMP_ERROR_NAME_IN_USE                                                          0xF2
S->C: Name already in use, pick another
      This is also used if the name is inappropriate.

PIMP_ERROR_NOT_WELCOME                                                          0xF3
S->C: You are not welcome.

PIMP_WELCOME_DETAILS                                                            0x03 byte, 4 byte unsigned integer
S->C: You now are player Y, password Z
      Sent instead of 0xF3 in case players accepted. The password is
      the number used to reauthenticate a connection when reconnecting.

PIMP_WELCOME_PLAYER                                                             0x04 byte, byte, string
S->A: Welcome player X, piece Y, name Z
      Implies that player X has a new piece at square 0.
      This will be followed by game state sent to the player.

PIMP_WELCOME_OBSERVER                                                           0x05 byte, byte, string
S->A: Welcome observer X, piece Y, name Z
      This will be followed by game state sent to the observer.


PIMP_REJOIN                                                                     0x0A byte, 4 byte unsigned integer
C->S: I am already in the game as player X, my password was Y

PIMP_WELCOME_BACK                                                               0x0B byte, byte, string, bool
S->C: Welcome back; for the record you are player X, piece Y, name Z, you are playing/observing: W
      This will be followed by game state.
      W is true if playing.

PIMP_ERROR_WRONG_PASSWORD                                                       0xF4
S->C: The provided password is incorrect.
      This can either be replied to by another PIMP_REJOIN, or it can
      be followed by a normal PIMP_JOIN message.


Link Dead
---------

PIMP_PING                                                                       0xD0 4 byte unsigned integer
S->C: Ping? X

PIMP_PONG                                                                       0xD1 4 byte unsigned integer
C->S: Pong: X

PIMP_LINK_DEAD                                                                  0xD2 byte
S=>A: Player X has stopped responding
      Sent if a player times out. Doesn't do anything else though.


Changing Status
---------------

PIMP_KICK                                                                       0xD3 byte
C->S: Kick player X
      Only has an effect if it is that player's turn
      Kick count gets reset when the turn ends

PIMP_PLAYER_BECAME_OBSERVER_KICKED                                              0xDC byte
S->A: Majority of players wanted player X kicked
      Actual resource transfers take place with separate messages.
      Player is made into an observer.

PIMP_TRANSFER                                                                   0xD4 byte
C->S: Transfer everything to player X
      Actual resource transfers take place with separate messages.
      Player 0 means transfer to the bank.

PIMP_ERROR_CANNOT_TRANSFER_DURING_TRANSACTION                                   0xEC 4 byte unsigned integer
S->C: You must complete transaction X before transfering
      If X is zero, then the transaction is merely a pending claim.
      The player need but wait until the next person rolls.
      (PIMP_RENT_COLLECTION_MORATORIUM will be sent then.)

PIMP_PLAYER_TAKEOVER                                                            0x0C byte, byte
S->A: Player X is becoming an active player taking over the piece who
      was player Y
      The sequence of events will be
         PIMP_TRANSFER
         PIMP_PLAYER_TAKEOVER
         PIMP_DELTA_*
         PIMP_PLAYER_BECAME_OBSERVER_TRANSFER
      Implies that player X has the piece player Y had.
      Triggered by using PIMP_TRANSFER.

PIMP_AFK                                                                        0xD5
C->S: I'm away from the keyboard
      This tells the server to ignore this player when it comes to
      votes. Any other message sent from the client will cancel this
      notice (including PIMP_PONG!). This won't stop the player from
      having to play his turn. The server may use this message as
      indication that the player is link dead and send the LINK_DEAD
      message but doesn't need to. This message does not excuse the
      client from any outstanding PIMP_QUERY_JOIN_PLAY/OBSERVE
      messages. Typically followed by the client disconnecting.

PIMP_SWITCH_PLAY                                                                0x0D
C->S: I'd like to play
      Runs through the 0x06, 0x08, 0x09, 0x0F thing with the players,
      but if successful responds to everyone with 0x0E instead of 0x03
      to the requester and 0x04 to everyone.
      Only one candidate per connection at a time is allowed, more
      such messages are silently ignored.

PIMP_OBSERVER_BECAME_PLAYER                                                     0x0E byte
S->A: Player X is becoming an active player
      Implies that player X has a new piece at square 0.

PIMP_PLAYER_BECAME_OBSERVER_TRANSFER                                            0xDA byte
S->A: Player X is becoming an observer
      Result of PIMP_TRANSFER, usually paired with
      PIMP_PLAYER_TAKEOVER unless other player is bank.

PIMP_PLAYER_BECAME_OBSERVER_BANKRUPT                                            0xDB byte
S->A: Player X bankrupt, now become an observer
      Results from PIMP_BANKRUPT_TRANSACTION.

PIMP_PLAYER_WON                                                                 0xDF byte
S->A: Player X wins
      Sent whenever only one person is left in the player state, if
      the last person to leave went bankrupt. (Thus, always and only
      sent after a "Player bankrupt" message.)
      May be followed by the server disconnecting.


Status
------

Upon joining, or upon request, the server can give the client an exact
report of what is going on (in no particular order):

PIMP_REQUEST_STATE                                                              0x11
C->S: Remind me, what's going on exactly?

PIMP_STATE_BOARD                                                                0x12 byte
S->C: We are playing on board X
      This message indicates the start of a state dump.

PIMP_STATE_PLAYER                                                               0x13 byte, byte, string, byte, 4 byte unsigned integer, byte
S->C: User X is a player with piece Y, named Z, on square W with cash Q,
      in jail for the Nth turn
      N=0 if not in jail

PIMP_STATE_OBSERVER                                                             0x14 byte, byte, string
S->C: User X is an observer who prefers piece Y and is named Z

PIMP_STATE_PROPERTY                                                             0x15 byte, byte, bool, byte, byte
S->C: Property X is owned by Y and is Z mortgaged with W houses, Q hotels
     (repeated for each owned property)

PIMP_STATE_CARD                                                                 0x16 byte, byte
S->C: Card X is owned by Y (repeated for each owned card)

PIMP_STATE_POT                                                                  0x1F 4 byte unsigned integer
S->C: The pot is at X
      This message indicates the end of the state dump.

Then, the required set of messages marked "S=>" are sent to the client
to get it quickly to the current state. (The PIMP_QUERY_JOIN_*
messages can be send before the PIMP_STATE_* messages, if that is more
convenient, since they are not dependent on the game state.)


Playing
-------

PIMP_START_OF_TURN                                                              0x20 byte, bool
S=>A: It's now the turn of player X, throw dice if Y
      Y is a boolean. If false, player is probably in jail. Further
      instructions will be forthcoming.

PIMP_THROW_DICE                                                                 0x21
C->S: Throw dice
      Also causes server to send PIMP_RENT_COLLECTION_MORATORIUM if
      appropriate.

PIMP_DICE_ROLLED                                                                0x22 byte, byte, byte
S->A: Player X rolled Y and Z
      Note that this is also sent when rolling to get out of jail.

PIMP_THREE_DOUBLES                                                              0x23 byte (player)
S->A: Player X rolled three doubles

PIMP_DICE_MOVED_PLAYER                                                          0x24 byte, byte, byte
S->A: Player X is moving to square Y due to dice roll totalling Z
      Any bonuses for passing squares, such as Go, will be done
      before the target square bonuses. Z will be zero if the
      destination is jail because of three doubles.

PIMP_CARD_MOVED_PLAYER                                                          0x25 byte (player), byte, byte
S->A: Card Y is sending player X to square Z

PIMP_SQUARE_MOVED_PLAYER                                                        0x26 byte (player), byte, byte
S->A: Square Y is sending player X to square Z

PIMP_PLAYER_PASSING_BY_SQUARE                                                   0x27 byte, byte
S->A: Player X is moving past square Y
      This is purely informative, for clients that want to animate the
      moving person interleaved with the messages from passed squares,
      e.g. Go collection. This message is sent immediately prior to
      entering the square. It is not sent for the last square, the
      next message is instead.

PIMP_PLAYER_LANDING_ON_SQUARE                                                   0x28 byte, byte
S->A: Player X is landing on square Y
      Sent instead of PIMP_PLAYER_PASSING_BY_SQUARE for the last
      square.

PIMP_GOING_TO_JAIL                                                              0x29 byte, byte
S->A: Player X is going to jail on square Y
      Sent after PIMP_THREE_DOUBLES / PIMP_DICE_MOVED_PLAYER,
      PIMP_GOT_CARD / PIMP_CARD_MOVED_PLAYER, or
      PIMP_PLAYER_LANDING_ON_SQUARE / PIMP_SQUARE_MOVED_PLAYER. Will
      be immediately followed by another PIMP_PLAYER_LANDING_ON_SQUARE
      message.

PIMP_WAITING_FOR_TRANSACTION                                                    0x2A byte, 4 byte unsigned integer
S=>A: Player X is involved in transaction Y that is holding up the game

PIMP_CLAIM_RENT                                                                 0x2B byte, byte
C->S: Request payment from player X for landing on property Y
      You have to send this once per time the player landed on it.

PIMP_ERROR_INVALID_RENT_CLAIM                                                   0xE0
S->C: You are not owed rent

PIMP_CLAIM_GO                                                                   0x2C byte
C->S: Request payment from bank for passing square X
      This needs to be claimed once per time you passed/landed on it.

PIMP_ERROR_INVALID_GO_CLAIM                                                     0xE1
S->C: You are not owed salary

PIMP_MONEY_BEING_HELD_IN_ESCROW                                                 0xED byte, 4 byte unsigned integer, 4 byte unsigned integer
S->C: The bank will give player X Z cash once they finish transaction Y

PIMP_RENT_COLLECTION_MORATORIUM                                                 0x2E
S->A: Beyond this stage, rent and go money can no longer be claimed

PIMP_ROLL_AGAIN                                                                 0x2F byte
S->A: Player X needs to roll again


Interactions with the Bank
--------------------------

PIMP_PROPERTY_SALE                                                              0x30 byte (player), byte, 4 byte unsigned integer
S=>A: Property Y available for sale to player X for cash Z

PIMP_BUY_PROPERTY                                                               0x31
C->S: Buy
      The cash and property and transferred in a separate message.

PIMP_ERROR_PROPERTY_TOO_EXPENSIVE                                               0xE2 byte, 4 byte unsigned integer
S->C: You can't afford to buy property X, it costs Y

PIMP_ERROR_PROPERTY_WOULD_REDUCE_NET_WORTH                                      0xEE byte, 4 byte unsigned integer
S->C: You can't buy property X, it would reduce your net worth to below
      what you need in transaction Y

PIMP_AUCTION_PROPERTY                                                           0x32
C->S: Don't buy

PIMP_PROPERTY_AUCTION                                                           0x33 byte
S=>A: Property X is now available for auction

PIMP_BID                                                                        0x34 4 byte unsigned integer
C->S: Bid cash X
      Server will reject this message if the player already has the highest bid.

PIMP_PROPERTY_AUCTION_BID                                                       0x35 byte, 4 byte unsigned integer
S=>A: Player X has bid cash Y

PIMP_NO_BID                                                                     0x36
C->S: Don't bid
      Every player but the winning one must say "Don't bid" for the
      auction to close. Even after saying Don't bid, though, a player
      can bid again if the auction is not yet over.
      Rejected if player has highest bid.

PIMP_PROPERTY_AUCTION_NO_BID                                                    0x37 byte
S=>A: Player X is out of the bidding

PIMP_PROPERTY_AUCTION_WON                                                       0x38 byte
S->A: Auction won by player X
      The property and cash are transferred in a separate message.

PIMP_PROPERTY_AUCTION_VOID                                                      0x39
S->A: Nobody bid on the property.


PIMP_PURCHASE_HOUSES                                                            0x90 byte = n, n times (byte, signed byte, signed byte)
C->S: Buy/sell houses
       Number of properties being changed: X
       Property ID Y: buy Z houses, W hotels (repeated X times)
      Must be sent before PIMP_THROW_DICE or PIMP_CHOICE (when in jail)

PIMP_ERROR_HOUSES_NOT_OWNED                                                     0x91 byte
S->C: You must own the properties to build houses, you do not own X

PIMP_ERROR_HOUSES_NEED_MONOPOLY                                                 0x92 byte
S->C: You must own all the properties to build houses, you do not own X

PIMP_ERROR_HOUSES_MORTGAGED                                                     0x93 byte
S->C: You cannot build on mortgaged properties (property X)

PIMP_ERROR_HOUSES_NOT_COLOUR_GROUP                                              0x94 byte
S->C: You cannot build on railroads or utilities (property X)

PIMP_ERROR_HOUSES_NOT_YOUR_TURN                                                 0x95
S->C: You cannot build when it is your turn

PIMP_ERROR_HOUSES_TOO_EXPENSIVE                                                 0x96 4 byte unsigned integer
S->C: You can't afford to buy those houses, it would cost X

PIMP_ERROR_HOUSES_NO_HOUSE_PIECES_LEFT                                          0x97 byte, byte
S->C: You can't build these houses or hotels, there aren't enough
      pieces left (there are X houses, Y hotels)

PIMP_ERROR_HOUSES_CANNOT_BUILD_THAT_NUMBER                                      0x98 byte
S->C: You can't build that number of houses or hotels on X
      Note that building a hotel requires building 4 houses too

PIMP_ERROR_HOUSES_UNBALANCED                                                    0x99 byte
S->C: You can't buy/sell those houses, it would cause the houses
      to be unbalanced near property X

PIMP_ERROR_HOUSES_WOULD_REDUCE_NET_WORTH                                        0x9A 4 byte unsigned integer
S->C: Buying houses would decrease your net worth, which you can't do
      while in transaction X

PIMP_ERROR_HOUSES_TERMITES                                                      0x9B
S->C: You failed to build the houses, the contruction materials were
      teeming with termites

PIMP_DELTA_HOUSES_PURCHASED                                                     0xC3 byte, byte, byte, byte
S->A: Player X has bought or sold houses on property Y, it now has Z houses
      and W hotels
      The cash is transferred in a separate message.


PIMP_MORTGAGE_PROPERTY                                                          0x3B byte
C->S: Mortgage property X
      Must be owned by the player.

PIMP_DELTA_PROPERTY_MORTGAGED                                                   0xC5 byte
S->A: Property X is now mortgaged
      The cash is transferred in a separate message.

PIMP_UNMORTGAGE_PROPERTY                                                        0x3C byte
C->S: Unmortgage property X

PIMP_DELTA_PROPERTY_UNMORTGAGED                                                 0xC6 byte
S->A: Property X is no longer mortgaged
      The cash is transferred in a separate message.

PIMP_ERROR_MORTGAGE_TOO_EXPENSIVE                                               0xE3 byte, 4 byte unsigned integer
S->C: You can't afford to unmortgage property X, it costs Y

Note: There is no PIMP_ERROR_MORTGAGE_WOULD_REDUCE_NET_WORTH because
we always want to allow unmortgaging. Unmortgaging is often done
before a deal to avoid having to pay the fee twice.


Squares and Tax and Stuff
-------------------------

PIMP_GOT_CARD                                                                   0x40 byte, byte, byte
S=>A: Player X picked up chance card Z at square Y
      This doesn't imply that a card (or cash) was received, only that
      a card was picked up. If the card is kept by the player, or if
      money changes hands, a state change will also be sent. Other
      messages, e.g. PIMP_SQUARE_GIVES_CASH or PIMP_SQUARE_GIVES_CARD,
      may also be sent with more specific details, although it again
      is just informative.

PIMP_CARD_COLLECT_OR_RETRY                                                      0x41 byte
S=>A: Player X has to chose: collect cash or retry

PIMP_CARD_SELECT_COLLECT                                                        0x42
C->S: Collect money
      Results in PIMP_SQUARE_GIVES_CASH

PIMP_CARD_SELECT_RETRY                                                          0x43
C->S: Retry
      Results in PIMP_GOT_CARD again.


PIMP_TAX_SELECT_OPTION                                                          0x45 byte, byte
S=>A: Player X is on income tax Y, do you want to pay 10% or 200$?

PIMP_TAX_PAY_TEN_PERCENT                                                        0x46
C->S: Pay 10%

PIMP_TAX_PAY_FLAT_FEE                                                           0x47
C->S: Pay $200


PIMP_JAIL_PAY_OR_ROLL                                                           0x4A byte, byte, bool
S=>A: Player X is in jail, can roll for Y more turns, can buy houses? Z
      Sent after PIMP_START_OF_TURN. If Y is non-zero, then player
      should send one of the following two messages. Otherwise, player
      must send back PIMP_JAIL_PAY_BAIL. (This is so that the server
      knows when to declare a rent moratorium.)

PIMP_JAIL_PAY_BAIL                                                              0x4B
C->S: Pay bail
      Results in PIMP_TRANSACTION_JAIL_REQUESTED.
      Also causes server to send PIMP_RENT_COLLECTION_MORATORIUM if
      appropriate.

PIMP_JAIL_ROLL_DICE                                                             0x4C
C->S: Roll the dice
      Results in PIMP_DICE_ROLLED and JAIL_FREE, or on the last turn,
      PIMP_TRANSACTION_JAIL_REQUESTED,
      Also causes server to send PIMP_RENT_COLLECTION_MORATORIUM if
      appropriate.

PIMP_JAIL_FREE                                                                  0x4D byte
S->A: Player X is leaving jail


Transactions
------------

Transaction IDs start at 1 for the first one and are given out
sequentially.

Transaction have three steps:
   set up
   finished
   agreed

Each player is in one of these steps at any time. They both start in
set up. They can each say they have finished, at which point they move
up to finished. When they are both finished, they can each say they
agree. Once they both reach agree, the deal is completed. At any
point, either may reopen the deal (by either making a change, sending
an explicit reopen request, or by changing what they own), which sends
that player back to the set up stage, and sends the other player down
to finished if they were at agreed before. At no time can one player
be agreed and the other in set up.


PIMP_TRANSACTION_REQUEST_TRADE                                                  0x50 byte
C->S: Request trade with player X

PIMP_TRANSACTION_TRADE_REQUESTED                                                0x51 4 byte unsigned integer, byte
S=>C: Start cancellable transaction X with player Y
      Sent to both players.

PIMP_TRANSACTION_RENT_REQUESTED                                                 0x52 4 byte unsigned integer, byte, byte, byte, 4 byte unsigned integer
S=>C: Start uncancellabled transaction X with player Y for landing on
      property Z owned by player W with rent of Q
      Sent to both players.

PIMP_TRANSACTION_CARD_REQUESTED                                                 0x53 4 byte unsigned integer, byte, byte, byte, 4 byte unsigned integer
S=>C: Start uncancellabled transaction X with player Y for card Z with
      default payment of Q owed to player W.
      Automatically sent to both players after a player gets an
      appropriate card.

PIMP_TRANSACTION_SQUARE_REQUESTED                                               0x54 4 byte unsigned integer, byte, 4 byte unsigned integer
S=>C: Start uncancellabled transaction X with square Y, with required
      payment of Z

PIMP_TRANSACTION_BANK_REQUESTED                                                 0x55 4 byte unsigned integer, 4 byte unsigned integer
S=>C: Start uncancellabled transaction X with bank for fixed amount Y
      Cash defaults are set in separate messages (i.e. this message
      will be followed up by PIMP_TRANSACTION_SET_CASH or
      PIMP_ERROR_TRANSACTION_TOO_EXPENSIVE).

PIMP_TRANSACTION_JAIL_REQUESTED                                                 0x56 4 byte unsigned integer, 4 byte unsigned integer
S=>C: Start uncancellabled transaction X with bank for fixed amount Y
      _or_ jail card
      Cash defaults are set in separate messages (i.e. this message
      will be followed up by PIMP_TRANSACTION_SET_CASH,
      PIMP_ERROR_TRANSACTION_TOO_EXPENSIVE, PIMP_TRANSACTION_SET_CARD
      or PIMP_ERROR_TRANSACTION_CARD_NOT_OWNED).


PIMP_TRANSACTION_SET_CASH                                                       0x60 4 byte unsigned integer, 4 byte unsigned integer
C->S: Set cash to Y in transaction X

PIMP_ERROR_TRANSACTION_TOO_EXPENSIVE                                            0xE4 4 byte unsigned integer, 4 byte unsigned integer
S->C: You can't afford Y in transaction X
      The "This player" message is sent too, but with the old value.

PIMP_TRANSACTION_CASH_SET                                                       0x61 4 byte unsigned integer, 4 byte unsigned integer
S=>C: This player set cash to Y in transaction X
      This gets sent whenever the value changes, as well as whenever
      the user tries to change it but fails. It also gets sent when
      the user's cash amount changes to less than the previous amount.

PIMP_TRANSACTION_OTHER_CASH_SET                                                 0x62 4 byte unsigned integer, 4 byte unsigned integer
S=>C: Other player set cash to Y in transaction X
      This gets sent whenever the value changes.


PIMP_TRANSACTION_ADD_PROPERTY                                                   0x63 4 byte unsigned integer, byte
C->S: Add property Y to transaction X
      If the property is already added, this does nothing.

PIMP_ERROR_TRANSACTION_PROPERTY_NOT_OWNED                                       0xE5 4 byte unsigned integer, byte
S->C: You don't own property Y in transaction X

PIMP_TRANSACTION_REMOVE_PROPERTY                                                0x64 4 byte unsigned integer, byte
C->S: Remove property Y from transaction X
      Errors from this are ignored.

PIMP_TRANSACTION_PROPERTY_ADDED                                                 0x65 4 byte unsigned integer, byte
S=>C: This player added property Y to transaction X

PIMP_TRANSACTION_PROPERTY_REMOVED                                               0x66 4 byte unsigned integer, byte
S->C: This player removed property Y from transaction X
      Also called when the property is lost in some other way.

PIMP_TRANSACTION_OTHER_PROPERTY_ADDED                                           0x67 4 byte unsigned integer, byte
S=>C: Other player added property Y to transaction X

PIMP_TRANSACTION_OTHER_PROPERTY_REMOVED                                         0x68 4 byte unsigned integer, byte
S->C: Other player removed property Y from transaction X


PIMP_TRANSACTION_ADD_CARD                                                       0x69 4 byte unsigned integer, byte
C->S: Add chance card Y to transaction X
      If the card is already added, this does nothing.

PIMP_ERROR_TRANSACTION_CARD_NOT_OWNED                                           0xE6 4 byte unsigned integer, byte
S->C: You don't own card Y in transaction X

PIMP_TRANSACTION_REMOVE_CARD                                                    0x6A 4 byte unsigned integer, byte
C->S: Remove chance card Y to transaction X
      Errors from this are ignored.

PIMP_TRANSACTION_CARD_ADDED                                                     0x6B 4 byte unsigned integer, byte
S=>C: This player added chance card Y to transaction X

PIMP_TRANSACTION_CARD_REMOVED                                                   0x6C 4 byte unsigned integer, byte
S->C: This player removed chance card Y from transaction X
      Also called when the property is lost in some other way.

PIMP_TRANSACTION_OTHER_CARD_ADDED                                               0x6D 4 byte unsigned integer, byte
S=>C: Other player added chance card Y to transaction X

PIMP_TRANSACTION_OTHER_CARD_REMOVED                                             0x6E 4 byte unsigned integer, byte
S->C: Other player removed chance card Y from transaction X


PIMP_TRANSACTION_FINISH                                                         0x70 4 byte unsigned integer
C->S: Finished setting up transaction X

PIMP_TRANSACTION_FINISHED                                                       0x71 4 byte unsigned integer
S=>C: This player has finished setting up transaction X
      Also sent if we were at the AGREED stage but other player
      reopened.

PIMP_TRANSACTION_OTHER_FINISHED                                                 0x72 4 byte unsigned integer
S=>C: Other player has finished setting up transaction X
      Also sent if other player was at the AGREED stage but we
      reopened.

PIMP_ERROR_TRANSACTION_NOT_SUITABLE                                             0xE7 4 byte unsigned integer, 4 byte unsigned integer
S->C: Transaction X requires a payment of Y
      The offered goods are not enough to satisfy the bank. This is
      only sent for BANK, CARD and JAIL transactions. This is purely
      informative and doesn't affect anything else.

PIMP_TRANSACTION_REOPEN                                                         0x73 4 byte unsigned integer
C->S: Reopen transaction X
      Cancels any agreement. This message is also implied if any of
      the messages in the range 0x60 to 0x6F are used.

PIMP_TRANSACTION_REOPENED                                                       0x74 4 byte unsigned integer
S=>C: This player has reopened transaction X
      Triggered whenever the contents of a transaction are about to
      change when the player has said he has either finished or
      agreed, or if PIMP_TRANSACTION_REOPEN is sent. Local player is
      sent back to the pre-FINISHED stage. Other player is also sent
      back down to FINISHED if he had said he had AGREED.

PIMP_TRANSACTION_OTHER_REOPENED                                                 0x75 4 byte unsigned integer
S=>C: Other player has reopened transaction X
      Triggered whenever the contents of a transaction are about to
      change when the other player has said he has either finished or
      agreed, or if PIMP_TRANSACTION_REOPEN is sent by the other
      player. Other player is sent back to the pre-FINISHED stage.
      Local player is sent down to FINISHED if he had AGREED.

PIMP_TRANSACTION_AGREE                                                          0x76 4 byte unsigned integer
C->S: Agreed to transaction X
      Can only be sent once both users have finished setting up the
      transaction.

PIMP_ERROR_TRANSACTION_PROPERTY_HAS_HOUSE                                       0xE8 4 byte unsigned integer, byte
S->C: Property Y in your transaction X has buildings on it; sell them
      first
      Sent instead of PIMP_TRANSACTION_AGREED, i.e. doesn't agree the
      transaction.

PIMP_ERROR_TRANSACTION_WOULD_REDUCE_NET_WORTH                                   0xE9 4 byte unsigned integer, 4 byte unsigned integer
S->C: Transaction X cannot be sealed because it would reduce the 
      net worth of the player to below the level required to pay
      for transaction Y
      This is purely informative and doesn't affect anything else.
      Sent instead of PIMP_TRANSACTION_AGREED, i.e. doesn't agree the
      transaction. It is only sent to the player in question.

PIMP_TRANSACTION_AGREED                                                         0x77 4 byte unsigned integer
S=>C: This player has agreed to transaction X

PIMP_TRANSACTION_OTHER_AGREED                                                   0x78 4 byte unsigned integer
S=>C: Other player has agreed to transaction X

PIMP_TRANSACTION_FINALISED                                                      0x79 4 byte unsigned integer
S->C: Transaction X finalised
      Sent once both players agree. Followed by ownership changes.

PIMP_BANKRUPT_TRANSACTION                                                       0x7A 4 byte unsigned integer
C->S: Cannot satisfy uncancellabled transaction X: bankrupt
      The server will only accept this if the player really doesn't
      have enough money, including houses and property, and if the
      player doesn't have any other outstanding transactions with
      lower IDs.

PIMP_ERROR_TRANSACTION_NOT_BANKRUPT                                             0xEA 4 byte unsigned integer, 4 byte unsigned integer
S->C: You cannot claim bankrupty from transaction X, because of
      transaction Y
      If Y is zero, then it means the player has enough cash,
      unmortgaged properties, houses, or hotels to raise the funds.

PIMP_TRANSACTION_UNUSUAL                                                        0x7D 4 byte unsigned integer
S=>C: This transaction is unusual
      The transaction has been changed in some way that makes it
      unusual. For example, the cash is not the expected cash.

PIMP_TRANSACTION_CANCEL                                                         0x7E 4 byte unsigned integer
C->S: Cancel transaction X.

PIMP_TRANSACTION_CANCELLED                                                      0x7F 4 byte unsigned integer
S->C: Transaction X cancelled.
      Sent to both players. Also sent if one of the players goes
      bankrupt or becomes an observer.

PIMP_ERROR_TRANSACTION_CANNOT_BE_CANCELLED                                      0xEB 4 byte unsigned integer
S->C: Transaction X cannot be cancelled.
      Sent instead of PIMP_TRANSACTION_CANCELLED, i.e. doesn't cancel
      the transaction.


Informative Cash and Card Changes
---------------------------------

PIMP_SQUARE_GIVES_CASH                                                          0x80 byte (player), byte, 4 byte unsigned integer
S->A: Square Y gives player X cash Z
      This message is purely informative. The cash is transferred in a
      separate message.

PIMP_SQUARE_TAKES_CASH                                                          0x81 byte (player), byte, 4 byte unsigned integer
S->A: Square Y takes from player X cash Z
      This message is purely informative. The cash is transferred in a
      separate message.

PIMP_SQUARE_GIVES_CARD                                                          0x82 byte (player), byte, byte
S->A: Square Y gives player X chance card Z
      This message is purely informative. The card is transferred in a
      separate message.

PIMP_SQUARE_TAKES_CARD                                                          0x83 byte (player), byte, byte
S->A: Square Y takes from player X card Z
      This message is purely informative. The card is transferred in a
      separate message.

PIMP_CONSTRUCTION_TAKES_CASH                                                    0x84 byte (player), 4 byte unsigned integer
S->A: Player X spends Y on houses
      This message is purely informative. The cash is transferred in a
      separate message.

PIMP_DESTRUCTION_GIVES_CASH                                                     0x85 byte (player), 4 byte unsigned integer
S->A: Player X received Y for selling houses
      This message is purely informative. The cash is transferred in a
      separate message.

PIMP_PLAYER_CLAIMED_RENT                                                        0x86 byte (player), byte, byte, 4 byte unsigned integer
S->A: Player X claimed rent from player Y for property Z costing Q
      This message is purely informative. The cash is transferred in a
      separate message.

PIMP_PLAYER_CLAIMED_GO                                                          0x87 byte (player), byte, 4 byte unsigned integer
S->A: Player X claimed salary for square Y, amount Z
      This message is purely informative. The cash is transferred in a
      separate message.


Ownership Changes
-----------------

PIMP_DELTA_CASH                                                                 0xC0 byte, byte, 4 byte unsigned integer
S->A: Cash Z has gone from player X to player Y
      This is sent _whenever_ a player's cash amount changes.

PIMP_DELTA_PROPERTY                                                             0xC1 byte (player), byte (player), byte
S->A: Property Z has gone from player X to player Y

PIMP_DELTA_CARD                                                                 0xC2 byte (player), byte (player), byte
S->A: Card Z has gone from player X to player Y

PIMP_DELTA_BANK                                                                 0xC4 byte, byte
S->A: The bank has X houses and Y hotels

PIMP_DELTA_POT                                                                  0xCF 4 byte unsigned integer
S->A: Pot has changed to X


Packet Design
-------------

All data is transmitted big endian (network byte order).

It is expected that all PIMP connections be tunneled through SSL to
prevent packet sniffing and packet spoofing.


PIMP version 1 packets consist of a two byte header followed by a
variable length payload. The first header byte is the message type,
the second byte is the length of the payload.

The payload may be empty (length zero). It may be longer than the
length required by the message, up to a maximum of 254 bytes. Thus the
longest possible packet is 256 bytes.

Content Length value 255 is reserved for future use.

   +-----------------+-----------------+--- - - -
   | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | payload
   +-----------------+-----------------+--- - - -
            ^                 ^
            |                 |
            |                 +---- Payload length
            |
            +---------------------- Message Type ID


SAMPLE CONNECTION

Here are the first three messages of a PIMP connection.

C->S: Hi, do you speak PIMP version X?

   The length of the C->S handshake message payload is 1 byte (the
   protocol version). The message type is 0, and the protocol version
   is currently 1.

   Therefore the handshake message is 0x00 0x01 0x01:

     0x00: The message ID is 0.
     0x01: The length of the message payload is 1.
     0x01: The version number is 1.


S->C: Hi, yes. We are playing game X.

   This is replied to by the ack message from the server, which
   contains a game ID, 4 bytes, e.g.: 0x01 0x04 0xA9 0x3F 0x91 0x0E.


C->S: I prefer piece X, I'd like to play/observe: Y, my name is Z

   The message ID, the length of the payload, the piece ID, the
   boolean, the length of the string, and the string.

   0x02 0x07 0x02 0x01 0x04 'k' 'e' 'r' 'z'


Piece Designation
-----------------

The player with name "kerz" should always be identified by a car
piece, and "pavlov" always by a donkey.

Piece IDs are board dependent.


Boards
------

BOARD 0

The standard US Monopoly board.

Squares
  00 = Go
  01 = Mediterranean Avenue (00)
  02 = Community Chest
  03 = Baltic Avenue (01)
  04 = Income Tax
  05 = Reading Railroad (02)
  06 = Oriental Avenue (03)
  07 = Chance
  08 = Vermont Avenue (04)
  09 = Connecticut Avenue (05)
  10 = Jail
  11 = St. Charles Place (06)
  12 = Electric Company (07)
  13 = States Avenue (08)
  14 = Virginia Avenue (09)
  15 = Pennsylvania Railroad (10)
  16 = St. James Place (11)
  17 = Community Chest
  18 = Tennessee Avenue (12)
  19 = New York Avenue (13)
  20 = Free Parking
  21 = Kentucky Avenue (14)
  22 = Chance
  23 = Indiana Avenue (15)
  24 = Illinois Avenue (16)
  25 = B & O Railroad (17)
  26 = Atlantic Avenue (18)
  27 = Ventnor Avenue (19)
  28 = Water Works (20)
  29 = Marvin Gardens (21)
  30 = Go To Jail
  31 = Pacific Avenue (22)
  32 = North Carolina Avenue (23)
  33 = Community Chest
  34 = Pennsylvania Avenue (24)
  35 = Short Line (25)
  36 = Chance
  37 = Park Place (26)
  38 = Luxury Tax
  39 = Boardwalk (27)

(Number in parentheses is the corresponding property ID.)

Properties
  00 = Mediterranean Avenue (Purple)
  01 = Baltic Avenue (Purple)
  02 = Reading Railroad (Railroad)
  03 = Oriental Avenue (Light Blue)
  04 = Vermont Avenue (Light Blue)
  05 = Connecticut Avenue (Light Blue)
  06 = St. Charles Place (Pink)
  07 = Electric Company (Utility)
  08 = States Avenue (Pink)
  09 = Virginia Avenue (Pink)
  10 = Pennsylvania Railroad (Railroad)
  11 = St. James Place (Orange)
  12 = Tennessee Avenue (Orange)
  13 = New York Avenue (Orange)
  14 = Kentucky Avenue (Red)
  15 = Indiana Avenue (Red)
  16 = Illinois Avenue (Red)
  17 = B & O Railroad (Railroad)
  18 = Atlantic Avenue (Yellow)
  19 = Ventnor Avenue (Yellow)
  20 = Water Works (Utility)
  21 = Marvin Gardens (Yellow)
  22 = Pacific Avenue (Green)
  23 = North Carolina Avenue (Green)
  24 = Pennsylvania Avenue (Green)
  25 = Short Line (Railroad)
  26 = Park Place (Dark Blue)
  27 = Boardwalk (Dark Blue)

Cards
  00 = Advance to Go (Collect $200)
  01 = Advance to Illinois Ave.
  02 = Advance token to nearest Utility. If unowned, you may buy it from the Bank. If owned, throw dice and pay owner a total ten times the amount thrown.
  03 = Advance token to the nearest Railroad and pay owner twice the rental to which he/she is otherwise entitled. If Railroad is unowned, you may buy it from the Bank. (first)
  04 = Advance token to the nearest Railroad and pay owner twice the rental to which he/she is otherwise entitled. If Railroad is unowned, you may buy it from the Bank. (second)
  05 = Advance to St. Charles Place; if you pass Go, collect $200
  06 = Bank pays you dividend of $50
  07 = Get out of Jail free; this card may be kept until needed, or sold (*)
  08 = Go back 3 spaces
  09 = Go directly to Jail; do not pass Go, do not collect $200
  10 = Make general repairs on all your property; for each house pay $25, for each hotel $100
  11 = Pay poor tax of $15
  12 = Take a ride on the Reading; if you pass Go collect $200
  13 = Take a walk on the Boardwalk; advance token to Boardwalk
  14 = You have been elected chairman of the board; pay each player $50
  15 = Your building and loan matures; collect $150
  16 = Advance to Go (Collect $200)
  17 = Bank error in your favor; collect $200
  18 = Doctor's fee; Pay $50
  19 = From sale of stock you get $45
  20 = Get out of Jail free; this card may be kept until needed, or sold (*)
  21 = Go to Jail; go directly to Jail; Do not pass Go, do not collect $200
  22 = Grand opera opening; collect $50 from every player for opening night seats
  23 = Income tax refund; collect $20
  24 = Life insurance matures; collect $100
  25 = Pay hospital $100
  26 = Pay school tax of $150
  27 = Receive for services $25
  28 = Xmas fun matures; collect $100
  29 = You are assessed for street repairs; $40 per house, $115 per hotel
  30 = You have won second prize in a beauty contest; collect $10
  31 = You inherit $100

Cards 00-15 are Chance cards, cards 16-31 are Community cards.

Cards marked (*) can be used in a PIMP_TRANSACTION_JAIL_REQUESTED
transaction to pay for bail.

Pieces
  0x00 = any
  0x01 = Bag of money
  0x02 = Battleship
  0x03 = Cannon
  0x04 = Dog
  0x05 = Horse & Rider
  0x06 = Iron
  0x07 = Race Car
  0x08 = Shoe
  0x09 = Thimble
  0x0A = Top Hat
  0x0B = Wheelbarrow
