ACBLscore Game Files Decoded

by Matthew Kidd
Original: September 30, 2013
Last Revised: July 28, 2014

As far as I know the internal format of the ACBLscore game files has never been published. The information presented below is the result of a few days of reverse engineering, most of it spent staring at a hex editor display much like the screenshot below. This documentation is not complete but it is fairly detailed and should be a good start for anyone else. I may update it from time to time but an exhaustive reverse engineering would be very time consuming and largely pointless because ACBLscore+, the long awaited successor to ACBLscore, is due in perhaps a year.

Hex editor view of an ACBLscore game file

Example of a Pair Entry in a Pair Entry Table in an ACBLscore game file. Entry length is 0x192 = 402 bytes (red box). Pair percentage is 0x1505 = 5381 ⇒ 53.81% (purple box). Last name of first player in partnership is "Angione”, seven ASCII characters (green box).

Why even bother at all? The initial motivation was to compute the field strength and display each player’s masterpoint total in ACBLmerge. Both of these features require the player numbers in order to lookup each player’s current masterpoint total. ACBLscore used to print the player numbers on the text and HTML reports but a couple of years ago ACBLscore stopped including them in most cases, perhaps to make the report format more compact. Since the player numbers had to be in the ACBLscore game files, I went looking for them. It was a fairly easy to search the entire game file for strings that looked like player numbers and then find the corresponding player names which were always at a fixed offset from the player numbers. This simplistic methods works pretty well though it can lead to incorrect results if two players have the same first and last names in a single game file, a rare event that nonetheless has happened at regionals where many events are contained in a single game file. A better understanding of the internal format would allow each player number to be associated with a section, pair number, and direction (N-S or E-W).

The second reason is to perform statistical analyses on players and partnerships across many sessions, typically in a regular game, say the La Jolla unit game or Thursday evening at the Soledad Club. For the Social Network graphs, it was enough to pull additional pair data using the same technique that ACBLmerge uses. But the Payoff Matrix requires more detail, specifically results from every board. It is possible to do these analyses by parsing the text and HTML reports generated by ACBLscore. However, there are many little quirks involved in the text parsing. And different clubs choose to generate different ACBLscore reports. Worse, I don’t know any way to systematically generate a particular style of report from the ACBLscore games files, i.e. from the command line; it is quite tedious to manually open several hundred game files in ACBLscore and create the desired report for each one. Directly reading the binary game files solves both these problems.

Third, some information is the game files is not readily obtainable elsewhere. For example, an analysis of whether some pairs routinely choke on the last round requires knowing which round each pair played each board. For a Mitchell movement this is straightforward to calculate. For a Howell movement it is necessary to know the exact movement. But when parsing game files directly, the round information is available from game file itself.

Finally, directly parsing the binary format is really fast. For example, my Payoff Matrix Perl program scans through 600 games files in about four seconds on a Windows 7 era laptop. It wouldn’t be intolerably slow to scan the text based reports but performance is always a win. Users don’t like to wait, especially when the user is also the developer.

Data Types, Data Layout, and Notation

It is worth making several general observations which will simplify the rest of the documentation.

Let uint8 designate a 1-byte unsigned integer. Let uint16 and int16 designate 2-byte unsigned and signed integers respectively. Let uint32 and int32 designate 4-byte unsigned and signed integers respectively. Let pointer designate a 4-byte integer file pointer, a uint32 that happens to be a pointer.

All floating point values discovered so far have exactly two digits after the decimal point. For example, the percentage 53.81% is stored as 5381 which has the hexadecimal representation of 0x1505 and hence the byte order 0x05 0x15 since data is stored little-endian. Both matchpoint and masterpoint quantities are handled in the same manner. Let the intfloat(n) designate a fixed decimal value with n digits after the decimal point. I have seen no evidence of standard IEEE-754 floating point values in the ACBLscore game files. So far only intfloat(2) data types have been observed. Some intfloat(2) values appear to occupy 2 bytes which others most likely occupy four bytes. Some intfloat(2) values are signed.

