Scripter
From Jin
The scripter plugin gives users extreme power and flexibility in interacting with the chess server and with other players. It does this by allowing them to write scripts that are run whenever a certain event occurs. You could for example, automatically respond to any tell you receive, send seeks after a game is finished or have the interface notify you when a topic you are interested in is being discussed in a certain channel.
Contents |
Script Types
Jin currently supports two types of scripts - command scripts and beanshell scripts. Command scripts are simpler, but more limited in what they can do. Beanshell scripts require knowing a little programming, but are extremely powerful.
With a command script, you specify the command(s) to be sent to the server, and the exact event when these commands should be sent. The event is identified by specifying an event type, an event subtype and an optional condition, to further narrow down the cases when your commands are sent.
In beanshell script, you specify actual Java code to be run when the script is invoked. Because a condition can be simply expressed in the script's code, a beanshell script only lets you specify the event type and subtype.
Event Types and Subtypes
When you choose the event type, you specify what type of event your script is is intended to "respond" to. In other words, what must happen for Jin to run your script.
The event subtypes selection specifies which of the subtypes of the chosen event type your script will "respond" to. If the selected event type has no subtypes, then no checkboxes will appear and your script will be run whenever an event of the chosen type occurs.
A list of the currently available event types and their subtypes:
- Chat (All types of tells)
- All kinds of tells are categorized as this type. This includes personal tells, channel tells, all kinds of shouts, kibitzes/whispers etc.
Subtypes include:- Personal tell - a regular personal tell, includes tells issued with the "say" command.
- Shout - regular shouts (not sshouts or c-shouts).
- (Bughouse) Partner Tell - tells from your current bughouse partner, issued with the "ptell" command.
- Channel Tell - tells to various channels/rooms.
- Kibitz - kibitzes in games, tells that go to all observers and players in a game.
- Whisper - like kibitzes, but goes only to observers, not players.
- Announcement - announcements made by the server administrators.
- Subtypes specific to the Internet Chess Club (chessclub.com):
- Serious Shout - shouts done with the "sshout" command.
- QTell - Personal tells from Tournament Directors (TDs), such as Tomato, Flash etc.
- Channel QTell - Channel tells from Tournament Directors (TDs), such as Tomato, Flash etc.
- Subtypes specific to the Free Internet Chess Server (freechess.org):
- C-Shout - shouts done with the "cshout" command.
- T-Shout - tournament announcements from mamer and Tournament Managers (TMs)
- Connection
- Events related to the connection of Jin to a chess server.
Subtypes include:- Attempt - Jin is about to attempt connecting to the server.
- Connect - Jin has connected to the server. You may not send commands to the server until login.
- Login - Jin has successfully logged in (the server accepted the username/password). You may now send commands to the server.
- Disconnect - Jin has been disconnected from the server for some reason. You may no longer send commands to the server.
- Seek
- Occur when a seek is posted/withdrawn on the server.
Subtypes include:- Post - a new seek has been posted.
- Withdraw - an existing seek has been removed.
- Game
- Game related events such as game start, moves, clock adjustments etc.
Subtypes include:- Game Start - a new game has started, or you started observing an existing game.
- Move - a move has been made in the game.
- Takeback/Backward - either a takeback has occurred or someone moved backwards in an examined game.
- Board Flip - the board has been flipped (from white-at-bottom to black-at-bottom view, or vice versa).
- Illegal Move Attempt - you've attempted to make an illegal move.
- Clock Update - a change to one of the clocks of the players.
- Other Position Change - a change in the position that can't be (or just isn't) described by a move or a takeback.
- Game End - a game has ended, or you have stopped observing it.
- Text (Unparsed text)
- Any text sent by the server that isn't categorized as any of the other types is automatically categorized as this type.
Condition for Command Scripts
The condition allows you to specify your own custom filter (on top of the event type and subtype selections) which determines when your script is run. When an event of the chosen type and one of the chosen subtypes occurs, it will be subjected to filtering by the condition you specify. If it passes that as well, your script will be run.
The condition must be a valid Java boolean expression. While it may sound a bit scary at first, it is really quite easy - all you have to do is write down a list of simple conditions, such as oppRating > 2000 or gameResult.equals("win"), surround them with round brackets and then connect them with either && or || strings, where && stands for "and" and || stands for "or".
Here are some examples so you see how easy it is:
(myTime > 10) || (oppRating >= 1800)- Means that you get 11 or more minutes on your clock or the opponent's rating must be at least 1800 (or both - "or" in computer languages means at least one of the conditions has to be true - if they are both true, then all the better).
(sender.equals("AlexTheGreat")) && (message.equals("Hello"))- Means that the sender must be AlexTheGreat and the message he sent must be "Hello".
(oppRating > 2300) || (oppTitle.indexOf("GM") != -1)- This is a slightly more complicated example. The first part of the condition is easy - it means that the opponent's rating must be higher than 2300. The second part uses the function
indexOf. That function looks for the specified string ("GM" in our case) inside the string it was called on (oppTitle in our case) and returns the index of its first appearance. More importantly, if it doesn't find the string "GM" inside oppTitle (in our example), it will return -1. Thus what we are checking withoppTitle.indexOf("GM") != -1(where!=stands for "not equal to") is basically that "GM" is a substring of the opponent's title, meaning that he is a Grandmaster (On ICC and FICS, at least). Finally, the two parts are connected with the "or" sign, meaning that the whole expression will be true if at least one of the parts is true. (myTime == 5)- This simple condition requires that you get exactly 5 minutes on your clock at the beginning of a game. It demonstrates the
==(two equal signs) operator whose meaning is "equals to".
Note that if you don't specify a condition, a default condition which always evaluates to true will be generated for you (meaning that the script will always be run if an event of the proper type and subtype occurs).
A list and documentation of the variables (such as oppRating, myTime etc.) you can use when writing scripts for various event types/subtypes, is available below
When you finish writing your script and click the "OK" button, Jin will try to test your condition by evaluating it with dummy values for the variables to make sure that it's valid. Since the variables it uses have dummy values, it may sometimes tell you that the condition is malformed even though it is ok. This should, however, happen very rarely, so make sure to check your condition again before going ahead and telling Jin to use it anyway.
Commands for Command Scripts
The commands are the "meat" of your script. You specify a single command on each line. These will be sent to the server when the script is run, after some processing. The processing allows you to add "variables" inside the commands which are replaced with the "variable" values before the command is sent. Those variables are specified by a dollar sign ('$') followed by the variable name. The processing then looks for this pattern and replaces its occurances with the value of the variable.
Let's look at some examples to get an idea of how it works:
tell Gorgonian Hello- This will simply send the above command to the server.
tell $sender Hello- Assuming that this script is responding to Chat Events (which provide a "sender" variable) with the Personal Tell subtype enabled, and you received a tell from Kiebitz, the command sent to the server will be "tell Kiebitz Hello"
tell $sender What do you mean by "$message"?- This is a funny script I used to test the scripter. Basically this replies to the sender asking him what he meant by his tell to you (or to a channel, or shout, or any other Chat Event subtype you chose). The variable "message" is replaced by the content of the sender's tell.
Note that if you use a variable that isn't defined, it will not be replaced and will be sent as specified, in its "$variable" form.
A list and documentation of the variables (such as sender, message etc.) you can use when writing scripts for various event types/subtypes are available available below
Beanshell Scripts
BeanShell is a Java source interpreter, meaning that beanshell scripts are essentially pieces of Java code. BeanShell, however, also has scripting features which extend (or break, depends on how you feel) the Java language. This means, for example, that you don't have to declare the type of a variable when you use it. You can also hold different types of objects in the same variable at different times. See the BeanShell documentation for additional information.
Your code doesn't start running in a blank environment - you already have a bunch of useful variables and methods defined which you can use. The most useful is the sendCommand(String) method which simply sends the specified string to the server. You can also use various variables whose exact identity and values are determined by the type and subtype of the event that your script is running on. See also the list of the "built-in" functions and variables.
An interesting property of how your BeanShell scripts are executed is that they are stateful - you can save some state (variable values) between separate invocations of the script. Let's look at the following Chat/Personal Tell script, for example:
if (super.count == void)
super.count = 0;
else
super.count++;
if (super.count < 5)
sendCommand("tell fishbait " + super.count);
The first time the script is run, the super.count variable doesn't exist yet, so its value is void and it gets initialized to 0. In consecutive executions, it gets incremented each time and fishbait will receive tells with "0", "1", "2", "3" and "4" etc. (which might annoy him quite a bit, so I recommend trying it on yourself instead ;-)). So, to "keep" a variable between runs of the script, start its name with super..
To understand exactly what's going on, I suggest reading the beanshell tutorial. In short, Jin wraps your BeanShell scripts in a method for performance reasons. The "super" scope modifier allows you to access variables global to the script. If you don't use "super", you will be accessing variables local to the method Jin wrapped your script in and the values would be gone as soon as the method finished executing.
Variables Available to Scripts
Below is a list of variables available for each event type (except Connection which has no special variables).
Chat Events (all types of tells)
- Applies only to the Internet Chess Club (chessclub.com)
- Applies only to the Free Internet Chess Server (freechess.org)
Text Events (unparsed text)
| Variable name | Meaning and explanation | Sample values |
|---|---|---|
| text | The line of text | "You have 4 messages (1 unread).", "There are no new news items." |
Seek Events
- Applies only to the Internet Chess Club (chessclub.com)
- Applies only to the Free Internet Chess Server (freechess.org)
Game Events
- Applies only to the Internet Chess Club (chessclub.com)
- Applies only to the Free Internet Chess Server (freechess.org)
All Events
These variables require fairly intimate understanding of Jin's source code to use
| Variable Name | Meaning and Explanation |
|---|---|
| scripter | The Scripter plugin itself. With this class, you can do anything a plugin can. For more information, see the free.jin.scripter.Scripter API.
|
| prefs | An object that stores user preferences. You can use it to store small bits of information between sessions and runs of Jin. For more information, see the free.jin.Preferences API.
|
| connection | An instance of JinConnection which is responsible for communicating with the server. For more information, see the free.jin.JinConnection class and its implementations - free.jin.chessclub.JinChessclubConnection and free.jin.freechess.JinFreechessConnection.
|
| event | The event that triggered this script to be run. See free.jin.event.JinEvent and its various subclasses.
|
| eventSubtype | The subtype of the event that triggered this script to be run. This is just a string - one of the subtype names you select when defining the script. |
Functions Available to Beanshell Scripts
These are predefined functions that BeanShell scripts can use directly. Of course, they are also free to use the entire Java API and any of Jin's classes/methods. The latter, however, are not guaranteed to keep existing/working between various versions of Jin.
sendCommand(String command)- Sends the specified command/message to the server.
playSound(String path)- Attempts to play the sound file at the specified path. The best format is WAV, but you can try other formats - they may or may not work. Also note that when specifying the file path on Windows, you need to type the backslash twice, like so:
playSound("C:\\tmp\\mysoundfile.wav") exec(String command)- Executes the specified command in the operating system. Calling
exec("notepad")on Windows, for example, will open the notepad application. appendLine(String line)- Appends the specified line to Jin's main console. The style of the text is specified by the "Special" type in console preferences.
Script Collection
Some interesting scripts are described in these articles:
- Subject Watcher - Notifies you whenever a subject you are interested in is being discussed.
- Channel Logger - Logs all channel tells to a file.
- Board Markings (arrows and circles) Manager - Allows adding arrows and circles to the board in examine mode (not relevant for ICC as this functionality is built-in there).
