eliot-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Eliot-dev] Changes to eliot/game/board.cpp [antoine-1]


From: eliot-dev
Subject: [Eliot-dev] Changes to eliot/game/board.cpp [antoine-1]
Date: Sun, 23 Oct 2005 13:16:27 -0400

Index: eliot/game/board.cpp
diff -u /dev/null eliot/game/board.cpp:1.7.2.1
--- /dev/null   Sun Oct 23 17:16:27 2005
+++ eliot/game/board.cpp        Sun Oct 23 17:16:23 2005
@@ -0,0 +1,484 @@
+/*****************************************************************************
+ * Copyright (C) 1999-2005 Eliot
+ * Authors: Antoine Fraboulet <address@hidden>
+ *          Olivier Teuliere  <address@hidden>
+ *
+ * $Id: board.cpp,v 1.7.2.1 2005/10/23 17:16:23 afrab Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *****************************************************************************/
+
+#include "dic.h"
+#include "tile.h"
+#include "round.h"
+#include "bag.h"
+#include "rack.h"
+#include "results.h"
+#include "board.h"
+
+#define oo 0
+#define __ 1
+#define T2 2
+#define T3 3
+#define W2 2
+#define W3 3
+
+
+const int Board::m_tileMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
+{
+    { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
+    { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
+    { oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
+    { oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
+    { oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
+    { oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
+    { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
+    { oo,__,__,T2,__,__,__,T2,__,T2,__,__,__,T2,__,__,oo },
+    { oo,__,T3,__,__,__,T3,__,__,__,T3,__,__,__,T3,__,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,T2,__,__,__,__,__,__,T2,__,__,__,__,__,__,T2,oo },
+    { oo,__,__,__,__,__,__,T2,__,T2,__,__,__,__,__,__,oo },
+    { oo,__,__,__,__,__,T3,__,__,__,T3,__,__,__,__,__,oo },
+    { oo,__,__,__,T2,__,__,__,__,__,__,__,T2,__,__,__,oo },
+    { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
+};
+
+
+const int Board::m_wordMultipliers[BOARD_REALDIM][BOARD_REALDIM] =
+{
+    { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo },
+    { oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
+    { oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
+    { oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
+    { oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
+    { oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,W3,__,__,__,__,__,__,W2,__,__,__,__,__,__,W3,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,__,__,__,__,__,__,__,__,__,__,__,__,__,__,__,oo },
+    { oo,__,__,__,__,W2,__,__,__,__,__,W2,__,__,__,__,oo },
+    { oo,__,__,__,W2,__,__,__,__,__,__,__,W2,__,__,__,oo },
+    { oo,__,__,W2,__,__,__,__,__,__,__,__,__,W2,__,__,oo },
+    { oo,__,W2,__,__,__,__,__,__,__,__,__,__,__,W2,__,oo },
+    { oo,W3,__,__,__,__,__,__,W3,__,__,__,__,__,__,W3,oo },
+    { oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo,oo }
+};
+
+
+Board::Board():
+    m_tilesRow(BOARD_REALDIM, Tile::dummy()),
+    m_tilesCol(BOARD_REALDIM, Tile::dummy()),
+    m_jokerRow(BOARD_REALDIM, false),
+    m_jokerCol(BOARD_REALDIM, false),
+    m_crossRow(BOARD_REALDIM, Cross()),
+    m_crossCol(BOARD_REALDIM, Cross()),
+    m_pointRow(BOARD_REALDIM, -1),
+    m_pointCol(BOARD_REALDIM, -1),
+    m_testsRow(BOARD_REALDIM, 0)
+{
+    // No cross check allowed around the board
+    for (int i = 0; i < BOARD_REALDIM; i++)
+    {
+        m_crossRow[0][i].clear();
+        m_crossCol[0][i].clear();
+        m_crossRow[i][0].clear();
+        m_crossCol[i][0].clear();
+        m_crossRow[BOARD_REALDIM - 1][i].clear();
+        m_crossCol[BOARD_REALDIM - 1][i].clear();
+        m_crossRow[i][BOARD_REALDIM - 1].clear();
+        m_crossCol[i][BOARD_REALDIM - 1].clear();
+    }
+}
+
+
+Tile Board::getTile(int iRow, int iCol) const
+{
+    return m_tilesRow[iRow][iCol];
+}
+
+
+bool Board::isJoker(int iRow, int iCol) const
+{
+    return m_jokerRow[iRow][iCol];
+}
+
+
+/*********************************************************
+ *********************************************************/
+
+char Board::getChar(int iRow, int iCol) const
+{
+    char letter = 0;
+    Tile tile = getTile(iRow, iCol);
+    if (!tile.isEmpty())
+    {
+        letter = tile.toChar();
+        if (isJoker(iRow, iCol))
+            letter = tolower(letter);
+    }
+    return letter;
+}
+
+int Board::getCharAttr(int iRow, int iCol) const
+{
+    int t = getTestChar(iRow, iCol);
+    int j = isJoker(iRow, iCol);
+    return  (t << 1) | j;
+}
+
+
+bool Board::isVacant(int iRow, int iCol) const
+{
+    if (iRow < 1 || iRow > BOARD_DIM ||
+        iCol < 1 || iCol > BOARD_DIM)
+    {
+        return false;
+    }
+    return m_tilesRow[iRow][iCol].isEmpty();
+}
+
+
+void Board::addRound(const Dictionary &iDic, const Round &iRound)
+{
+    Tile t;
+    int row, col;
+
+    row = iRound.getRow();
+    col = iRound.getCol();
+    if (iRound.getDir() == HORIZONTAL)
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (m_tilesRow[row][col + i].isEmpty())
+            {
+                t = iRound.getTile(i);
+                m_tilesRow[row][col + i] = t;
+                m_jokerRow[row][col + i] = iRound.isJoker(i);
+                m_tilesCol[col + i][row] = t;
+                m_jokerCol[col + i][row] = iRound.isJoker(i);
+            }
+        }
+    }
+    else
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (m_tilesRow[row + i][col].isEmpty())
+            {
+                t = iRound.getTile(i);
+                m_tilesRow[row + i][col] = t;
+                m_jokerRow[row + i][col] = iRound.isJoker(i);
+                m_tilesCol[col][row + i] = t;
+                m_jokerCol[col][row + i] = iRound.isJoker(i);
+            }
+        }
+    }
+    buildCross(iDic);
+#ifdef DEBUG
+    checkDouble();
+#endif
+}
+
+
+void Board::removeRound(const Dictionary &iDic, const Round &iRound)
+{
+    int row, col;
+
+    row = iRound.getRow();
+    col = iRound.getCol();
+    if (iRound.getDir() == HORIZONTAL)
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (iRound.isPlayedFromRack(i))
+            {
+                m_tilesRow[row][col + i] = Tile::dummy();
+                m_jokerRow[row][col + i] = false;
+                m_tilesCol[col + i][row] = Tile::dummy();
+                m_jokerCol[col + i][row] = false;
+            }
+        }
+    }
+    else
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (iRound.isPlayedFromRack(i))
+            {
+                m_tilesRow[row + i][col] = Tile::dummy();
+                m_jokerRow[row + i][col] = false;
+                m_tilesCol[col][row + i] = Tile::dummy();
+                m_jokerCol[col][row + i] = false;
+            }
+        }
+    }
+    buildCross(iDic);
+#ifdef DEBUG
+    checkDouble();
+#endif
+}
+
+
+/* XXX: There is duplicated code with board_search.c.
+ * We could probably factorize something... */
+int Board::checkRoundAux(Matrix<Tile> &iTilesMx,
+                         Matrix<Cross> &iCrossMx,
+                         Matrix<int> &iPointsMx,
+                         Matrix<bool> &iJokerMx,
+                         Round &iRound,
+                         bool firstturn)
+{
+    Tile t;
+    int row, col, i;
+    int l, p, fromrack;
+    int pts, ptscross, wordmul;
+    bool isolated = true;
+
+    fromrack = 0;
+    pts = 0;
+    ptscross = 0;
+    wordmul = 1;
+    row = iRound.getRow();
+    col = iRound.getCol();
+
+    /* Is the word an extension of another word? */
+    if (!iTilesMx[row][col - 1].isEmpty() ||
+        !iTilesMx[row][col + iRound.getWordLen()].isEmpty())
+    {
+        return 1;
+    }
+
+    for (i = 0; i < iRound.getWordLen(); i++)
+    {
+        t = iRound.getTile(i);
+        if (!iTilesMx[row][col + i].isEmpty())
+        {
+            /* There is already a letter on the board */
+            if (iTilesMx[row][col + i] != t)
+                return 2;
+
+            isolated = false;
+            iRound.setFromBoard(i);
+
+            if (!iJokerMx[row][col + i])
+                pts += t.getPoints();
+        }
+        else
+        {
+            /* The letter is not yet on the board */
+            if (iCrossMx[row][col + i].check(t))
+            {
+                /* A non-trivial cross-check means an anchor square */
+                if (!iCrossMx[row][col + i].isAny())
+                    isolated = false;
+
+                if (!iRound.isJoker(i))
+                    l = t.getPoints() * m_tileMultipliers[row][col + i];
+                else
+                    l = 0;
+                pts += l;
+                wordmul *= m_wordMultipliers[row][col + i];
+
+                p = iPointsMx[row][col + i];
+                if (p >= 0)
+                {
+                    ptscross += (p + l) * m_wordMultipliers[row][col + i];
+                }
+                fromrack++;
+                iRound.setFromRack(i);
+            }
+            else
+            {
+                /* The letter is not in the crosscheck */
+                return 3;
+            }
+        }
+    }
+
+    /* There must be at least 1 letter from the rack */
+    if (fromrack == 0)
+        return 4;
+
+    /* The word must cover at least one anchor square, except
+     * for the first turn */
+    if (isolated && !firstturn)
+        return 5;
+    /* The first word must be horizontal */
+    if (firstturn && iRound.getDir() == VERTICAL)
+        return 6;
+    /* The first word must cover the H8 square */
+    if (firstturn
+        && (row != 8 || col > 8 || col + iRound.getWordLen() <= 8))
+    {
+        return 7;
+    }
+
+    /* Set the iPointsMx and bonus */
+    pts = ptscross + pts * wordmul + 50 * (fromrack == 7);
+    iRound.setPoints(pts);
+    iRound.setBonus(fromrack == 7);
+
+    return 0;
+}
+
+
+int Board::checkRound(Round &iRound, bool firstturn)
+{
+    if (iRound.getDir() == HORIZONTAL)
+        return checkRoundAux(m_tilesRow, m_crossRow,
+                             m_pointRow, m_jokerRow,
+                             iRound, firstturn);
+    else
+    {
+        int res, tmp;
+
+        // XXX: ugly!
+        /* Exchange the coordinates temporarily */
+        tmp = iRound.getRow();
+        iRound.setRow(iRound.getCol());
+        iRound.setCol(tmp);
+
+        res = checkRoundAux(m_tilesCol, m_crossCol,
+                            m_pointCol, m_jokerCol,
+                            iRound, firstturn);
+
+        /* Restore the coordinates */
+        tmp = iRound.getRow();
+        iRound.setRow(iRound.getCol());
+        iRound.setCol(tmp);
+
+        return res;
+    }
+}
+
+
+void Board::testRound(const Round &iRound)
+{
+    Tile t;
+    int row, col;
+
+    row = iRound.getRow();
+    col = iRound.getCol();
+    if (iRound.getDir() == HORIZONTAL)
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (m_tilesRow[row][col + i].isEmpty())
+            {
+                t = iRound.getTile(i);
+                m_tilesRow[row][col + i] = t;
+                m_jokerRow[row][col + i] = iRound.isJoker(i);
+                m_testsRow[row][col + i] = 1;
+
+                m_tilesCol[col + i][row] = t;
+                m_jokerCol[col + i][row] = iRound.isJoker(i);
+            }
+        }
+    }
+    else
+    {
+        for (int i = 0; i < iRound.getWordLen(); i++)
+        {
+            if (m_tilesRow[row + i][col].isEmpty())
+            {
+                t = iRound.getTile(i);
+                m_tilesRow[row + i][col] = t;
+                m_jokerRow[row + i][col] = iRound.isJoker(i);
+                m_testsRow[row + i][col] = 1;
+
+                m_tilesCol[col][row + i] = t;
+                m_jokerCol[col][row + i] = iRound.isJoker(i);
+            }
+        }
+    }
+}
+
+
+void Board::removeTestRound()
+{
+    for (int row = 1; row <= BOARD_DIM; row++)
+    {
+        for (int col = 1; col <= BOARD_DIM; col++)
+        {
+            if (m_testsRow[row][col])
+            {
+                m_tilesRow[row][col] = Tile::dummy();
+                m_testsRow[row][col] = 0;
+                m_jokerRow[row][col] = false;
+
+                m_tilesCol[col][row] = Tile::dummy();
+                m_jokerCol[col][row] = false;
+            }
+        }
+    }
+}
+
+
+char Board::getTestChar(int iRow, int iCol) const
+{
+    return m_testsRow[iRow][iCol];
+}
+
+
+int Board::getWordMultiplier(int iRow, int iCol) const
+{
+    if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
+        iCol < BOARD_MIN || iCol > BOARD_MAX)
+        return 0;
+    return m_wordMultipliers[iRow][iCol];
+}
+
+
+int Board::getLetterMultiplier(int iRow, int iCol) const
+{
+    if (iRow < BOARD_MIN || iRow > BOARD_MAX ||
+        iCol < BOARD_MIN || iCol > BOARD_MAX)
+        return 0;
+    return m_tileMultipliers[iRow][iCol];
+}
+
+
+#ifdef DEBUG
+void Board::checkDouble()
+{
+    for (int row = BOARD_MIN; row <= BOARD_MAX; row++)
+    {
+        for (int col = BOARD_MIN; col <= BOARD_MAX; col++)
+        {
+            if (m_tilesRow[row][col] != m_tilesCol[col][row])
+                printf("tiles diff %d %d\n", row, col);
+
+            // The crossckecks and the points have no reason to be the same
+            // in both directions
+            /*
+            if (m_crossRow[row][col] != m_crossCol[col][row])
+            {
+                printf("cross diff %d %d\n",row,col);
+            }
+
+            if (m_pointRow[row][col] != m_pointCol[col][row])
+                printf("point diff %d %d\n",row,col);
+            */
+
+            if (m_jokerRow[row][col] != m_jokerCol[col][row])
+                printf("joker diff %d %d\n", row, col);
+        }
+    }
+}
+#endif
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]