Let string(n) designate a string containing up to n ASCII characters. These fields occupy n+1 bytes because the first byte indicates the length of string. The unused part of the string field is almost always zero padded but this is not completely reliable and even if it were, relying on a terminating NUL will fail whenever the string length is as long as longest string allowed. Use the first byte to determine the string length. Let char(n) designate an array of n bytes intended to be interpreted as characters, e.g. ‘A’ without nul termination. In practice only char(1) has been relevant.

Let struct mean a C style structure where members are laid out at fixed offsets from the start of the structure. Let table mean a structure whose primary purpose is to contain many entries (records) of another structure. Tables usually consist of a table header followed by multiple table entries. Usually the table entries start immediately after the table header and are laid out without gaps. However, it is unsafe to rely on this if the table has a corresponding index table. Use the index table to find the starting location of each entry in the table.

None of the structure or table names described here are official names. This is strictly a reverse engineering effort.

All relative offsets shown in blue in the charts below are in hexadecimal, even though they are not prefixed with 0x. All other values should be assumed to be decimal values unless prefixed by 0x.

Acknowledgement

Don Greenwood sent me his C# code for parsing ACBLscore games files in early January 2014. At the start of March I was finally able to integrate my reverse engineering with his reverse engineering to produce the most complete and accurate documentation to date.

Events and Sections

Each ACBLscore game file contains one or more events. Examples of events are Open Pairs, 0-750 Pairs, Swiss Teams, Knockout Teams, etc. Each event contains one or more sections. Sections are designated by letter designations, A-Z or AA-ZZ. In this documentation, a section refers to both the N-S and E-W pairs, i.e. both directions. The use of section in ACBL documentation is inconsistent. Sometimes it has the meaning above; other times it means only one direction, e.g. when an section masterpoint award is computed for the each direction of a lettered section in a Mitchell movement.

Sections may be combined to produce overall winners across sections. for pairs events, the top matchpoint score on a board is N-1 where N is the highest number of times any board is played in any section. The results from other boards are scaled to this matchpoint top. For example consider the ugly situation of a pairs event with a 12 table section and a 13 table section. The 12 table section will play nine rounds of 3 boards per round for a matchpoint top of 8 while the 13 table section will play 13 rounds of 2 boards per round for a matchpoint of 12. Matchpoint scores from the 12 table section will be scaled up. Scaling is the most common reason for funny looking matchpoint scores like 4.87. Note: the ACBLscore documentation confusingly uses the term factoring, despite its completely different meaning in algebra, instead of scaling.

Master Table and Section Summary Structure

An ACBLscore game file begins with the Master Table. Therefore in this case only, the relative file offsets are identical to the absolute file offsets.

Master Table
Offset Type Description
0000 uint16 Length of rest of table (seems to always be 0x0a12 = 2578 bytes)
0002 string(3) ‘AC3’ string
0006 uint32 Length of game file (in bytes)
000a pointer Usually null but sometimes a pointer to a Pair Index Table. Purpose is unclear.
0012 pointer Pointer to 1st Event Details Structure
0016 pointer Pointer to 2nd Event Details Structure (if at least two events; otherwise null). It appears that up to 50 event pointers are permitted.
00da uint8 Event Type for 1st Event: 0 → Pairs, 1 → Teams, 2 → Individual, 3 → Home Style pairs, 4 → Board-A-Match teams, 5 → Series winner (a zero-based offset for the “Select type of game” dialog in ACBLscore).
00db uint8 Event Type for 2nd Event and so on (up to 50 events)
010c uint8 Event Scoring for 1st Event. For Pairs events the options are 0 → Matchpoints, 1 → IMPs with computed datum, 2 → Average IMPs, 3 → Total IMPs, 4 → Instant Matchpoints, 5 → Board-a-Match Teams, 13 → IMPs with predetermined datum, 14 → Double Matchpoints (European), 15 → Total Points. The first few values are a zero-based offset of the “Select scoring method” dialog in ACBLscore, reached via F9 → 9. Change scoring method. For Teams events the options are 6 → Win/Loss, 7 → Victory Points, 8 → Knockout, 16 → Board-a-Match Matchpoints, 18 → Compact KO. 10 → Series Winners.
010d uint8 Event Scoring for 2nd Event and so on (up to 50 events)
013e struct 1st Section Summary Structure (22 bytes)
0160 struct 2nd Section Summary Structure (if at least two sections; otherwise zero filled). It appears that up to 100 Section Structures are permitted.
09d6 62 mystery bytes

