File indexing completed on 2024-07-14 04:00:00

0001 /*
0002     This file is part of the KDE games kwin4 program
0003     SPDX-FileCopyrightText: 2006 Martin Heni <kde@heni-online.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "aiboard.h"
0009 
0010 // own
0011 #include "kfourinline_debug.h"
0012 // Std
0013 #include <cstdio>
0014 
0015 // Construct a board object
0016 AIBoard::AIBoard()
0017 {
0018 }
0019 
0020 // Construct a board object from a given game field.
0021 AIBoard::AIBoard(uchar current, const char field[][7])
0022 {
0023     fromField(current, false, field);
0024 }
0025 
0026 // Compare two boards
0027 bool AIBoard::operator==(const AIBoard &other) const
0028 {
0029     if (mCurrent != other.mCurrent)
0030         return false;
0031     for (int i = 0; i < 6; i++) {
0032         if (mBoard[i] != other.mBoard[i])
0033             return false;
0034     }
0035     return true;
0036 }
0037 
0038 // Create a board from a given game field. Support mirroring the field.
0039 void AIBoard::fromField(uchar current, bool mirror, const char field[][7])
0040 {
0041     // Store current player
0042     mCurrent = current;
0043 
0044     // Loop rows
0045     for (int y = 0; y <= 5; y++) {
0046         ushort tmp = 0;
0047         // Loop columns
0048         for (int x = 0; x <= 6; x++) {
0049             tmp = tmp << 2;
0050             // Mirror board?
0051             if (mirror) {
0052                 if (field[y][6 - x] == Yellow)
0053                     tmp |= 1;
0054                 else if (field[y][6 - x] == Red)
0055                     tmp |= 2;
0056                 // else tmp |= 0;
0057             } else {
0058                 if (field[y][x] == Yellow)
0059                     tmp |= 1;
0060                 else if (field[y][x] == Red)
0061                     tmp |= 2;
0062                 // else tmp |= 0;
0063             }
0064         }
0065         mBoard[y] = tmp;
0066     }
0067 }
0068 
0069 // Retrieve a mirrored board.
0070 AIBoard AIBoard::mirror() const
0071 {
0072     AIBoard other;
0073     other.mCurrent = mCurrent;
0074 
0075     // Loop rows
0076     for (int y = 0; y <= 5; y++) {
0077         ushort tmp = mBoard[y];
0078         ushort ntmp = 0;
0079         // Loop columns
0080         for (int x = 0; x <= 6; x++) {
0081             ntmp = ntmp << 2;
0082             ntmp |= (tmp >> (x << 1)) & 3;
0083         }
0084         other.mBoard[y] = ntmp;
0085     }
0086     return other;
0087 }
0088 
0089 // Debug function to output the board.
0090 void AIBoard::print() const
0091 {
0092     fprintf(stderr, " AIBOARD ======== COLOR %d ========\n", mCurrent);
0093     for (int i = 5; i >= 0; i--) {
0094         ushort tmp = mBoard[i];
0095         fprintf(stderr, "   Row %d: [%04x]", i, tmp);
0096         for (int x = 6; x >= 0; x--) {
0097             if (((tmp >> (x * 2)) & 3) == 1)
0098                 fprintf(stderr, " 1 ");
0099             else if (((tmp >> (x * 2) & 3)) == 2)
0100                 fprintf(stderr, " 2 ");
0101             else
0102                 fprintf(stderr, " 0 ");
0103         }
0104         fprintf(stderr, "\n");
0105     }
0106     fflush(stderr);
0107 }
0108 
0109 // Stream the board
0110 QDataStream &operator<<(QDataStream &s, const AIBoard &board)
0111 {
0112     s << (qint8)board.mCurrent;
0113     for (int i = 0; i < 6; i++)
0114         s << (qint16)board.mBoard[i];
0115     return s;
0116 }
0117 
0118 // Stream the board
0119 QDataStream &operator>>(QDataStream &s, AIBoard &board)
0120 {
0121     qint8 tmp8;
0122     qint16 tmp16;
0123     s >> tmp8;
0124     board.mCurrent = tmp8;
0125     for (int i = 0; i < 6; i++) {
0126         s >> tmp16;
0127         board.mBoard[i] = tmp16;
0128     }
0129     return s;
0130 }
0131 
0132 // Create hashkey for a board
0133 uint qHash(const AIBoard &key)
0134 {
0135     uint h;
0136     h = (key.mCurrent & 1) << 15;
0137 
0138     h += key.mBoard[0];
0139     h += key.mBoard[1] << 1;
0140     h += key.mBoard[2];
0141     h += (~(key.mBoard[3])) & 0x7fff;
0142     h += (~(key.mBoard[4] << 1)) & 0x7fff;
0143     h += (~(key.mBoard[5])) & 0x7fff;
0144 
0145     return h;
0146 }
0147 
0148 // Create a value structure. Fill it with an unused value as
0149 // marker for 'unused'.
0150 AIValue::AIValue()
0151 {
0152     for (int i = 0; i < NO_OF_LEVELS; i++) {
0153         mValue[i] = 0x40000000;
0154     }
0155 }
0156 
0157 // Store a value for a given level.
0158 void AIValue::setValue(int level, long value)
0159 {
0160     if (level < 0 || level >= NO_OF_LEVELS) {
0161         fprintf(stderr, "AIValue::setValue: Level %d not supported\n", level);
0162         fflush(stderr);
0163         return;
0164     }
0165     mValue[level] = value;
0166 }
0167 
0168 // Retrieve a value for a given level.
0169 long AIValue::value(int level) const
0170 {
0171     if (level < 0 || level >= NO_OF_LEVELS) {
0172         fprintf(stderr, "AIValue::value: Level %d not supported\n", level);
0173         fflush(stderr);
0174         return 0;
0175     }
0176     return mValue[level];
0177 }
0178 
0179 // Check whether a given level has a stored value.
0180 bool AIValue::isSet(int level) const
0181 {
0182     if (level < 0 || level >= NO_OF_LEVELS) {
0183         fprintf(stderr, "AIValue::isSet: Level %d not supported\n", level);
0184         fflush(stderr);
0185         return 0;
0186     }
0187     if (mValue[level] == 0x40000000)
0188         return false;
0189     return true;
0190 }
0191 
0192 // Stream a value
0193 QDataStream &operator<<(QDataStream &s, const AIValue &value)
0194 {
0195     for (int i = 0; i < AIValue::NO_OF_LEVELS; i++)
0196         s << (qint32)value.mValue[i];
0197     return s;
0198 }
0199 
0200 // Stream a value
0201 QDataStream &operator>>(QDataStream &s, AIValue &value)
0202 {
0203     qint32 tmp32;
0204     for (int i = 0; i < AIValue::NO_OF_LEVELS; i++) {
0205         s >> tmp32;
0206         value.mValue[i] = tmp32;
0207     }
0208     return s;
0209 }