Changeset 21 for trunk


Ignore:
Timestamp:
Dec 19, 2005, 8:56:54 AM (14 years ago)
Author:
jtv
Message:

New file format, stowing everything into a single data block

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/gamelogic.cxx

    r18 r21  
    9797  ++m_nearmines;
    9898  ++m_near_hiddenmines;
    99   assert(m_nearmines == m_near_hiddenmines);
    10099  assert(m_nearmines <= 8);
     100  assert(m_near_hiddenmines <= m_nearmines);
    101101}
    102102
     
    174174};
    175175
     176struct CoordsPair
     177{
     178  bool operator()(const pair<Coords,Coords> &lhs,
     179      const pair<Coords,Coords> &rhs) const throw ()
     180  {
     181    return (lhs.first < rhs.first) ||
     182      (!(rhs.first < lhs.first) && (lhs.second < rhs.second));
     183  }
     184};
    176185
    177186/// Is Patch a candidate for "superset detection" based on newly revealed Patch?
    178 /** This looks for the case where the unexplored area around the Patch is a
    179  * proper superset of the one of a neighbour that was just revealed.  If it is,
    180  * and if the number of unexplored mines near the current one is either equal to
    181  * that near the newly revealed one, or the difference is equal to the size
    182  * difference of the unexplored areas, then the unexplored area near the Patch
    183  * is either all clear or all mined, respectively.
     187/** This looks for the case where the unexplored area around a Patch is a proper
     188 * superset of a neighbour's (where one of the two is newly revealed).  If it
     189 * is, and if the number of unexplored mines near the "superset" one is either
     190 * equal to that near the "subset" one, or the difference is equal to the size
     191 * difference of the unexplored areas, then the unexplored area near
     192 * the "superset" one that doesn't border on the "subset" patch is either all
     193 * clear or all mined, respectively.
    184194 */
    185195class SuperSet
    186196{
    187   set<Coords> &m_worklist;
    188   const Patch &m_revealed;
    189 public:
    190   SuperSet(set<Coords> &worklist, const Patch &newly_revealed) :
     197public:
     198  typedef set<pair<Coords,Coords>,CoordsPair> PairList;
     199
     200  SuperSet(PairList &worklist, Coords nr, const Patch &newly_revealed) :
    191201    m_worklist(worklist),
    192     m_revealed(newly_revealed)
     202    m_revealed(newly_revealed),
     203    m_rc(nr)
    193204  {
    194205    assert(newly_revealed.revealed());
    195206  }
    196207
    197   void operator()(Coords c, const Patch &p) const
     208  void operator()(Coords c, const Patch &p)
    198209  {
    199210    if (p.revealed())
    200211    {
    201212      const int areadiff = p.near_unknown() - m_revealed.near_unknown();
    202       if (areadiff > 0 &&
    203       (p.near_hiddenmines() == m_revealed.near_hiddenmines() ||
    204        p.near_hiddenmines() == areadiff))
    205       m_worklist.insert(c);
     213      if (areadiff > 0)
     214        consider(m_rc, m_revealed, c, p, areadiff);
     215      else if (areadiff < 0)
     216        consider(c, p, m_rc, m_revealed, -areadiff);
    206217    }
     218  }
     219
     220private:
     221  PairList &m_worklist;
     222  const Patch &m_revealed;
     223  Coords m_rc;
     224
     225  void consider(Coords subc, const Patch &subp,
     226      Coords supc, const Patch &supp,
     227      int areadiff)
     228  {
     229    assert(areadiff > 0);
     230    if (supp.near_hiddenmines() == subp.near_hiddenmines() ||
     231    supp.near_hiddenmines() == areadiff)
     232      m_worklist.insert(make_pair(subc,supc));
    207233  }
    208234};
     
    271297  here = skip_whitespace(here);
    272298
    273   // TODO: Unify these two read operations
    274 
    275299  const int padding = linepadding(m_cols);
    276300
    277   // Read mine placement
     301  // Read data block: mine placement & revealed fields
    278302  for (int r=0; r<m_rows; ++r)
    279303  {
    280     for (int c = 0; c < m_cols; c += bitsperchar)
     304    for (int c = 0; c < m_cols; c += patchesperchar)
    281305    {
    282306      unsigned int x = extract_char(here);
    283       for (int i = 0; i < bitsperchar; ++i)
     307      for (int i = 0; i < patchesperchar; ++i)
    284308      {
    285     if (x & 1) place_mine_at(r,c+i);
    286     x >>= 1;
     309    if (x & 2) place_mine_at(r,c+i);
     310    if (x & 1) reveal_patch(r,c+i);
     311    x >>= 2;
    287312      }
    288313    }
     
    290315  }
    291316
    292   // Read revealed fields
    293   for (int r=0; r<m_rows; ++r)
    294   {
    295     for (int c = 0; c < m_cols; c += bitsperchar)
    296     {
    297       unsigned int x = extract_char(here);
    298       for (int i = 0; i < bitsperchar; ++i)
    299       {
    300     if (x & 1) reveal_patch(r, c+i);
    301     x >>= 1;
    302       }
    303     }
    304     here = read_eol(here, padding);
    305   }
     317  read_terminator(here);
    306318
    307319  // TODO: Re-unify this with regular constructor
     
    335347  const int padding = linepadding(m_cols);
    336348
    337   // TODO: Unify these two write actions
    338 
    339   // Write mines
     349  // Write mines & revealed fields
    340350  for (int r = 0; r < m_rows; ++r)
    341351  {
    342     for (int c = 0; c < m_cols; c += bitsperchar)
     352    for (int c = 0; c < m_cols; c += patchesperchar)
    343353    {
    344354      unsigned int x = 0;
    345       for (int i = bitsperchar-1; i >= 0; --i)
     355      for (int i = patchesperchar-1; i >= 0; --i)
    346356      {
    347     x <<= 1;
    348     if (c+i < m_cols && at(r,c+i).mined()) x |= 1;
    349       }
    350       *here++ = produce_char(x);
    351     }
    352     here = write_eol(here, padding);
    353   }
    354 
    355   here = write_newline(here);
    356 
    357   // Write revealed fields
    358   for (int r = 0; r < m_rows; ++r)
    359   {
    360     for (int c = 0; c < m_cols; c += bitsperchar)
    361     {
    362       unsigned int x = 0;
    363       for (int i = bitsperchar-1; i >= 0; --i)
    364       {
    365     x <<= 1;
     357    x <<= 2;
     358    if (c+i < m_cols && at(r,c+i).mined()) x |= 2;
    366359    if (c+i < m_cols && at(r,c+i).revealed()) x |= 1;
    367360      }
     
    500493    if (m_intelligence > 2)
    501494    {
    502       set<Coords> cand;
    503 
    504       // First step: filter out the possible cases
     495      SuperSet::PairList cand;
     496
     497      // First step: filter out the possible cases, based purely on numbers
    505498      for (set<Coords>::const_iterator i = area.begin(); i != area.end(); ++i)
    506499      {
    507500    const Patch &p = at(i->row, i->col);
    508         if (p.revealed()) for_neighbours(i->row, i->col, SuperSet(cand,p));
     501        if (p.revealed()) for_neighbours(i->row, i->col, SuperSet(cand,*i,p));
    509502      }
    510503     
    511504      // TODO: Iterate through candidates to find the *real* superset cases
    512       for (set<Coords>::const_iterator i = cand.begin(); i != cand.end(); ++i)
     505      for (SuperSet::PairList::const_iterator i = cand.begin();
     506       i != cand.end();
     507       ++i)
    513508      {
    514509      }
  • trunk/save.cxx

    r5 r21  
    3333{
    3434/// Header at start of saved file--we may change the format later
    35 const string saveheader = "#mines 0.1\n";
     35const string saveheader = "#mines 0.2\n";
    3636
    3737unsigned char encode[64], decode[256];
     
    190190}
    191191
     192
     193void read_terminator(const char *here)
     194{
     195  here = skip_whitespace(here);
     196  if (*here) throw runtime_error("Saved game format error: "
     197      "Unexpected data after end of data block");
     198}
     199
  • trunk/save.hxx

    r5 r21  
    1818*/
    1919
    20 enum { bitsperchar = 6 };
     20enum { patchesperchar = 3 };
    2121
    2222/// Call this to initialize encoding tables (lazy; should be threadsafe)
     
    5151/// Write terminating zero to output buffer
    5252void terminate(char *);
     53/// Verify that end-of-file happens where we expect it
     54void read_terminator(const char *);
    5355
Note: See TracChangeset for help on using the changeset viewer.