Scid  4.6.5
indexentry.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 1999-2002 Shane Hudson
3 * Copyright (c) 2006-2009 Pascal Georges
4 * Copyright (C) 2014 Fulvio Benini
5 
6 * This file is part of Scid (Shane's Chess Information Database).
7 *
8 * Scid is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation.
11 *
12 * Scid is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with Scid. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef SCID_INDEXENTRY_H
22 #define SCID_INDEXENTRY_H
23 
24 #include "common.h"
25 #include "matsig.h"
26 #include "namebase.h"
27 
28 // Length is encoded as 17bits uint
29 #define MAX_GAME_LENGTH 131072
30 
31 // HPSIG_SIZE = size of HomePawnData array in an IndexEntry.
32 // It is nine bytes: the first byte contains the number of valid entries
33 // in the array, and the next 8 bytes contain up to 16 half-byte entries.
34 const uint HPSIG_SIZE = 9;
35 
36 const uint MAX_ELO = 4000; // Since we store Elo Ratings in 12 bits
37 
38 const byte CUSTOM_FLAG_MASK[] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5 };
39 
40 // Total on-disk size per index entry: currently 47 bytes.
43 
44 
45 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46 // Class IndexEntry: one of these per game in the index file.
47 //
48 // It contains more than just the location of the game data in the main
49 // data file. For fast searching, it also store some other important
50 // values: players, event, site, date, result, eco, gamelength.
51 //
52 // It takes 48 bytes, assuming sizeof(uint) == 4 and sizeof(ushort) == 2.
53 
55 {
56  uint32_t Offset; // Start of gamefile record for this game.
57  uint16_t Length_Low; // Length of gamefile record for this game. 17 bits are used so the max
58  // length is 128 ko (131071). So 7 bits are usable for custom flags or other.
59  byte Length_High; // LxFFFFFF ( L = length for long games, x = spare, F = custom flags)
60  // Name ID values are packed into 12 bytes, saving 8 bytes over the
61  // simpler method of just storing each as a 4-byte idNumberT.
62  byte WhiteBlack_High; // High bits of White, Black.
63  uint16_t WhiteID_Low; // Lower 16 bits of White ID.
64  uint16_t BlackID_Low; // Lower 16 bits of Black ID.
65  uint16_t EventID_Low; // Lower 16 bits of Site.
66  uint16_t SiteID_Low; // Lower 16 bits of Site ID.
67  uint16_t RoundID_Low; // Lower 16 bits of Round ID.
68  uint16_t Flags;
69  uint16_t VarCounts; // Counters for comments, variations, etc.
70  // VarCounts also stores the result.
71  ecoT EcoCode; // ECO code
72  dateT Dates; // Date and EventDate fields.
73  eloT WhiteElo;
74  eloT BlackElo;
75  matSigT FinalMatSig; // material of the final position in the game,
76  // and the StoredLineCode in the top 8 bits.
77  uint16_t NumHalfMoves;
78  byte HomePawnData [HPSIG_SIZE]; // homePawnSig data.
79  byte EventSiteRnd_High; // High bits of Event, Site, Round.
80 
81 public:
82  void Init();
83  template <class T> errorT Read (T* file, versionT version);
84  template <class T> errorT Write (T* file, versionT version) const;
85 
86 
87  uint32_t GetOffset () const { return Offset; }
88  void SetOffset (uint32_t offset) { Offset = offset; }
89  uint32_t GetLength() const {
90  return Length_Low + (uint32_t(Length_High & 0x80) << 9);
91  }
92  void SetLength (size_t length) {
93  ASSERT(length < MAX_GAME_LENGTH);
94  Length_Low = static_cast<uint16_t>(length & 0xFFFF);
95  // preserve the last 7 bits
96  Length_High = ( Length_High & 0x7F ) | static_cast<byte>( (length >> 16) << 7 );
97  }
98 
99 
100  // Name Get and Set routines:
101  // WhiteID and BlackID are 20-bit values, EventID and SiteID are
102  // 19-bit values, and RoundID is an 18-bit value.
103  //
104  // WhiteID high 4 bits = bits 4-7 of WhiteBlack_High.
105  // BlackID high 4 bits = bits 0-3 of WhiteBlack_High.
106  // EventID high 3 bits = bits 5-7 of EventSiteRnd_high.
107  // SiteID high 3 bits = bits 2-4 of EventSiteRnd_high.
108  // RoundID high 2 bits = bits 0-1 of EventSiteRnd_high.
109  idNumberT GetWhite () const {
110  idNumberT id = (idNumberT) WhiteBlack_High;
111  id = id >> 4; // High 4 bits = bits 4-7 of WhiteBlack_High.
112  id <<= 16;
113  id |= (idNumberT) WhiteID_Low;
114  return id;
115  }
116  idNumberT GetBlack () const {
117  idNumberT id = (idNumberT) WhiteBlack_High;
118  id = id & 0xF; // High 4 bits = bits 0-3 of WhiteBlack_High.
119  id <<= 16;
120  id |= (idNumberT) BlackID_Low;
121  return id;
122  }
124  if (col == BLACK) return GetBlack();
125  return GetWhite();
126  }
127  idNumberT GetEvent () const {
128  uint id = (idNumberT) EventSiteRnd_High;
129  id >>= 5; // High 3 bits = bits 5-7 of EventSiteRnd_High.
130  id <<= 16;
131  id |= (idNumberT) EventID_Low;
132  return id;
133  }
134  idNumberT GetSite () const {
135  uint id = (idNumberT) EventSiteRnd_High;
136  id = (id >> 2) & 7; // High 3 bits = bits 2-5 of EventSiteRnd_High.
137  id <<= 16;
138  id |= (idNumberT) SiteID_Low;
139  return id;
140  }
141  idNumberT GetRound () const {
142  uint id = (idNumberT) EventSiteRnd_High;
143  id &= 3; // High 2 bits = bits 0-1 of EventSiteRnd_High.
144  id <<= 16;
145  id |= (idNumberT) RoundID_Low;
146  return id;
147  }
148 
149  void SetWhite (idNumberT id) {
150  WhiteID_Low = id & 0xFFFF;
151  WhiteBlack_High = WhiteBlack_High & 0x0F; // Clear bits 4-7.
152  WhiteBlack_High |= ((id >> 16) << 4); // Set bits 4-7.
153  }
154  void SetBlack (idNumberT id) {
155  BlackID_Low = id & 0xFFFF;
156  WhiteBlack_High = WhiteBlack_High & 0xF0; // Clear bits 0-3.
157  WhiteBlack_High |= (id >> 16); // Set bits 0-3.
158  }
159  void SetPlayer (colorT col, idNumberT id) {
160  if (col == BLACK) return SetBlack(id);
161  return SetWhite(id);
162  }
163  void SetEvent (idNumberT id) {
164  EventID_Low = id & 0xFFFF;
165  // Clear bits 2-4 of EventSiteRnd_high: 31 = 00011111 binary.
166  EventSiteRnd_High = EventSiteRnd_High & 31;
167  EventSiteRnd_High |= ((id >> 16) << 5);
168  }
169  void SetSite (idNumberT id) {
170  SiteID_Low = id & 0xFFFF;
171  // Clear bits 2-4 of EventSiteRnd_high: 227 = 11100011 binary.
172  EventSiteRnd_High = EventSiteRnd_High & 227;
173  EventSiteRnd_High |= ((id >> 16) << 2);
174  }
175  void SetRound (idNumberT id) {
176  RoundID_Low = id & 0xFFFF;
177  // Clear bits 0-1 of EventSiteRnd_high: 252 = 11111100 binary.
178  EventSiteRnd_High = EventSiteRnd_High & 252;
179  EventSiteRnd_High |= (id >> 16);
180  }
181 
182 
183  const char* GetWhiteName (const NameBase* nb) const {
184  return nb->GetName (NAME_PLAYER, GetWhite());
185  }
186  const char* GetBlackName (const NameBase* nb) const {
187  return nb->GetName (NAME_PLAYER, GetBlack());
188  }
189  const char* GetEventName (const NameBase* nb) const {
190  return nb->GetName (NAME_EVENT, GetEvent());
191  }
192  const char* GetSiteName (const NameBase* nb) const {
193  return nb->GetName (NAME_SITE, GetSite());
194  }
195  const char* GetRoundName (const NameBase* nb) const {
196  return nb->GetName (NAME_ROUND, GetRound());
197  }
198 
199  errorT SetWhiteName(NameBase* nb, const char* s) {
200  idNumberT id = 0;
201  errorT res = nb->AddName (NAME_PLAYER, s ? s : "?", &id);
202  if (res == OK) SetWhite (id);
203  return res;
204  }
205  errorT SetBlackName(NameBase* nb, const char* s) {
206  idNumberT id = 0;
207  errorT res = nb->AddName (NAME_PLAYER, s ? s : "?", &id);
208  if (res == OK) SetBlack (id);
209  return res;
210  }
211  errorT SetEventName(NameBase* nb, const char* s) {
212  idNumberT id = 0;
213  errorT res = nb->AddName (NAME_EVENT, s ? s : "?", &id);
214  if (res == OK) SetEvent (id);
215  return res;
216  }
217  errorT SetSiteName(NameBase* nb, const char* s) {
218  idNumberT id = 0;
219  errorT res = nb->AddName (NAME_SITE, s ? s : "?", &id);
220  if (res == OK) SetSite (id);
221  return res;
222  }
223  errorT SetRoundName(NameBase* nb, const char* s) {
224  idNumberT id = 0;
225  errorT res = nb->AddName (NAME_ROUND, s ? s : "?", &id);
226  if (res == OK) SetRound (id);
227  return res;
228  }
229 
230 
231  dateT GetDate () const { return u32_low_20(Dates); }
232  uint GetYear () const { return date_GetYear (GetDate()); }
233  uint GetMonth() const { return date_GetMonth (GetDate()); }
234  uint GetDay () const { return date_GetDay (GetDate()); }
235  dateT GetEventDate () const {
236  uint dyear = date_GetYear (GetDate());
237  dateT edate = u32_high_12 (Dates);
238  uint month = date_GetMonth (edate);
239  uint day = date_GetDay (edate);
240  uint year = date_GetYear(edate) & 7;
241  if (year == 0) { return ZERO_DATE; }
242  year = dyear + year - 4;
243  return DATE_MAKE (year, month, day);
244  }
245  resultT GetResult () const { return (VarCounts >> 12); }
246  eloT GetWhiteElo () const { return u16_low_12(WhiteElo); }
247  eloT GetWhiteElo (const NameBase* nb) const {
248  eloT r = GetWhiteElo();
249  if (r == 0 && nb != 0) return nb->GetElo (GetWhite());
250  return r;
251  }
252  eloT GetBlackElo () const { return u16_low_12(BlackElo); }
253  eloT GetBlackElo (const NameBase* nb) const {
254  eloT r = GetBlackElo();
255  if (r == 0 && nb != 0) return nb->GetElo (GetBlack());
256  return r;
257  }
258  eloT GetElo(colorT col) const {
259  if (col == BLACK) return GetBlackElo();
260  return GetWhiteElo();
261  }
262  byte GetWhiteRatingType () const { return u16_high_4 (WhiteElo); }
263  byte GetBlackRatingType () const { return u16_high_4 (BlackElo); }
264  ecoT GetEcoCode () const { return EcoCode; }
265  ushort GetNumHalfMoves () const { return NumHalfMoves; }
266  byte GetRating(const NameBase* nb) const;
267 
268  void SetDate (dateT date) {
269  Dates = u32_set_low_20 (Dates, date);
270  }
271  void SetEventDate (dateT edate) {
272  uint codedDate = date_GetMonth(edate) << 5;
273  codedDate |= date_GetDay (edate);
274  uint eyear = date_GetYear (edate);
275  uint dyear = date_GetYear (GetDate());
276  // Due to a compact encoding format, the EventDate
277  // must be within a few years of the Date.
278  if ((eyear + 3) < dyear || eyear > (dyear + 3)) {
279  codedDate = 0;
280  } else {
281  codedDate |= (((eyear + 4 - dyear) & 7) << 9);
282  }
283  Dates = u32_set_high_12 (Dates, codedDate);
284  }
285  void SetResult (resultT res) {
286  VarCounts = (VarCounts & 0x0FFF) | (((ushort)res) << 12);
287  }
288  void SetWhiteElo (eloT elo) {
289  WhiteElo = u16_set_low_12(WhiteElo, elo);
290  }
291  void SetBlackElo (eloT elo) {
292  BlackElo = u16_set_low_12 (BlackElo, elo);
293  }
295  WhiteElo = u16_set_high_4 (WhiteElo, b);
296  }
298  BlackElo = u16_set_high_4 (BlackElo, b);
299  }
300  void SetEcoCode (ecoT eco) { EcoCode = eco; }
301  void SetNumHalfMoves (ushort b) { NumHalfMoves = b; }
302 
303 
304  bool GetFlag (uint32_t mask) const {
305  uint32_t tmp = Flags;
306  if ((mask & 0xFFFF0000) != 0) {
307  // The if is not necessary but should be faster
308  tmp |= (Length_High & 0x3F) << 16;
309  }
310  return (tmp & mask) == mask;
311  }
312  bool GetStartFlag () const { return (Flags & (1 << IDX_FLAG_START)) != 0; }
313  bool GetPromotionsFlag () const { return (Flags & (1 << IDX_FLAG_PROMO)) != 0; }
314  bool GetUnderPromoFlag() const { return (Flags & (1 << IDX_FLAG_UPROMO)) != 0; }
315  bool GetCommentsFlag () const { return (GetCommentCount() > 0); }
316  bool GetVariationsFlag () const { return (GetVariationCount() > 0); }
317  bool GetNagsFlag () const { return (GetNagCount() > 0); }
318  bool GetDeleteFlag () const { return (Flags & (1 << IDX_FLAG_DELETE)) != 0; }
319 
320  static uint CharToFlag (char ch);
321  static uint32_t CharToFlagMask (char flag);
322  static uint32_t StrToFlagMask (const char* flags);
323  uint GetFlagStr(char* dest, const char* flags) const;
324 
325  uint GetVariationCount () const { return DecodeCount(VarCounts & 15); }
326  uint GetCommentCount () const { return DecodeCount((VarCounts >> 4) & 15); }
327  uint GetNagCount () const { return DecodeCount((VarCounts >> 8) & 15); }
328 
329  matSigT GetFinalMatSig () const { return u32_low_24 (FinalMatSig); }
330  byte GetStoredLineCode () const { return u32_high_8 (FinalMatSig); }
331  const byte* GetHomePawnData () const { return HomePawnData; }
332  byte* GetHomePawnData () { return HomePawnData; }
333 
334  void SetFlag (uint32_t flagMask, bool b) {
335  uint16_t flagLow = flagMask & 0xFFFF;
336  if (flagLow != 0) {
337  if (b) {
338  Flags |= flagLow;
339  } else {
340  Flags &= ~flagLow;
341  }
342  }
343 
344  byte flagHigh = (flagMask >> 16) & 0x3F;
345  if (flagHigh != 0) {
346  if (b) {
347  Length_High |= flagHigh;
348  } else {
349  Length_High &= ~flagHigh;
350  }
351  }
352  }
353  void SetStartFlag (bool b) { SetFlag(1 << IDX_FLAG_START, b); }
354  void SetPromotionsFlag (bool b) { SetFlag(1 << IDX_FLAG_PROMO, b); }
355  void SetUnderPromoFlag (bool b) { SetFlag(1 << IDX_FLAG_UPROMO, b); }
356  void SetDeleteFlag (bool b) { SetFlag(1 << IDX_FLAG_DELETE, b); }
357  void clearFlags() { return SetFlag(IDX_MASK_ALLFLAGS, false); }
358 
360  VarCounts = (VarCounts & 0xFFF0U) | EncodeCount(x);
361  }
363  VarCounts = (VarCounts & 0xFF0FU) | (EncodeCount(x) << 4);
364  }
365  void SetNagCount (uint x) {
366  VarCounts = (VarCounts & 0xF0FFU) | (EncodeCount(x) << 8);
367  }
368 
370  FinalMatSig = u32_set_low_24 (FinalMatSig, ms);
371  }
373  FinalMatSig = u32_set_high_8 (FinalMatSig, b);
374  }
375 
376  enum {
377  // IndexEntry Flag types:
378  IDX_FLAG_START = 0, // Game has own start position.
379  IDX_FLAG_PROMO = 1, // Game contains promotion(s).
380  IDX_FLAG_UPROMO = 2, // Game contains promotion(s).
381  IDX_FLAG_DELETE = 3, // Game marked for deletion.
382  IDX_FLAG_WHITE_OP = 4, // White openings flag.
383  IDX_FLAG_BLACK_OP = 5, // Black openings flag.
384  IDX_FLAG_MIDDLEGAME = 6, // Middlegames flag.
385  IDX_FLAG_ENDGAME = 7, // Endgames flag.
386  IDX_FLAG_NOVELTY = 8, // Novelty flag.
387  IDX_FLAG_PAWN = 9, // Pawn structure flag.
388  IDX_FLAG_TACTICS = 10, // Tactics flag.
389  IDX_FLAG_KSIDE = 11, // Kingside play flag.
390  IDX_FLAG_QSIDE = 12, // Queenside play flag.
391  IDX_FLAG_BRILLIANCY = 13, // Brilliancy or good play.
392  IDX_FLAG_BLUNDER = 14, // Blunder or bad play.
393  IDX_FLAG_USER = 15, // User-defined flag.
394  IDX_FLAG_CUSTOM1 = 16, // Custom flag.
395  IDX_FLAG_CUSTOM2 = 17, // Custom flag.
396  IDX_FLAG_CUSTOM3 = 18, // Custom flag.
397  IDX_FLAG_CUSTOM4 = 19, // Custom flag.
398  IDX_FLAG_CUSTOM5 = 20, // Custom flag.
399  IDX_FLAG_CUSTOM6 = 21, // Custom flag.
401  };
402  static const uint32_t IDX_MASK_ALLFLAGS = 0xFFFFFFFF;
403 
404 private:
405  static uint EncodeCount (uint x) {
406  if (x <= 10) { return x; }
407  if (x <= 12) { return 10; }
408  if (x <= 17) { return 11; } // 11 indicates 15 (13-17)
409  if (x <= 24) { return 12; } // 12 indicates 20 (18-24)
410  if (x <= 34) { return 13; } // 13 indicates 30 (25-34)
411  if (x <= 44) { return 14; } // 14 indicates 40 (35-44)
412  return 15; // 15 indicates 50 or more
413  }
414  static uint DecodeCount (uint x) {
415  static uint countCodes[16] = {0,1,2,3,4,5,6,7,8,9,10,15,20,30,40,50};
416  return countCodes[x & 15];
417  }
418 
419 // Bitmask functions for index entry decoding:
420  static byte u32_high_8( uint x )
421  {
422  return (byte)(x >> 24);
423  }
424 
425  static uint u32_low_24( uint x )
426  {
427  return x & 0x00FFFFFF;
428  }
429 
430  static uint u32_high_12( uint x )
431  {
432  return x >> 20;
433  }
434 
435  static uint u32_low_20( uint x )
436  {
437  return x & 0x000FFFFF;
438  }
439 
440  static byte u16_high_4( ushort x )
441  {
442  return (byte)(x >> 12);
443  }
444 
445  static ushort u16_low_12( ushort x )
446  {
447  return x & 0x0FFF;
448  }
449 
450  static uint u32_set_high_8( uint u, byte x )
451  {
452  return u32_low_24(u) | ((uint)x << 24);
453  }
454 
455  static uint u32_set_low_24( uint u, uint x )
456  {
457  return (u & 0xFF000000) | (x & 0x00FFFFFF);
458  }
459 
460  static uint u32_set_high_12( uint u, uint x )
461  {
462  return u32_low_20(u) | (x << 20);
463  }
464 
465  static uint u32_set_low_20( uint u, uint x )
466  {
467  return (u & 0xFFF00000) | (x & 0x000FFFFF);
468  }
469 
470  static ushort u16_set_high_4( ushort u, byte x )
471  {
472  return u16_low_12(u) | ((ushort)x << 12);
473  }
474 
475  static ushort u16_set_low_12( ushort u, ushort x )
476  {
477  return (u & 0xF000) | (x & 0x0FFF);
478  }
479 };
480 
481 
482 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
483 // IndexEntry::Init():
484 // Initialise a single index entry.
485 //
486 inline void
488 {
489  NumHalfMoves = 0;
490  WhiteID_Low = 0;
491  BlackID_Low = 0;
492  EventID_Low = 0;
493  SiteID_Low = 0;
494  RoundID_Low = 0;
495  WhiteBlack_High = 0;
496  EventSiteRnd_High = 0;
497  EcoCode = 0;
498  Dates = 0;
499  WhiteElo = 0;
500  BlackElo = 0;
501  FinalMatSig = 0;
502  Flags = 0;
503  VarCounts = 0;
504  Offset = 0;
505  Length_Low = 0;
506  Length_High = 0;
507  SetDate (ZERO_DATE);
512  for (uint i=0; i < HPSIG_SIZE; i++) {
513  HomePawnData[i] = 0;
514  }
515 }
516 
517 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518 // IndexEntry::Read():
519 // Reads a single entry's values from an open index file.
520 //
521 template <class T> errorT
523 {
524  // Length of each gamefile record and its offset.
525  Offset = file->ReadFourBytes ();
526  Length_Low = file->ReadTwoBytes ();
527  Length_High = (version < 400) ? 0 : file->ReadOneByte();
528  Flags = file->ReadTwoBytes ();
529 
530  // White and Black player names:
531  WhiteBlack_High = file->ReadOneByte ();
532  WhiteID_Low = file->ReadTwoBytes ();
533  BlackID_Low = file->ReadTwoBytes ();
534 
535  // Event, Site and Round names:
536  EventSiteRnd_High = file->ReadOneByte ();
537  EventID_Low = file->ReadTwoBytes ();
538  SiteID_Low = file->ReadTwoBytes ();
539  RoundID_Low = file->ReadTwoBytes ();
540 
541  VarCounts = file->ReadTwoBytes();
542  EcoCode = file->ReadTwoBytes ();
543 
544  // Date and EventDate are stored in four bytes.
545  Dates = file->ReadFourBytes();
546 
547  // The two ELO ratings and rating types take 2 bytes each.
548  WhiteElo = file->ReadTwoBytes ();
549  BlackElo = file->ReadTwoBytes ();
550  if (GetWhiteElo() > MAX_ELO) { SetWhiteElo(MAX_ELO); }
551  if (GetBlackElo() > MAX_ELO) { SetBlackElo(MAX_ELO); }
552 
553  FinalMatSig = file->ReadFourBytes ();
554  NumHalfMoves = file->ReadOneByte ();
555 
556  // Read the 9-byte homePawnData array:
557  byte * pb = HomePawnData;
558  // The first byte of HomePawnData has high bits of the NumHalfMoves
559  // counter in its top two bits:
560  uint pb0 = file->ReadOneByte();
561  *pb = (pb0 & 63);
562  pb++;
563  NumHalfMoves = NumHalfMoves | ((pb0 >> 6) << 8);
564  for (uint i2 = 1; i2 < HPSIG_SIZE; i2++) {
565  *pb = file->ReadOneByte ();
566  pb++;
567  }
568 
569  // Top 2 bits of HomePawnData[0] are for NumHalfMoves:
570  uint numMoves_High = HomePawnData[0];
571  HomePawnData[0] = HomePawnData[0] & 63;
572  numMoves_High >>= 6;
573  numMoves_High <<= 8;
574  NumHalfMoves = NumHalfMoves | numMoves_High;
575 
576  return OK;
577 }
578 
579 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
580 // IndexEntry::Write():
581 // Writes a single index entry to an open index file.
582 // INDEX_ENTRY_SIZE must be updated
583 template <class T> errorT
584 IndexEntry::Write (T* file, versionT version) const
585 {
586  // Cannot write old-version index files:
587  if (version < 400) { return ERROR_FileVersion; }
588 
589  version = 0; // We don't have any version-specific code.
590 
591  file->WriteFourBytes (Offset);
592 
593  file->WriteTwoBytes (Length_Low);
594  file->WriteOneByte (Length_High);
595  file->WriteTwoBytes (Flags);
596 
597  file->WriteOneByte (WhiteBlack_High);
598  file->WriteTwoBytes (WhiteID_Low);
599  file->WriteTwoBytes (BlackID_Low);
600 
601  file->WriteOneByte (EventSiteRnd_High);
602  file->WriteTwoBytes (EventID_Low);
603  file->WriteTwoBytes (SiteID_Low);
604  file->WriteTwoBytes (RoundID_Low);
605 
606  file->WriteTwoBytes (VarCounts);
607  file->WriteTwoBytes (EcoCode);
608  file->WriteFourBytes (Dates);
609 
610  // Elo ratings and rating types: 2 bytes each.
611  file->WriteTwoBytes (WhiteElo);
612  file->WriteTwoBytes (BlackElo);
613 
614  file->WriteFourBytes (FinalMatSig);
615  file->WriteOneByte (NumHalfMoves & 255);
616 
617  // Write the 9-byte homePawnData array:
618  const byte* pb = HomePawnData;
619  // The first byte of HomePawnData has high bits of the NumHalfMoves
620  // counter in its top two bits:
621  byte pb0 = *pb;
622  pb0 = pb0 | ((NumHalfMoves >> 8) << 6);
623  file->WriteOneByte (pb0);
624  pb++;
625  // write 8 bytes
626  for (uint i2 = 1; i2 < HPSIG_SIZE; i2++) {
627  file->WriteOneByte (*pb);
628  pb++;
629  }
630 
631  return OK;
632 }
633 
634 inline byte IndexEntry::GetRating(const NameBase* nb) const {
635  eloT welo = GetWhiteElo();
636  eloT belo = GetBlackElo();
637  if (welo == 0) { welo = nb->GetElo (GetWhite()); }
638  if (belo == 0) { belo = nb->GetElo (GetBlack()); }
639  int rating = static_cast<int>(welo + belo) / 140;
640 
641  // Bonus for comments or Nags
642  if (GetCommentCount() > 2 || GetNagCount() > 2) {
643  if (rating < 21) { // Missing elo
644  rating = 40;
645  } else {
646  rating += 6;
647  }
648  }
649 
650  // Early draw penalty
651  if (GetResult() == RESULT_Draw) {
652  uint moves = GetNumHalfMoves();
653  if (moves < 80) {
654  rating -= 3;
655  if (moves < 60) {
656  rating -= 2;
657  if (moves < 40) rating -= 2;
658  }
659  }
660  }
661 
662  if (rating < 0) return 0;
663  else return static_cast<byte> (rating);
664 }
665 
666 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
667 // IndexEntry::CharToFlag():
668 // Returns the flag number corresponding to the given character.
669 inline uint
671 {
672  uint flag = 0;
673  switch (toupper(ch)) {
674  case 'D': flag = IDX_FLAG_DELETE; break;
675  case 'W': flag = IDX_FLAG_WHITE_OP; break;
676  case 'B': flag = IDX_FLAG_BLACK_OP; break;
677  case 'M': flag = IDX_FLAG_MIDDLEGAME; break;
678  case 'E': flag = IDX_FLAG_ENDGAME; break;
679  case 'N': flag = IDX_FLAG_NOVELTY; break;
680  case 'P': flag = IDX_FLAG_PAWN; break;
681  case 'T': flag = IDX_FLAG_TACTICS; break;
682  case 'K': flag = IDX_FLAG_KSIDE; break;
683  case 'Q': flag = IDX_FLAG_QSIDE; break;
684  case '!': flag = IDX_FLAG_BRILLIANCY; break;
685  case '?': flag = IDX_FLAG_BLUNDER; break;
686  case 'U': flag = IDX_FLAG_USER; break;
687  case '1': flag = IDX_FLAG_CUSTOM1; break;
688  case '2': flag = IDX_FLAG_CUSTOM2; break;
689  case '3': flag = IDX_FLAG_CUSTOM3; break;
690  case '4': flag = IDX_FLAG_CUSTOM4; break;
691  case '5': flag = IDX_FLAG_CUSTOM5; break;
692  case '6': flag = IDX_FLAG_CUSTOM6; break;
693  }
694  return flag;
695 }
696 
697 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
698 // IndexEntry::CharToFlagMask():
699 // Transform a char in a mask that can be used with GetFlag() and SetFlag()
700 inline uint32_t IndexEntry::CharToFlagMask(char flag)
701 {
702  switch (toupper(flag)) {
703  case 'S': return 1 << IDX_FLAG_START;
704  case 'X': return 1 << IDX_FLAG_PROMO;
705  case 'Y': return 1 << IDX_FLAG_UPROMO;
706  case 'D': return 1 << IDX_FLAG_DELETE;
707  case 'W': return 1 << IDX_FLAG_WHITE_OP;
708  case 'B': return 1 << IDX_FLAG_BLACK_OP;
709  case 'M': return 1 << IDX_FLAG_MIDDLEGAME;
710  case 'E': return 1 << IDX_FLAG_ENDGAME;
711  case 'N': return 1 << IDX_FLAG_NOVELTY;
712  case 'P': return 1 << IDX_FLAG_PAWN;
713  case 'T': return 1 << IDX_FLAG_TACTICS;
714  case 'K': return 1 << IDX_FLAG_KSIDE;
715  case 'Q': return 1 << IDX_FLAG_QSIDE;
716  case '!': return 1 << IDX_FLAG_BRILLIANCY;
717  case '?': return 1 << IDX_FLAG_BLUNDER;
718  case 'U': return 1 << IDX_FLAG_USER;
719  case '1': return 1 << IDX_FLAG_CUSTOM1;
720  case '2': return 1 << IDX_FLAG_CUSTOM2;
721  case '3': return 1 << IDX_FLAG_CUSTOM3;
722  case '4': return 1 << IDX_FLAG_CUSTOM4;
723  case '5': return 1 << IDX_FLAG_CUSTOM5;
724  case '6': return 1 << IDX_FLAG_CUSTOM6;
725  }
726 
727  ASSERT(0);
728  return 0;
729 }
730 
731 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
732 // IndexEntry::StrToFlagMask():
733 // Transform a string in a mask that can be used with GetFlag() and SetFlag()
734 inline uint32_t IndexEntry::StrToFlagMask(const char* flags)
735 {
736  if (flags == 0) return 0;
737 
738  uint32_t res = 0;
739  while (*flags != 0) {
740  res |= IndexEntry::CharToFlagMask(*(flags++));
741  }
742  return res;
743 }
744 
745 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
746 // IndexEntry::GetFlagStr():
747 // Fills in the provided flag string with information on the
748 // user-settable flags set for this game.
749 // Returns the number of specified flags that are turned on.
750 inline uint
751 IndexEntry::GetFlagStr(char* dest, const char* flags) const
752 {
753  if (flags == NULL) { flags = "DWBMENPTKQ!?U123456"; }
754  uint count = 0;
755  while (*flags != 0) {
756  uint32_t mask = CharToFlagMask(*flags);
757  ASSERT(mask != 0);
758  if (GetFlag(mask)) {
759  *dest++ = *flags;
760  count++;
761  }
762  flags++;
763  }
764  *dest = 0;
765  return count;
766 }
767 
768 #endif
void SetNumHalfMoves(ushort b)
Definition: indexentry.h:301
void SetBlack(idNumberT id)
Definition: indexentry.h:154
unsigned char byte
Definition: common.h:97
uint date_GetYear(dateT date)
Definition: date.h:55
byte resultT
Definition: common.h:183
static const uint32_t IDX_MASK_ALLFLAGS
Definition: indexentry.h:402
bool GetFlag(uint32_t mask) const
Definition: indexentry.h:304
byte GetBlackRatingType() const
Definition: indexentry.h:263
const uint INDEX_ENTRY_SIZE
Definition: indexentry.h:41
idNumberT GetEvent() const
Definition: indexentry.h:127
uint32_t GetLength() const
Definition: indexentry.h:89
Definition: indexentry.h:400
uint idNumberT
Definition: namebase.h:39
const errorT OK
Definition: error.h:23
idNumberT GetPlayer(colorT col) const
Definition: indexentry.h:123
errorT Write(T *file, versionT version) const
Definition: indexentry.h:584
unsigned short versionT
Definition: common.h:44
Definition: indexentry.h:395
const uint HPSIG_SIZE
Definition: indexentry.h:34
const ecoT ECO_None
Definition: common.h:164
void SetNagCount(uint x)
Definition: indexentry.h:365
static uint32_t StrToFlagMask(const char *flags)
Definition: indexentry.h:734
void SetDeleteFlag(bool b)
Definition: indexentry.h:356
uint GetMonth() const
Definition: indexentry.h:233
void SetBlackRatingType(byte b)
Definition: indexentry.h:297
uint dateT
Definition: common.h:155
#define ASSERT(f)
Definition: common.h:67
void SetStartFlag(bool b)
Definition: indexentry.h:353
Definition: indexentry.h:381
uint32_t matSigT
Definition: matsig.h:25
dateT GetEventDate() const
Definition: indexentry.h:235
void SetWhite(idNumberT id)
Definition: indexentry.h:149
uint GetFlagStr(char *dest, const char *flags) const
Definition: indexentry.h:751
bool GetNagsFlag() const
Definition: indexentry.h:317
const colorT BLACK
Definition: common.h:204
void SetUnderPromoFlag(bool b)
Definition: indexentry.h:355
eloT GetBlackElo() const
Definition: indexentry.h:252
Definition: indexentry.h:397
void SetRound(idNumberT id)
Definition: indexentry.h:175
static uint CharToFlag(char ch)
Definition: indexentry.h:670
Definition: indexentry.h:391
resultT GetResult() const
Definition: indexentry.h:245
void SetStoredLineCode(byte b)
Definition: indexentry.h:372
bool GetUnderPromoFlag() const
Definition: indexentry.h:314
void SetEcoCode(ecoT eco)
Definition: indexentry.h:300
errorT SetSiteName(NameBase *nb, const char *s)
Definition: indexentry.h:217
Definition: indexentry.h:399
Definition: indexentry.h:389
const resultT RESULT_Draw
Definition: common.h:188
eloT GetBlackElo(const NameBase *nb) const
Definition: indexentry.h:253
#define DATE_MAKE(y, m, d)
Definition: date.h:44
const dateT ZERO_DATE
Definition: date.h:34
ecoT GetEcoCode() const
Definition: indexentry.h:264
void SetFlag(uint32_t flagMask, bool b)
Definition: indexentry.h:334
errorT AddName(nameT nt, const char *str, idNumberT *idPtr)
NameBase::AddName() - Returns the idNumberT corresponding to : a valid name type : the name to looku...
Definition: namebase.cpp:291
uint GetVariationCount() const
Definition: indexentry.h:325
matSigT GetFinalMatSig() const
Definition: indexentry.h:329
static uint32_t CharToFlagMask(char flag)
Definition: indexentry.h:700
Definition: indexentry.h:387
const byte CUSTOM_FLAG_MASK[]
Definition: indexentry.h:38
const uint MAX_ELO
Definition: indexentry.h:36
Definition: indexentry.h:393
errorT SetEventName(NameBase *nb, const char *s)
Definition: indexentry.h:211
const char * GetBlackName(const NameBase *nb) const
Definition: indexentry.h:186
bool GetDeleteFlag() const
Definition: indexentry.h:318
void SetDate(dateT date)
Definition: indexentry.h:268
const matSigT MATSIG_Empty
Definition: matsig.h:176
void SetCommentCount(uint x)
Definition: indexentry.h:362
Definition: indexentry.h:378
uint32_t uint
Definition: common.h:99
Definition: indexentry.h:390
uint GetCommentCount() const
Definition: indexentry.h:326
bool GetStartFlag() const
Definition: indexentry.h:312
void SetSite(idNumberT id)
Definition: indexentry.h:169
const char * GetName(nameT nt, idNumberT id) const
Definition: namebase.h:97
void Init()
Definition: indexentry.h:487
const char * GetSiteName(const NameBase *nb) const
Definition: indexentry.h:192
void SetLength(size_t length)
Definition: indexentry.h:92
uint32_t GetOffset() const
Definition: indexentry.h:87
errorT Read(T *file, versionT version)
Definition: indexentry.h:522
ushort GetNumHalfMoves() const
Definition: indexentry.h:265
ushort eloT
Definition: common.h:160
errorT SetRoundName(NameBase *nb, const char *s)
Definition: indexentry.h:223
Definition: indexentry.h:386
void SetEventDate(dateT edate)
Definition: indexentry.h:271
ushort ecoT
Definition: common.h:161
const byte * GetHomePawnData() const
Definition: indexentry.h:331
eloT GetElo(colorT col) const
Definition: indexentry.h:258
bool GetPromotionsFlag() const
Definition: indexentry.h:313
unsigned short errorT
Definition: error.h:20
const errorT ERROR_FileVersion
Definition: error.h:39
void SetPromotionsFlag(bool b)
Definition: indexentry.h:354
Definition: indexentry.h:385
void SetVariationCount(uint x)
Definition: indexentry.h:359
Definition: indexentry.h:382
bool GetVariationsFlag() const
Definition: indexentry.h:316
errorT SetWhiteName(NameBase *nb, const char *s)
Definition: indexentry.h:199
#define MAX_GAME_LENGTH
Definition: indexentry.h:29
uint16_t ushort
Definition: common.h:98
void SetWhiteElo(eloT elo)
Definition: indexentry.h:288
eloT GetWhiteElo(const NameBase *nb) const
Definition: indexentry.h:247
uint GetDay() const
Definition: indexentry.h:234
idNumberT GetRound() const
Definition: indexentry.h:141
Definition: indexentry.h:380
byte GetWhiteRatingType() const
Definition: indexentry.h:262
Definition: indexentry.h:388
void SetFinalMatSig(matSigT ms)
Definition: indexentry.h:369
void SetResult(resultT res)
Definition: indexentry.h:285
errorT SetBlackName(NameBase *nb, const char *s)
Definition: indexentry.h:205
idNumberT GetBlack() const
Definition: indexentry.h:116
void SetPlayer(colorT col, idNumberT id)
Definition: indexentry.h:159
Definition: indexentry.h:383
Definition: indexentry.h:379
void SetEvent(idNumberT id)
Definition: indexentry.h:163
Definition: indexentry.h:394
byte colorT
Definition: common.h:112
bool GetCommentsFlag() const
Definition: indexentry.h:315
const char * GetEventName(const NameBase *nb) const
Definition: indexentry.h:189
void clearFlags()
Definition: indexentry.h:357
void SetBlackElo(eloT elo)
Definition: indexentry.h:291
eloT GetElo(idNumberT id) const
Definition: namebase.h:98
Definition: indexentry.h:392
const uint OLD_INDEX_ENTRY_SIZE
Definition: indexentry.h:42
eloT GetWhiteElo() const
Definition: indexentry.h:246
const resultT RESULT_None
Definition: common.h:185
Definition: indexentry.h:396
idNumberT GetSite() const
Definition: indexentry.h:134
void SetWhiteRatingType(byte b)
Definition: indexentry.h:294
idNumberT GetWhite() const
Definition: indexentry.h:109
uint date_GetMonth(dateT date)
Definition: date.h:64
const char * GetRoundName(const NameBase *nb) const
Definition: indexentry.h:195
byte GetRating(const NameBase *nb) const
Definition: indexentry.h:634
dateT GetDate() const
Definition: indexentry.h:231
byte GetStoredLineCode() const
Definition: indexentry.h:330
const char * GetWhiteName(const NameBase *nb) const
Definition: indexentry.h:183
Definition: indexentry.h:54
uint GetNagCount() const
Definition: indexentry.h:327
byte * GetHomePawnData()
Definition: indexentry.h:332
void SetOffset(uint32_t offset)
Definition: indexentry.h:88
Definition: indexentry.h:384
Definition: indexentry.h:398
uint GetYear() const
Definition: indexentry.h:232
uint date_GetDay(dateT date)
Definition: date.h:73