The ‘AC3’ string seems like a reliable way to test whether a file is an ACBLscore game file, i.e. the bytes of the ‘AC3’ string are good magic bytes. The Master Table length can probably also be used as part of the magic bytes; I don’t know whether the limits of 50 event and 100 sections are hard coded into ACBLscore or whether a bigger Master Table can be created. Since the starting location of the Section Summary Structures at 0x013e appears to be hard coded, my guess is that the event and section limits are hard coded.

Section Summary Structure
Offset Type Description
0000 uint8 Event number that section belongs to. Event numbering starts at 1. Zero if section structure is not used.
0001 string(2) Section designation. Examples: ‘A’, ‘B’, or ‘TT’
0004 pointer Pointer to Section Details Structure
0008 pointer Pointer to Board Results Index Table. NULL for team events.
000c intfloat(2) Total matchpoint score for a 100% games (pairs events only)
000e uint8 Related to scoring method?? (Usually is 3 for Pair games)
000f uint8 Section number within event. Section numbering starts at 0.
0010 uint8 ?? (Have seen 0, 2, and 3)
0011 uint16 ?? (Always seems to be 0)
0013 uint16 Number of rounds entered so far
0014 uint16 Number of rounds
0015 uint16 ?? (Always seems to be 0)

Event Details Structure

Each event has a pointer in the Master Table to an Event Details structure.

Event Details Structure
Offset Type Description
0000 uint16 Length of rest of structure (seems to always be 0x02e4 = 740 bytes)
0002 uint8 Event number (numbering starts at 1).
0003 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16, though it needn’t be because 50 is the maximum number of events).
0004 string(25) Event name, e.g. ‘Sunday Afternoon Pairs’
001e string(13) Session name, e.g. ‘Sunday Aft’
002c string(16) Director’s name
003d string(16) Tournament sanction, e.g. ‘R1204034’ (empty for club games)
0048 string(20) Date, e.g. ‘August 25, 2013’
005c string(25) Club or tournament name, e.g. ‘La Jolla Unit 526’
0076 string(4) Event code, e.g. ‘AMSS’ for Morning (AM) Side Series. Probably only used for tournaments. Might actually be string(17).
007a ?? (11 bytes). May be part of previous field.
0088 uint8 Rating: 0 → No Masterpoints Awarded, 1 → Club Masterpoint, etc. Refer to the auxiliary Event Rating Enum table below for a list of all known values. Note: In ACBLscore, The rating is set via F9 → “10. Set masterpoint rating”.
0089 uint8 End of event flag (0xFF = 255 indicates the last session in the event)
008a ?? (2 bytes). Always zero?
008c uint(16) Session number (starting at 1)
008e unit(16) Session number (starting at 1)
0090 ?? (14 bytes).
009e unit(8) Number of strats
009e unit(8) Total number of sessions
009f ?? (10 bytes)
00a9 unit(8) Rating (see above). Why is this repeated?
00b0 string(6) Club number, e.g. ‘146506’
00b7 ?? (13 bytes)
00ca unit(8) Handicapped flag. 0 → not handicapped
00cb ?? (25 bytes)
00e4 intfloat(2) ?? - MPs 1st O/A side series
00e6 ?? (4 bytes)
00ea intfloat(2) ?? - MPs 1st O/A
00ec ?? (8 bytes)
00f4 uint16 Strat 1 masterpoint cutoff (0 = Unlimited, i.e. an open game)
00f6 char(1) Strat 1 ASCII letter, e.g. ‘A’
00f7 uint8 Percent of open game rating for Strat 1 in a limited game, e.g. 80 if the ACBLscore report says: RATING>Club Masterpoint (80%, 60%, 60% Open). Set to 100 for an open game.
00f8 ?? (91 bytes)
0153 uint16 Strat 2 masterpoint cutoff
0155 char(1) Strat 2 ASCII letter, e.g. ‘B’
0156 uint8 Percent of open game rating for Strat 2
0157 ?? (91 bytes)
01b2 uint16 Strat 3 masterpoint cutoff
01b4 char(1) Strat 3 ASCII letter, e.g. ‘C’
01b5 uint8 Percent of open game rating for Strat 3
01b5 ?? (131 bytes)
Event Rating Enum
Value Description
0 No Masterpoints Awarded
1 Club Masterpoint
2 Club Championship
3 Charity Club Championship
4 Unit Championship
5 Regional
6 Sectional
7 Club International Fund
8 Club Membership
12 Upgraded Club Championship
14 STAC
15 National
16 Bridge Plus
17 Progressive Sectional
18 Unit Charity Game
19 Unit Extended Team Game
20 NAP Club Level
21 NAP Unit Level
22 GNT Club Level
23 GNT Unit Level
24 ACBL Wide Charity
25 ACBL Wide International Fund
Value Description
27 Canada Wide Olympiad
28 World Wide Instant Matchpoints
29 ACBL Wide Instant Matchpoints
30 Junior Fund
32 ACBL Wide Senior
33 COPC Club Level
34 CNTC Master/Non Master
35 CNTC Club Level
36 CNTC Unit Level
37 CWTC
38 Canada Rookie/Master
39 Inter-Club Championship
40 Unit Wide Championship
43 Club Appreciation
49 Club Appreciation Team
50 NABC Fund Raiser
51 GNT Fund Raiser
52 CNTC Fund Raiser
55 Club Education Foundation
56 Unit International Fund
57 Club Membership
58 Unit Education Fund
63 Grass Roots Fund

