How to set up tsh for your particular tournament.
Updated Mon Nov 19 10:47:12 EST 2007 for tsh 3.210.
After you’ve installed tsh, you need to set up a subfolder (directory) of your tsh folder containing a configuration file (“config.tsh”, formerly known as “tsh.config”) describing your tournament, and one (“.t”) data file for each division. You can run as many tournaments as you like with one installation of tsh, but each one should have its own folder.
You need to have a text file called “config.tsh” in your tournament folder/directory. You can ask me (John Chew, jjchew@math.utoronto.ca) to create one for you if you give me a few weeks’ notice. There are also a few sample tournaments that come with the tsh distribution, and you can try modifying one of their configuration files to make your own.
Your configuration file consists of a sequence of lines. The order of the lines sometimes matters: you may run into trouble if you try to specify the properties of a division before you declare its existence. The first word on a line determines its type, of which there are currently six:
Here is a very short sample “config.tsh” file.
# This is a comment because it starts with a '#'. # The next line that you will store the data for Division a in file a.t. division a a.t # The next line says that for prize purposes the division is subdivided # into three classes classes a 3 # The next line says that you want to keep track of 1sts/2nds (starts/replies) config track_firsts = 1 # The next line says that Division A will play a simple round robin autopair a 0 1 rr a # The next line demonstrates the 'perl' command perl print "Hello, world\n";
The following subsections discuss each type of line in detail.
Comments begin with a ‘#
’.
You may add as many comments as you like to your configuration file, and it’s a good idea to be verbose so that the next person who runs your tournament for you will know what you were thinking.
Your configuration file must contain at least one division declaration,
beginning with the word ‘division
’,
then followed by a space, a case-insensitive division name,
another space, and a filename.
Filenames may or may not be case-sensitive depending on your operating system.
You may have as many divisions as you like, but each one has to have its
own division name and file name.
All divisions should play the same number of rounds at roughly the
same schedule; if not, you should set up separate directories and
configuration files for differently scheduled divisions, and run
separate copies of tsh.
If you have only one division in your tournament, it does not matter what you name it, and you won’t ever have to type its name. If you do type its name, some older commands may give you cryptic error messages. If you have more than one division, you should keep your division names short as you will be typing them frequently.
Your configuration file may contain one or more class declarations,
beginning with the word ‘classes
’,
then followed by a space, a case-insensitive division name,
another space, and an integer greater than 1.
Classes are typically used to award
prizes to deserving lower-ranked players in a division.
If you specify how many classes a division has, then players will be assigned to equal-sized classes according to their pretournament ranking. Classes are named ‘A’, ‘B’, ‘C’... and are listed in the ratings and standings reports.
There are a number of configuration options that you can set using lines
beginning with the “config
” keyword.
Perl hackers should note that “config
whatever” results simply
in the evaluation of “$config::whatever
” others should ignore
this sentence.
Here are all currently available configuration options:
Option | Example | Description |
---|---|---|
allow_gaps | allow_gaps = 1 | If this option is specified, tsh will let you leave unassigned gaps in the pairing schedule. Don’t specify it unless you have a good reason to do so, such as running a Human vs Computer tournament where you have to schedule a large number of future byes. |
alpha_pair_page_break | alpha_pair_page_break = 15 | tsh will force a page break after this many rows (defaulting to 10) are shown in two-column alpha pairings. If you choose a value that is too small, then some rows may be split across pages and hard to read. |
assign_firsts | assign_firsts = 1 | Have tsh randomly determine who goes first when players would otherwise have to draw. |
autopair | Set using the autopair instruction. It’s not a good idea to mess with this directly. | |
backup_directory | backup_directory = './notold/' | Override the default “./old/” as a place to keep journalled “.t” files. Must end with a “/” or other locally appropriate path separator. |
board_stability | board_stability = 1 | If set to 1 , try to keep one of the two players in each game at the same board in the next round during sessions (if you do not specify “config session_breaks ” the entire tournament is treated as a single session). If not set, boards will be reassigned each round to place high-ranked players at low-numbered boards. |
bye_spread | bye_spread = 75 | Defaults to 50 unless “realm = 'absp' ”. Sets the number of points of spread awarded to a player who is assigned a bye. You should probably adjust the value of “realm ” rather than change this directly; contact John Chew if this is not possible. |
check_by_winner | check_by_winner = 1 | Instructs the “CheckRoundScores ” command to sort rows by winning player rather than starting player. |
colour | colour = 'no' | Enables use of ANSI colour escape sequences to highlight text in the tsh session. |
colour = 'yes' | ||
director_name | director_name = "John Chew" | Used to identify the tournament director, particularly when submitting ratings data. |
entry | entry = "spread" | Used to specify data entry mode. Default value is "scores", where you enter scores; the only other possible value is "spread", where you enter spread. |
event_date | event_date = "September 30, 2005" | Used to specify the event date, particularly when submitting ratings data. |
event_name | event_name = "Toronto 2005" | Used to identify the event, particularly when submitting ratings data. |
exagony | exagony = 1 | If used, prevents players from the same team from facing each other in KOTH and NewSwiss pairings. See also the “team ” extension field. |
external_path | external_path = ['./bin','../bin'] | Used to specify where external commands can be found. Default value is ['./bin']. |
flight_cap | flight_cap = 'TSH::PairingCommand::FlightCapNSC' | Lets you override the default algorithm for capping the number of players who can be considered in contention when using the Chew pairing algorithm. Talk to John Chew if you need to adjust this. The example given is suitable for a tournament which is used to select two finalists. This parameter is also used in estimating pairings flights when choosing an opponent for a Gibsonized player. |
force_koth | force_koth = 1 | When using default pairings, makes the last round be KOTH with unlimited repeats, rather than Chew pairings. |
gibson | gibson = 1 | Enable automatic detection of Gibson situations. When using default or Chew pairings, tsh always looks for possible Gibson situations. When using automatic pairings, tsh does or does not check depending on the value of this option. |
gibson_groups | gibson_groups{'A'} = [[1,2]] | Indicates final ranks that are to be considered equivalent when testing for Gibsonization. Works only with Chew pairings. If not specified, each final rank is considered to be of different value to a player. The example given should be used where the current event is a preliminary to qualify players for a two-player final match and it doesn’t matter whether a player finishes first or second. In the unlikely event that you wanted to have players ranked 3 through 6 compete in a separate final match, you could specify the value “[[1,2],[3,4,5,6]] ”. |
html_directory | html_directory = '/Library/WebServer/Documents/myevent/tsh/' | Override the default “./html/” as a place to keep round-by-round “.html” reports. Must end with a “/” or other locally appropriate path separator. The example given places reports on the local machine’s public web server under OS/X. |
html_in_event_directory | html_in_event_directory = 1 | Stores an extra copy of printable HTML reports directly in the event directory, where they may be easy to find, but may cause clutter. Note that player photos will not be correctly linked in event directory web pages unless you manually copy the photo directory into the event directory as well. |
html_top | html_top = '<p align=center><a href="event url"><img src="event logo"></a></p>' | If defined, appears between the body and h1 tags at the top of each HTML page. |
initial_exagony | initial_exagony = 1 | If used, prevents players from the same team from facing each other in first-round random pairings. See also the “team ” extension field. |
initial_random | initial_random = 1 | When using Chew pairings either explicitly or as the default pairing algorithm, specifies one initial round of random pairings, as required at the WSC. |
initial_schedule | initial_schedule = 3 | When using Chew pairings either explicitly or as the default pairing algorithm, it is often useful to start with a semirandomized fixed schedule generated by the InitFontes command. This parameter (which defaults to zero) specifies the number of rounds that that schedule should run. |
manual_pairings | manual_pairings = 1 | Use neither auto-pairings even if configured, nor Chew pairings in the absence of auto-pairings. Deprecated in favour of “pairing_system = 'manual' ”. |
max_name_length | max_name_length = 22 | Specify minimum width of name fields, may get automatically increased by the presence of longer names in a “.t” file. |
max_div_rounds | max_div_rounds{'A'} = 12 | Like “config max_rounds but applies only to one division. If you only specify the maximum number of rounds in some divisions, the largest value you give is assumed for the rest. |
max_rounds | max_rounds = 12 | Specify the last round in the tournament. Used in Gibson detection, and to check for illegal round numbers in commands. |
name_format | name_format = "%-22s" | Specify sprintf(3) formatting of player names. |
no_ranked_pairings | no_ranked_pairings = 1 | Do not show ranked pairings in “ShowPairings ”, only alphabetical ones. |
no_show_last | no_show_last = 1 | Do not show information about the last round’s results in “RoundRATings ” or “RATings ”. Use if you find the information too cluttered or hard to understand. |
no_text_files | no_text_files = 1 | Do not create text versions of reports. Useful if you only want HTML files, and don’t want your directories cluttered with text files. |
pairing_system | pairing_system = 'auto' | Explicitly declares that automatic pairings should be used; not necessary if au. |
pairing_system = 'chew' | Explicitly declares that Chew pairings should be used; the default value. | |
pairing_system = 'manual' | Explicitly declares that Manual pairings should be used; is equivalent to “manual_pairings = 1 ”. | |
pairing_system = 'nast' | Specifies the use of NAST pairings. | |
pair_page_break | pair_page_break = 15 | If this option is specified, tsh will force a page break after this many rows are shown in rank-ordered (not alpha) pairings. If this option is not used, player names may be split across page breaks. |
player_number_format | player_number_format = "#%s" | Specify sprintf(3) formatting of player numbers. By default, a "#' is prepended to the number for clarity if there is only one division. |
player_photos | player_photos = 1 | If specified, display photos of opponents in alpha pairings reports. |
port | port = 7777 | If this is set to a nonzero value, tsh will use its web interface instead of its command-line interface. Still in early development and incomplete but feel free to see what is there so far. |
prize_bands | prize_bands{'A'} = [2,3,4,5] | Specifies which final ranks are to be considered equivalent for pairings purposes: the numbers given mark the end of each band (range) of equivalent prizes (ranks). Only used in Chew pairings, which try to pair players who are in contention for one prize band with each other. In the example, the top prize band goes from 1st place to 2nd place (presumably because the top two finalists qualify for a playoff); each of 3rd, 4th and 5th place is its own prize band (presumably awarding players cash prizes); and everything from 6th place on is the last prize band (presumably winning nothing). If this option is omitted when required, a warning is displayed and a default value is assigned which assumes prizes are assigned to the top quarter of the division. Note that Gibsonization won’t work with a value of “[1] ”, because the “highest ranked player out of contention for prize money” that the Gibsonized player ought to play ends up being the second-ranked player. |
prizes | currently too complex to document | Specifies the structure of prizes for the “PRiZes ” command. |
rating_system | rating_system = 'absp' | If set to 'absp' , computes ABSP ratings instead of NSA ratings in the “RATings ” command. If set to 'nsa lct' enables local club tournament ratings multipliers. Also affects the way pretournament ratings are used to influence the scores generated by the “RANDomscores ” command. Must be set when using the “SUBMIT ” command. |
ratings_note | ratings_note = "Please rate this after the early bird." | Specifies a note to include when submitting ratings data. |
realm | realm = 'absp' | Specifies default values for several parameters:
“alpha_pair_page_break = 10000 ”,
“bye_spread = 75 ”,
“entry = 'spread' ”,
“rating_system = 'absp' ”,
“surname_last = 1 ”,
“table_method = 'consecutive' ”,
and also uses the ABSP-specific version of the ‘tsh.css’ CSS style sheet and specifies the use of ABSP-specific terminology.
|
realm = 'nsa' | Specifies default values for several parameters:
“bye_spread = 50 ”,
“entry = 'scores' ”,
“rating_system = 'nsa' ”,
and also uses the NSA-specific version of the ‘tsh.css’ CSS style sheet and specifies the use of NSA-specific terminology.
This is the default value of this option. | |
realm = 'sgp' | Specifies default values for several parameters:
“alpha_pair_page_break = 100005 ”,
“bye_spread = 50 ”,
“entry = 'scores' ”,
“rating_system = 'nsa' ”,
“surname_last = 1 ”,
and also uses the Singapore-specific version of the ‘tsh.css’ CSS style sheet and specifies the use of Singapore-specific terminology.
| |
reserved | reserved{'P'}[13] = 4 | Permanently assigns player P13 to board 4. Typically used when you have a player with special needs. |
rotofile | rotofile = 'roto.txt' | Specify the name of a rotisserie pool file to be used in producing U.S.-style rotisserie pool reports. |
save_interval | save_interval = 10 | Specifies how often results should be saved to disk in “Addscore ”. Defaults to every ten new entries. |
session_breaks | session_breaks = [3,6,8,11,12] | Specifies after which rounds there is enough time in the schedule to wait for all results to come in before computing pairings. Used when the “ChewPair ” is automatically invoked. |
show_divname | show_divname = 1 | Show division names in report headings even when you have only one division. Use this if you have to split a tournament into different tsh events because you have more than one computer for data entry, but you want to be able to tell which reports came from which division. |
show_teams | show_teams = 1 | Show team names with player names. |
sort_by_first_name | sort_by_first_name = 1 | Sort players by first name (when names are being presented in "given_names surnames" order). |
spitfile | spitfile{'A'} = 'spita.txt' | Specify the name of a rotisserie pool file to be used in producing U.K. rotisserie pool reports for a given division. |
split1 | split1 = 9 | Specifies after which round a long tournament should be split-rated when using Elo ratings. (This option is no longer needed, and is therefore deprecated.) |
surname_last | surname_last = 1 | If specified, raw names of the form ‘surnames, given names’ in ‘.t’ files are translated to ‘given names surnames’ whenever displayed. |
table_format | table_format = '%3s' | sprintf(3) description of how table numbers are formatted. |
table_method | table_method = 'consecutive' | If set to 'consecutive', assigns boards to table numbers consecutively across divisions. If left unset, or set to the default value of 'none', does not assign boards to tables automatically. |
table_title | table_title = "Room" | Specify what tables are called in titles. The default value is "Table". |
tables | tables{'A'} = [1,1,2,2,3,3,4,4,5,5] | List which board is at which table. Division name must be capitalized. If you don’t give information for enough boards, you’ll get cryptic error messages. You may use Perl expressions like 1..20 or map { $_, $_ } 1..20 to save typing. |
track_firsts | track_firsts = 1 | Make tsh care about who played first and second in each game. If this option is set and assign_firsts is not set, tsh will use the order in which scores are entered to determine who played first, and complain if the wrong player did. If this option is set and you use Chew pairings, the pairing algorithm will have a weak preference for pairing players due to go first with players due to go second. |
tsh has a number of pairings commands, each of which adds one or more rounds of who-plays-whom information to the player data (“.t”) files. Pairing information must be entered before scoring information: the score entry command will not accept scores for players whose opponents are not yet known to the program. You should be familiar with the contents of the section on pairing theory and have decided on one or more of the pairing systems described in that section for your tournament before reading further.
There are four ways of telling tsh what kind of pairings to use: default, automatic, NAST and manual pairings.
With default pairings the only thing you need to tell tsh is how many rounds your tournament is:
# The following config.tsh line says that this tournament has 12 rounds. config max_rounds = 12
After you enter the results for each round, ask tsh
for the next round’s pairings using the
“ShowPairings
” command
and it will compute
Chew pairings.
(If the number of rounds is large compared to the number of players,
one or more round robins will be scheduled first.)
The following
configuration options
can be set to control how
these
default pairings work.
See the detailed description of
configuration options
for their syntax.
Option | Effect | Usefulness |
---|---|---|
flight_cap | If set, overrides the cap on the size of the top flight. | Do not use, unless you are a pairings wizard. |
force_koth | If set, the last round will be KOTH even when default pairings are being used. | You might want to use this, if your (likely North American players) will rebel at the thought of a tournament that doesn't end in a KOTH. |
initial_schedule | If set, specifies a number of initial rounds that will be paired in a fixed schedule. | It's not a bad idea to set this if you have the number of players is much larger than the number of rounds, or if you want to give yourself some breathing space early in your tournament. |
max_rounds | Specifies the length of the tournament in rounds. | Required. |
pairing_system | Explicitly set to indicate which of 'auto', 'chew', 'manual' or 'nast' pairings you want. | Required when using NAST pairings, optional otherwise. |
prize_bands | Should be set to indicate which final ranks are equivalent. If you do not set it, you will be warned that you have not set it each time pairings are calculated. | Strongly advised. |
session_breaks | If set, pairings may be calculated based Fontes-style on the second preceding round’s scores during sessions. If not set, pairings will only be calculated once the immediately preceding round’s scores have all been entered. | Strongly advised. |
If you prefer to have more control over your tournament’s pairings, or have advertised the use of a specific system that is not the tsh default, you should use automatic pairings. This involves pre-entering all the pairings commands that you expect to use into the configuration file, where they will be automatically triggered when the time is right.
Each
auto-pairing configuration
line consists of the command word “autopair
”,
a division name, the number of the round whose results must all
be in before pairings can be calculated, the number of the round
whose pairings will be calculated, and then a tsh command that
generates the pairings.
For example, you can tell tsh that the first seven rounds of your two-division event is a round-robin, and the eighth round is a king-of-the-hill (KOTH):
# When Div. A has no scores and needs Rd. 1 pairings: RoundRobin A autopair a 0 1 rr a # When Div. B has no scores and needs Rd. 1 pairings: RoundRobin B autopair b 0 1 rr b # When Div. A has Rd. 7 scores and needs Rd. 8 pairings: # KOTH with one repeat allowed based on Rd. 7 standings, Division A autopair a 7 8 koth 1 7 a # When Div. B has Rd. 7 scores and needs Rd. 8 pairings: # KOTH with one repeat allowed based on Rd. 7 standings, Division B autopair b 7 8 koth 1 7 b
When you ask for the first round’s pairings tsh will compute the round-robin, then later on when you have entered scores for the first seven rounds you can ask tsh for the eight round’s pairings and it will compute the KOTH. If you ask for Round 8 pairings before all results are in for Round 7, tsh will remind you that it can’t compute them yet.
Here’s a slightly more complicated example, for a six-round
two-division tournament where the first three rounds are paired
using the
“InitFontes
” command,
the next two are paired Swiss based on Round 3 standings
but with no repeats, and
the last is a KOTH based on Round 5 standings with repeats permitted:
autopair a 0 1 if 3 a autopair a 3 4 ns 0 3 a autopair a 3 5 ns 0 3 a autopair a 5 6 koth 1 5 a autopair b 0 1 if 3 b autopair b 3 4 ns 0 3 b autopair b 3 5 ns 0 3 b autopair b 5 6 koth 1 5 b
As explained in the next section, you might still need to resort to manual pairings even when you have planned on using automatic pairings.
You should use NAST pairings if you are directing a satellite event of the North American Scrabble Tour, which has specific requirements for the pairings of such events. The exact system depends on the number of players in the tournament, and consists of either four rounds of fixed pairings and one round of Swiss pairings or five rounds of fixed pairings, followed by one round of KOTH pairings.
You should use manual pairings if you do not know in advance exactly how you will be pairing the tournament, such as when you haven’t decided when to start allowing repeats.
You might also find during your tournament that the automatic system you specified is impossible. For example, you might have asked for a round-robin followed by a KOTH with no repeats. You can quit tsh, edit the automatic pairing instructions and then try again, but if you’re under time pressure you’ll likely prefer to just enter the pairings commands directly and manually.
Experienced thrill-seekers may also add lines to the “config.tsh” file
which begin with the keyword
“perl
”. This is about as safe as using
the tsh shell command
“eval
”, and does the same thing: it evaluates
its argument as a string.
There is currently no good reason for using this feature.
A “.t” file contains all the information for a division, and must be in the same subdirectory as your “config.tsh” file. It’s a text file that can be edited with a text editor if need be, and is usually created in the first place using a text editor. You may have received “.t” files for your tournament with your tsh distribution, but you should be familiar with the content of this section in case of no-shows and walk-ins.
There is an experimental script for importing data from TourneyMan files. It’s called “parsetm”, is found in the “util/” directory and can be invoked from the command-line to turn one “.ltm” file at a time into a “.t” file. It has been thoroughly tested on the version of TourneyMan to be used at the 2005 US NSC.
A “.t” file should contain one line per player. The line should look something like this:
Chew, John 1850 400 450 350; 10 4 3; p12 1 2 2; board 1 1 3
In this example, a player named John Chew entered the tournament with a rating of 1850. In round 1, he played player #10 and scored 400 points. In round 2, he played player #4 and scored 450 points. In round 3, he played player #3 and scored 350 points. He went first in round 1 and second in rounds 2 and 3. He played at board #1 in rounds 1 and 2, and at board #3 in round 3. Anywhere where there is a space on the line, tsh will tolerate as many spaces as you like, but please do not use tabs. Of course, adding spaces within a player’s name will make many reports look odd.
Scores and opponent numbers may have the special value
“00
”,
indicating that the value
has not yet been assigned.
This should not be confused with the
“0
”
that indicates a bye.
Players must be listed in order of player number, beginning with player number 1. Note that this means that players must be numbered within each division starting at 1. Unless you feel strongly otherwise, you should number players beginning with the highest-rated. If you want to number players in two divisions in one numbering system without restarting from 1 at the top of the second division, you must call the two divisions one division for data entry purposes.
When you first set up a tournament file, it will probably contain only player names and ratings. So your file will look something like:
Chew, John 1850 Saint John, Sherrie 1300 Chew, Kristen 1200
Player names may include any characters other than semicolons, and must not end in a digit. If you really have to have a player name that ends in a digit (it has happened), put a comma after the final digit and the comma will be silently omitted in reports. Player names should be entered as shown above, with the surname (last name) first followed by a comma. If you do not do so, a few commands which need to know how to split names into given names (first names) and surnames will not function.
Not all files contain the same information for players. Some information only appears if some optional features are enabled. Each set of optional data is preceded by a semicolon and an identifying keyword. At present, the following extensions are in use:
Keyword | Data |
---|---|
board |
Lists at which board the player played in each round.
This is typically set by the “ShowPairings ”
command the first time pairings for the round are shown, and
not changed thereafter.
|
cume | Is present if the player’s cume must be set to a given value. It should be used with extreme caution, as it will override the regular calculation of cume in all rounds. This feature is not yet fully implemented. |
cumeadj | Is present if the player’s cume must be adjusted, typically to compensate for a misadjudication. It should be followed by one or two values, the first the amount of the adjustment, the second the round in which the adjustment should first be applied. This feature is not yet fully implemented. |
lifeg | If set, indicates the number of games that the player has played in his life, used for ratings computations. If not set, a value of 50 is assumed. |
off | Is present if the player is inactive for pairing purposes. It is followed by a single integer, indicating what spread ought to be awarded to them for each missed game. This feature is not yet fully implemented. |
p12 | Lists whether the player went first (1) or second (2) in each round. Rounds where the player went neither first nor second are marked 0, rounds where the player is paired but has to randomly determine whether or not s/he goes first are marked 3, rounds where tsh is not sure who will go first or even whether a random determination will be required are marked 4. |
team |
Names the player’s team, for use when
“config initial_exagony ”
or
“config exagony ”
are enabled,
or the
“TeamStandings ” command.
The value is a case-sensitive single-word code with no spaces.
|
Once you have everything set up, preferably a few days before your
tournament, you should try a dry run of your event.
Save a backup copy of your
“.t” files.
Enter one complete set of results for one division,
then use the
“RAND
”
command to quickly add additional random scores as necessary.
Check to make sure that all of your pairings are generated in a
reasonable manner, and in particular that you’ve chosen sensible
times to allow repeat pairings.
Try it a few times more with just the
“RAND
”
command, then restore the original backups of your
“.t” files
or use the
“TRUNCATEROUNDS
” command to delete the test data.
You can also do this more automatically by using the
“DRYrun
” command,
which runs an entire tournament for one division on random data using
the pairings you configured. You still have to delete the test data
at the end yourself
(this might be the only time it’s a good idea to use the
“RESETEVERYTHING
” command),
and don’t forget to delete any reports that may
have been generated during testing.
The “util/” folder contains an unsupported script currently called “simwsc” which has hardcoded values in it to perform a full-tournament simulation for pairings testing purposes.
Now is a good time to think about what to do if disaster strikes. You should always bring an extra computer, extra printer and extra ink cartridges. If you are running a multidivision tournament and have extra staff, then you can use the extra equipment to split the data entry task across two installations of tsh, combining the two if some of your hardware fails.
tsh journals a copy of every “.t” file after every change, which is useful for correcting errors, but not helpful if your hard disk crashes or your computer dies. Follow the standard rule for backups: make a copy of important files often enough that you don’t mind having to type in any changes since your last backup. For “.t” files, this should be somewhere between every round (to be safe) and every session (to live dangerously). Back up files to other computers, the net, and/or removable media.
If your computer fails and you do not have a spare computer, announce what has happened, gather scorecards and any qualified directors and do pairings by hand. Then write out “I will not run a tournament without a spare computer” enough times by hand that you learn your lesson.
If your printer fails or you run out of ink, in a small tournament you can probably write out or announce pairings aloud, especially if you just need to cover until you can find a replacement cartridge.