File indexing completed on 2024-05-19 07:52:01

0001 /*
0002     This file is part of the game 'KJumpingCube'
0003 
0004     SPDX-FileCopyrightText: 1998-2000 Matthias Kiefer <matthias.kiefer@gmx.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "ai_newton.h"
0010 
0011 AI_Newton::AI_Newton()
0012 {
0013 }
0014 
0015 int AI_Newton::assessCube (const int index,         const Player player,
0016                            const int neighbors [4], const Player owners[],
0017                            const int values[],      const int    maxValues[]
0018                           ) const
0019 {
0020    enum Value {StrongerOpponent = HighValue,
0021                TakeOrBeTaken = 1, EqualOpponent, CanTake,
0022                OccupyCorner, OccupyEdge, OccupyCenter,
0023                CanConsolidate,
0024                CanReachMaximum, CanExpand, IncreaseEdge, IncreaseCenter,
0025                PlayHereAnyway};
0026    Player      p         = player;          // This player.
0027    Player      o         = (p == One) ?  Two : One; // The other player.
0028    Player      cOwner    = owners[index];       // This cubes's owner.
0029 
0030    int         pCount = 0;
0031    int         pRank  = 4;
0032    int         oCount = 0;
0033    int         oRank  = 4;
0034    int         cRank  = maxValues[index] - values[index];
0035    int         pos    = 0;
0036 
0037    // Get statistics for neighbors: count and best rank for player and other.
0038    for (int i = 0; i < 4; i++) {
0039       if ((pos = neighbors [i]) < 0) {
0040          continue;          // No neighbor on this side.
0041       }
0042       int rank = maxValues[pos] - values[pos];
0043       if (owners[pos] == p) {       // Neighbor is owned by this player.
0044          pCount++;
0045          pRank = (rank < pRank) ? rank : pRank;
0046       }
0047       else if (owners[pos] == o) {  // Neighbor is owned by other player.
0048          oCount++;
0049          oRank = (rank < oRank) ? rank : oRank;
0050       }
0051       else {                // Otherwise, nobody owns it.
0052          oRank = (rank < oRank) ? rank : oRank;
0053       }
0054    }
0055 
0056    if (oRank < cRank)                    return StrongerOpponent;
0057    // return PlayHereAnyway; // IDW test. Try ALL REASONABLE MOVES.
0058 
0059    if ((cRank <= 0) && (oRank <= 0))     return TakeOrBeTaken;  // Value 1.
0060    if ((cRank == oRank) && (oCount > 0)) return EqualOpponent;  // Value 2.
0061    if ((cRank <= 0) && (oCount > 0))     return CanTake;    // Value 3.
0062 
0063    bool vacant  =  (cOwner == Nobody);
0064    bool nVacant = ((pCount + oCount) == 0);
0065    int  cMax    = maxValues[index];
0066    if (vacant && nVacant && (cMax == 2)) return OccupyCorner;   // Value 4.
0067    if (vacant && nVacant && (cMax == 3)) return OccupyEdge; // Value 5.
0068    if (vacant && nVacant && (cMax == 4)) return OccupyCenter;   // Value 6.
0069    // Sun 2 Dec 2012 - This seems to play well on sizes 3, 5 and 7.
0070    return PlayHereAnyway; // IDW test. Ignore val > 6. Try ALL REASONABLE MOVES.
0071 }