Section Details Structure

Each Section Summary Structure has a pointer to a Section Details Structure.

Section Details Structure
Offset Type Description
0000 uint16 Length of rest of structure (seems to always be 0x0322 = 802 bytes)
0002 uint8 Section number within event (numbering starts at 1).
0003 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16).
0004 pointer Pointer to Pair Index Table for N-S pairs at first round (if pairs event)
Pointer to Team Index Table (if teams event)
Pointer to Individual Index Table for North (if individual event)
0008 pointer Pointer to Pair Index Table for E-W pairs at first round (if pairs event)
Point to Individual Index Table for East (if individual event)
000c pointer Pointer to Individual Index Table for South (individual events only)
0010 pointer Pointer to Individual Index Table for West (individual events only)
0014 pointer Pointer to the Movement Table
0018 uint8 Movement related??
0019 uint8 Number of boards in play
001a uint8 ?? (Always seems to be zero. Previous field may be uint16)
001b uint8 Number of tables
001c uint8 ?? (Always seems to be zero. Previous field may be uint16)
001d uint8 Number of board / round
001e ?? (26 bytes)
0037 string(11) Movement filename, e.g. ‘H0509.HOW’ for a five table Howell movement. These files are stored in the MOV subfolder of the ACBLscore installation. Mitchell movements do not seem to get a name, probably because they are programmatically easy to handle for any number of tables and presumably no movement file is consulted.
0043 int16 Phantom pair number. Zero if no phantom pair. A positive value indicates a N-S phantom; negative indicates an E-W phantom.
004e intfloat(2) Total matchpoint score for a 100% game, i.e. the denominator when working out a pair’s percentage. Maximum number of Victory Points for Victory Point scoring of team games.
0050 string(?) Color designation for section, e.g. ‘BLUE’. These colors are used in the ACBLscore user interface.
0051 ?? (104 bytes)
00b9 uint8 Victory Point scale used (team game). 0 → 20, 1 → 30, 2 → 25

Player Structure

Player Structure
Offset Type Description
0000 string(16) Last name
0011 string(16) First name
0022 string(16) City
0033 string(2) State, e.g. ‘CA’
0036 string(7) ACBL player number. Empty string or ’NM’ (Non-Member) if players does not have an ACBL player number.
003e ?? (28 bytes)
0054 intfloat(2) ?? (2 bytes)
0056 ?? (10 bytes)
0060 intfloat(2) Masterpoint award
0062 ?? (15 bytes)
0071 uint16 Player’s masterpoint total (integer portion only). This can be out of date because it is based on the last time player information has been updated in ACBLscore. Also this field will overflow for Jeff Meckstroth who is over 65535 MP.
0073 char(1) Player’s Rank. See Masterpoint Honor Titles in The Masterpoint Plan. Space (“blank”) → Rookie (0-5 MP), A → Junior Master (5-20 MP), B → Club Master (20-50 MP), …, N → Grand LM. Refer to the Player Ranks table below. These ranks can be out of date because the are based on the last time player information has been updated in ACBLscore.
0074 ?? (1 byte). Always seems to be zero.
0075 string(2) Country code, e.g. ‘US’

