File indexing completed on 2024-09-08 06:48:19

0001 /*
0002     SPDX-FileCopyrightText: 2003 Russell Steffen <rsteffen@bayarea.net>
0003     SPDX-FileCopyrightText: 2003 Stephan Zehetner <s.zehetner@nevox.org>
0004     SPDX-FileCopyrightText: 2006 Dmitry Suzdalev <dimsuz@gmail.com>
0005     SPDX-FileCopyrightText: 2006 Inge Wallin <inge@lysator.liu.se>
0006     SPDX-FileCopyrightText: 2006 Pierre Ducroquet <pinaraf@pinaraf.info>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "default.h"
0012 #include "../../../game.h"
0013 #include "../../../planet.h"
0014 
0015 #include <QDebug>
0016 #include <cmath>
0017 #include <cfloat>
0018 
0019 AiDefault::AiDefault(Game *game,
0020                                const QString &newName,
0021                                const QColor &color,
0022                                AiLevel level)
0023     : ComputerPlayer(game, newName, color),
0024     m_level(level)
0025 {
0026 
0027 }
0028 
0029 
0030 void AiDefault::play()
0031 {
0032     //qDebug() << "computer playing";
0033     int      ships = 0, minimumShips =10, shipCountFactor = 2;
0034     Planet  *target = nullptr;
0035 
0036     switch (m_level)
0037     {
0038     case Weak:
0039        minimumShips = 20;
0040        shipCountFactor = 2;
0041        break;
0042     case Normal: // Offensive
0043        minimumShips = 10;
0044        shipCountFactor = 2;
0045        break;
0046     case Hard: // Defensive
0047        minimumShips = 30;
0048        shipCountFactor = 3;
0049        break;
0050     }
0051 
0052     for (Planet *home : m_game->planets()) {
0053         if (home->player() == this) {
0054             ships = (int)floor(home->ships() * 0.7 );
0055 
0056             if (ships >= minimumShips) {
0057                 bool hasAttack = false;
0058                 double  minDistance = 100;
0059 
0060                 for (Planet *attack : m_game->planets()) {
0061                     if (attack->player() == this)
0062                         continue;
0063 
0064                     bool    skip = false;
0065                     double  dist = m_game->map()->distance( home, attack );
0066 
0067                     if (dist < minDistance && attack->ships() < ships ) {
0068                         for (AttackFleet *curFleet : attackList()) {
0069                             if (curFleet->destination == attack) {
0070                                 skip = true;
0071                                 break;
0072                             }
0073                         }
0074                         if (skip)
0075                             continue;
0076 
0077                         target      = attack;
0078                         hasAttack   = true;
0079                         minDistance = dist;
0080                     }
0081                 }
0082 
0083                 if (hasAttack) {
0084                     m_game->attack( home, target, ships );
0085                 } else {
0086                     minDistance = DBL_MAX;
0087                     int shipsToSend = 0;
0088                     bool hasDestination = false;
0089 
0090                     for (Planet *attack : m_game->planets()) {
0091                         bool    skip = false;
0092                         double  dist = m_game->map()->distance( home, attack );
0093                         int     homeships = (int)floor(home->ships() * 0.5 );
0094 
0095                         if (dist < minDistance
0096                             && attack->player() == this
0097                             && attack->ships() < homeships ) {
0098                             for (AttackFleet *curFleet : attackList()) {
0099                                 if (curFleet->destination == attack) {
0100                                     skip = true;
0101                                     break;
0102                                 }
0103                             }
0104                             if (skip)
0105                                 continue;
0106 
0107                             shipsToSend = (int)floor( double(home->ships()
0108                                                              - attack->ships()) / shipCountFactor);
0109 
0110                             target         = attack;
0111                             hasDestination = true;
0112                             minDistance    = dist;
0113                         }
0114                     }
0115                     if (hasDestination) {
0116                         m_game->attack( home, target, shipsToSend );
0117                     }
0118                 }
0119             }
0120         }
0121     }
0122     Q_EMIT donePlaying();
0123 }