About

JSPoker is a non-networked single-player game; all your opponents will be (ideally entertaining) computer players. Think the likes of Poker Night at the Inventory.

Playing

JSPoker follows the rules of Five-card draw poker. A house rule is that there is no side pot when a player goes all-in: they may win the entire pot, even if other players continue to raise. A player must also have enough funds to meet the ante and have at least one credit left in reserve to still be in the game.

Very loosely, the game flow is that everyone:

This repeats until all but one player is bankrupt.

Starting the game

Use the "Setup" button to add characters to the game. When you have added enough, hit "Begin". You will "puppet" the first character loaded to play the game. You need to know the URL of a character to load, or use one of the ones from tgchan, an interactive fiction site. The default "Nobody" is a fairly blank slate for you to control.

The roster of players, along with their current (visible) cash, is shown in the top-right. During the showdown, you can also see which cards they were holding.

All control during the game is done in the bottom-right window. When a character is speaking, click the "→" button to continue.

Betting

During the game the bottom-right window shows your current hand, along with a description of its worth and the current pot in its title bar.

You can take several actions:

Max
Bid the most you can, up to the bet limit, or your own means.
Raise
Match the current high bet and add an amount on top typed into the box on the left.
Call
Only go so far as to match the current high bet (e.g. someone else's raise).
Fold
Bow out of this round and forfeit your chance of winning in exchange for not having to contribute any more money to the pot.

Drawing

When the "Change" button appears, click on cards to toggle selection of them (cards which fade out will be discarded and replaced), then click the "Change" button to confirm.

Hint: the game orders your hand automatically so the cards which contribute to any set you may have are leftmost. You therefore probably most want to discard cards on the right.

Creating a character

The only hard requirement of providing a character is that you have somewhere on the web to host files. You will need to be able to serve up a JavaScript file, and almost certainly some images from the same path. While you're developing, you should be able to load them from a file:/// URL just fine. If it's easier, later you can deploy as a single ZIP archive (see below). (All the modern browsers have fairly decent JavaScript consoles if you press F12. Character errors, and a fair bit of helpful trace, should show up there.)

Speech tags and IDs

When a character speaks, they give the game four pieces of information: what they're saying, what they look like when they're saying it, their player list icon (if changed), and some tags.

Other characters can hear when someone speaks some tags, and this allows characters to react to each-other beyond just their actions in the game. You can use them to set up specific chains of banter, or more general announcements ("angry", "despondent", "bolshy") that any character might end up some day reacting to.

Every character has a unique ID. (No doppelgangers!) This lets you know who's speaking or acting, both so you can keep track of them during the game, and so you can spot specific other characters to interact with.

Don't get too chatty. There's poker to play, after all.

The simple way

If you look down a bit at "the powerful way", you'll see that characters are defined as JavaScript classes. The good news is that there's a nice stock class you can build upon which does a lot for you. It can be found in pokercharbase.js.

If you use Extends: PokerCharacterDeclarative, you'll get a character which already plays the game, using the default FlexibleAI with default settings, and getting its personality from some member variables. You don't have to write any real JavaScript code at all, just data structures. It's fairly powerful, and even allows your characters to respond to tags to have inter-character conversations. (TODO: It should allow checking IDs, too.) You can set up sell-to-avoid-bankruptcy stages as well.

A simple character might look like:

declarePokerCharacter({
	Extends: PokerCharacterDeclarative,
	work:   '(unpublished)',
	name:   'Example Bob',
	author: 'LionsPhil',
	icon:   'bobicon.png', // Loads relative to your JS file; 64x64
	say_won_round: [ // This is a JavaScript array (list of things)
		"Victory is mine!",
		"Another triumph for Robert.",
	],
});

You should be able to figure out the rest from the comments in pokercharbase and examples of other characters. (Try looking at my ports of Lagotrope's tgchan Polo/Roaka/Pilon ones. They use a slightly different legacy base, but the only difference is it gives them different AI.)

The powerful way

Ok, here's the technical description. A character's JS file must contain exactly one call to the function declarePokerCharacter(), passing it an anonymous object (hash) of members as per MooTools' Class constructor properties. It shouldn't do anything else. The class it describes must extend from class PokerCharacter. (The "simple" ones are specializations of this already.)

This means that a minimal valid character JS looks like:

declarePokerCharacter({
	Extends: PokerCharacter,
	work:   'Nothing',
	name:   'Nobody',
	author: 'LionsPhil'
});

To give it actual appearance and behaviour, you need to override methods within the class (and possibly some more fields if you want to use default behaviour).

Rather than duplicate that all here, your best bet is to read class PokerCharacter in the source. (Don't worry, it's right near the top and very heavily commented with a focus on how to do this.)

You may find it immensely helpful to use one of the PokerAI implementations to make gameplay decisions. This API is at the bottom of pokercharbase.js and is a subset of the full character one. The default implemenation is FlexibleAI, and there is also the older LagotropeAI available. (You could also write your own, and use it with PokerCharacterDeclarative: just override its getAI() to return an instance.)

You have MooTools Core available, which gives you a fairly hefty library of useful language features. JSPoker runs in strict mode, and I suggest you put your characters in the same if they have any substantial code to them. And don't forget that you can look at existing characters for examples. I have written some at varying complexities. TODO: ...or am in the process of doing so.

(Yes, nothing stops you writing a character who cheats silly, or eats all the diamonds out of the deck, or replaces the whole game with a dating sim where you play the joker and must woo the elusive two of clubs. JavaScript has, at the time of writing, no worthwhile sandboxing to stop you. But don't. It's only funny once [OK, maybe not the dating sim one] and after that people will just stop playing against your character.)

Single-ZIP characters

You can ZIP up a character's JavaScript file and its images into a single archive, and JSPoker will load that directly. There is a caveat if you're doing anything fancy: it directly injects other file resources into your script by matching the quoted filenames. If you want to build up names, e.g. var img = "jena_" + emotion + ".png", you will have to use the regular, bare-files approach.

Advanced topics

Hosting JSPoker

Download and extract the latest JSPoker source. You do not require any special server-side support; just the ability to serve files.

IMPORTANT: Don't host this on a domain where you also have web applications with user authentication. The ability to load arbitrary characters' JavaScript is a XSS/Cross-site request forgery vulnerability otherwise. (See the complexities of cookie scoping.) Logged-in users could impersonate each-other by making them play poker with maliciously-crafted characters.

Providers

JSPoker finds remote characters to list in the setup UI from providers. You can override the default provider with the fragment identifier #provider=URL, which can be specified multiple times. It will be retrieved and run as a script which should call providePokerCharacters(). This API is not yet completely stable, so see the tgchan provider as an example for now.

Autoloading characters

You can create a link to JSPoker which automatically loads a set of characters by appending each as a #character=URL argument. Here is an example which autoloads Nobody. This will skip through any welcome dialogue as characters load.

Deck graphics

Using an argument of #deck=URL will override where JSPoker looks for its deck graphics. It will append card names of the form RS.png to this URL and try to load them as images. R is a rank, so one of 210, J, Q, K, A. S is a suite, so one of C, D, H, S. The reverse of the cards will be loaded as back.png. You cannot currently change the appearance of the minature views in the player list. Decks are not resized and will scale the UI; the default set are 69×96.

License

JSPoker—A JavaScript Computer Poker implementation
Copyright © 2013 Philip Boulain and others

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Stating the obvious

Any character you load from someone else's site is that someone else's problem. Characters go straight from wherever you load them from into your browser and don't pass through my server. I do not distribute them, so am not responsible for offensive/illegal/copyright infringing/etc. content.

Third-party libraries

JSPoker uses MooTools (MIT license) and zip.js (3-clause BSD license). The default deck graphics are rasterized versions of:

Vectorized Playing Cards 1.3 - http://code.google.com/p/vectorized-playing-cards/
Copyright 2011 - Chris Aguilar
Licensed under LGPL 3 - http://www.gnu.org/copyleft/lesser.html