The Player Structure occurs twice in the Pair Structure and six times in the Team Structure. In team events, team members can end up with different masterpoints, for example when a team member is added in a later round of a Knockout event. I am not sure what distinguishes the two fields that seem masterpoint related or whether they are relevant to pairs events.

Player Ranks
Code Title Masterpoint Range
Rookie 0–5
A Junior Master 5+
B Club Master 20+
C Sectional Master 50+
D Regional Master 100+
E NABC Master 200+
F Advanced NABC Master 300+
G Life Master 500+ (was 300+)
H Bronze Life Master 500+
I Silver Life Master 1000+
J Gold Life Master 2500+
K Diamond Life Master 5000+
L Emerald Life Master 7500+
M Platinum Life Master 10000+
N Grand Life Master 10000+

The Sectional Master and all higher ranks, also have pigmented point requirements. Grand Life Master requires a national title.

Pair Structure

Pair Structure
Offset Type Description
0000 uint16 Length of rest of structure (seems to always be 0x0192 = 402 bytes)
0002 uint8 Table number on first round. This will equal the pair number for a Mitchell movement but not for a Howell movement. This number can also be viewed as a 1-based index into the Pair Index Table.
0003 ?? (1 byte - previous field may be uint16)
0004 intfloat(2)
(4 bytes)
Adjustment (usually the result of a pair being penalized, e.g. for a Zero Tolerance violation or slow play.
0008 intfloat(2)
(4 bytes)
Unscaled score for this session. For example, consider a pair that gets bumped for one round of 13 rounds in a Mitchell Rover (bump) movement. Their score in the next field will be (13/12) times their unscaled score. Similar if a pair was ran out of time to play a single board in the same event, their score will be scaled up by (26/25). See Number of Boards played field at offset 0x002f.
000c intfloat(2)
(4 bytes)
Score for this session. For pairs, this is the total matchpoints for the partnership and this number divided by the total matchpoint score for a 100% game at offset 0x004e in Section Details Structures gives the partnership percentage. For IMP Pairs, this number is the total IMPs and the value is signed. ACBLscore reports display this value in the ‘Score’ column. For Teams games, it is the total victory points or number of wins depending on the scoring method for the event.
0010 intfloat(2)
(4 bytes)
Carryover Score (multi-session events only). Value has the same meaning as Score as per the scoring method used for the event.
0014 intfloat(2)
(4 bytes)
Final Score (multi-session events only). Value has the same meaning as Score as per the scoring method used for the event. Probably a four byte field.
0018 ?? (4 bytes). Usually all zeros. A reasonable guess would be the carryover score for the next session in a multi-session event.
001c intfloat(2) Partnership percentage. Zero for IMP Pairs.
001e uint8 Partnership strat
0020 uint16 Partnership average masterpoints (nearest integer). Used to determine the stratification.
0022 ?? (7 bytes)
0029 Next session assignment (multi-session events only)
002f uint16 Number of boards played
0031 ?? (2 bytes)
0033 uint8 Eligibility flag. Normally zero but will be non-zero (seen value of 10) if an ineligible pair fills in. Examples include a life master playing in an NLM event or a pair where one player’s (or the pair’s average) masterpoint holding exceeds the upper limit of a limited game. Usually the pair is filling in to prevent a half table. For the ranking, ACBLscore reports will show NE (Not Eligible) in the top flight.
0034 intfloat(2) Masterpoints awarded to each member of the partnership from previous session(s). Zero for one session events.
0036 ?? (10 bytes)
0040 intfloat(2) Masterpoints awarded to each member of the partnership in this session (may not be right)
0042 ?? (10 bytes)
004c intfloat(2) Masterpoints awarded to each member of the partnership from all sessions (use this value if there is only one session)
0042 ?? (26 bytes)
005e uint16 Section rank in A strat
0060 uint16 Zero unless there is a tie, e.g. if there is a tie for second and third place, the preceding value will be 2 and this value will be 3.
0062 uint16 Overall rank in A strat
0064 uint16 Zero unless there is a tie for Overall rank in A strat.
0066 ?? (12 bytes)
0072 uint16 Section rank in B strat
0074 uint16 Zero unless there is a tie for Section rank in B strat
0076 uint16 Overall rank in B strat
0078 uint16 Zero unless there is a tie for Overall rank in B strat
007a ?? (12 bytes)
0086 uint16 Section rank in C strat
0088 uint16 Zero unless there is a tie for Section rank in C strat
008a uint16 Overall rank in C strat
008c uint16 Zero unless there is a tie for Overall rank in C strat
008e ?? (12 bytes)
008e ?? (10 bytes)
00a4 struct Player Structure for first player in partnership (120 bytes)
011c struct Player Structure for second player in partnership (120 bytes)

If there is a phantom pair, the phantom pair will have a Pair Structure associated with it but nothing will be filled in.

Pair Index Table

The Pair Index Table gives the starting addresses of each Pair Structure. Pair Structures are usually laid out consecutively without gaps but this should not be assumed. Use the Pair Index Table to find each entry. For sections belonging to pairs events, the Section Details Structure contains two pointers at offsets 0x0004 and 0x0008 to Pair Index Tables.

Pair Index Table
Offset Type Description
0000 uint16 Length of rest of table (18 + 8 × number of Pair Index Entries)
0002 ?? (4 bytes)
0006 uint8 Number of Pair Index Entries
0007 ?? (11 bytes)
0014 struct 1st Pair Index Entry
struct Additional Pair Index Entries
Pair Index Entry
Offset Type Description
0000 ?? (2 bytes - always seems to be 0x00 x00)
0002 ?? (2 bytes - always seems to be 0x02 x00)
0004 pointer Pointer to Pair Structure

Board Result Table

A Board Result Table stores all the results on a board in a single section.

Board Results Table
Offset Type Description
0000 uint16 Length of rest of table (6 + 18 × number of Board Result Entries)
0002 uint16 Board number
0004 uint8 ?? (2 bytes)
0005 uint8 Number of results for board. This is not necessarily equal to the number of rounds in the section. For example, if 17 pairs play a Mitchell in one section, some boards will be in play at two tables on the same round.
0006 struct 1st Board Result Entry (18 bytes)
Board Result Entry
Offset Type Description
0000 uint8 Round number
0001 uint8 ?? (1 byte)
0002 uint8 N-S pair number
0003 uint8 ?? (1 byte)
0004 int16 Raw score for N-S / 10, e.g. +430 is encoded as 43, i.e. 0x2b 0x00. -50 is encoded as -5, i.e. 0xfb 0xff. Special values: 950 ⇒ Not Played (should have been, but wasn’t), 999 ⇒ Board not in play on this round, 2040 ⇒ Ave-, 2050 ⇒ Ave, 2060 ⇒ Ave+
0006 intfloat(2) Matchpoint score for N-S
0008 ?? (2 bytes - always seems to be 0x00 0x00)
000a uint8 E-W pair number
000b uint8 ?? (1 byte)
000c int16 Raw score for E-W / 10 (as above). Normally the E-W raw score is the opposite of the N-S raw score.
000e intfloat(2) Matchpoint score for N-S
0010 ?? (2 bytes - always seems to be 0x00 0x00)

The internal storage of raw scores is similar to the ACBLscore user interface. The superfluous final zero is dropped in both during data entry and in the internal store.

ACBLscore has to track separate raw scores and matchpoints for each direction to support director rulings where each side is assigned a different results, possibly based on different assumed contracts, and/or is assigned and Ave-, Ave, or Ave+ score.

Board Results Index Table

The Board Result Index Table gives the starting addresses of each Board Result Table. Board Result Tables are usually laid out consecutively without gaps but this should not be assumed. Use the Board Result Index Table to find each entry. The Section Summary Structure has a pointer to the Board Result Index Table at offset 0x0008.

Board Results Index Table
Offset Type Description
0000 uint16 Length of rest of table (36 + 8 × number of Board Results Table Entries)
0002 uint8 Section number within Event (see Section Details Structure)
0003 ?? (1 byte - always seems to be zero. Perhaps preceding field is really uint16.)
0004 uint8 Number of Board Results Tables
0005 ?? (31 bytes)
0024 struct 1st Board Results Index Entry (8 bytes)
Additional Board Results Index entries
Board Results Index Entry
Offset Type Description
0000 uint8 Board number
0001 ?? (1 byte)
0002 uint8 Number of Board Results Entries in corresponding Board Result Table
0003 ?? (1 byte)
0004 pointer Pointer to Board Results Table

Movement Table

The Movement Table indicates which pairs are seated at each direction at each round at each table. Use the information about which pairs are seated at each table at round one to determine the pair number for each Pair Structure based on the table number given at offset 0x0002 of the Pair Structure.

Movement Table
Offset Type Description
0000 uint16 Length of rest of structure (7 + 75 × number of Movement Table Entries)
0002 uint8 Probably Section number within Event (see Section Details Structure)
0003 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16).
0004 uint8 Number of tables in the movement
0005 uint8 Number of rounds in the movement
0006 ?? (1 byte)
0007 array Array of 25 Movement Structures for Table 1 (75 bytes)
0052 array Array of 25 Movement Structures for Table 2 (75 bytes)
Additional arrays of Movement Structures (one per table)
Movement Structure
Offset Type Description
0000 uint8 N-S pair number
0001 uint8 E-W pair number
0002 uint8 Lowest board number played by the N-S and E-W pairs on this round at this table

The Movement table allocates 75 bytes per table for movement information, enough for 75 / 3 = 25 rounds. This is enough rounds for one board per round. In practice it is much more common to have two or three boards per round. Unused Movement Structure array elements contain zeros in all fields.

Team Structure

Team Structure
Offset Type Description
0000 uint16 Length of rest of structure (seems to always be 0x0372 = 882 bytes)
0002 uint16 Team number
0004 ?? (4 bytes)
0008 intfloat(2) Number of wins. A tie is 0.5 wins (long ago ACBL used to have winning and losing ties at 0.75 and 0.25 wins each).
000a ?? (2 bytes)
000c intfloat(2) Score (Victory Points)
000e ?? (62 bytes)
004c intfloat(2) Masterpoints awarded to each member of the team (except when award is different for different team members).
004e ?? (19 bytes)
0062 uint16 Overall rank in A strat
0064 uint16 Zero unless there is a tie, e.g. if there is a tie for fifth thought seventh places, the preceding value will be 5 and this value will be 7.
0066 ?? (16 bytes)
0076 uint16 Overall rank in B strat
0078 uint16 Zero unless there is a tie for Overall rank in B strat
007a ?? (16 bytes)
008a uint16 Overall rank in C strat
008c uint16 Zero unless there is a tie for Overall rank in C strat
008e ?? (16 bytes)
009e ?? (6 bytes)
00a4 struct Player Structure for team player 1 (120 bytes)
011c struct Player Structure for team player 2 (120 bytes)
0194 struct Player Structure for team player 3 (120 bytes)
020c struct Player Structure for team player 4 (120 bytes)
0284 struct Player Structure for team player 5 (120 bytes)
02fc struct Player Structure for team player 6 (120 bytes)

A team may have up to six members. Team members receive masterpoints if they play at least half the time.

Team Index Table

The Team Index Table gives the starting addresses of each Team Structure. Team Structures are usually laid out consecutively without gaps but this should not be assumed. Use the Team Index Table to find each entry.

Team Index Table
Offset Type Description
0000 uint16 Length of rest of table (18 + 8 × number of Team Index Entries)
0002 uint8 Probably Section number within Event (see Section Details Structure)
0003 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16).
0004 ?? (2 bytes)
0006 uint8 Number of Team Index Entries
0007 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16).
0008 ?? (10 bytes)
0012 struct 1st Team Index Entry (8 bytes)
struct Additional Team Index Entries
Team Index Entry
Offset Type Description
0000 uint8 Team number
0001 ?? (1 byte - always seems to be zero. Perhaps the preceding field is really uint16.)
0002 ?? (2 bytes - always seems to be 0x04 0x00)
0004 pointer Pointer to Team Structure