Не могу решить проблему – неконтролируемая инкрементация в моей игре внутри цикла for – игрок, который выполняет команду, каким-то образом умножает повстанцев.

Вопрос или проблема

Ок, я знаю, я знаю. Игра действительно старая, код ужасен, сервер работает на баклажане с облезлой кожурой и так далее. Нам нужно освежить подачу на Салат латук сервера, yadda yadda.

Ситуация такова. Игрок, в данном случае blueguyz, выдаёт команду “поп rebel”. В этом случае игрок выпускает 34 повстанца с квадрата 43. Это означает, что 34 повстанца покидают квадрат и случайным образом распродаются по другим квадратам. Проблема в том, что у игрока, который выполняет команду, количество повстанцев резко увеличивается. Существуют 2 таблицы – Игроки и Квадраты. Ошибка возникает в таблице Игроков. КАК это происходит? КАК у blueguyz количество повстанцев растёт до более чем 1,600? Оно должно быть очень низким, менее 50. Любая помощь будет оценена!

$totalSquares = 44; // количество увеличивается по мере расширения сетки
$multipliedRebs = 34; // это число может достигать 50

// определите квадраты, чтобы разместить новых повстанцев
for ($i = 0; $i < $multipliedRebs; $i++)
{
     $randSquares[$i] = rand(1, $totalSquares);
     $squareList .= $randSquares[$i] . ", ";

     // id игрока, которого затрагивает квадрат из таблицы Квадратов
     $args = runQuery(" FROM Squares WHERE id = '$randSquares[$i]'", "owner,rebels,ownerId,farms,cities,units,permanent", false, false);
     $values = explode(",", $args);
     $p2Name = $values[0];
     $p2Rebels = $values[1];
     $p2OwnerId = $values[2];
     $p2Farms = $values[3];
     $p2Cities = $values[4];
     $p2Units = $values[5];
     $p2Permanent = $values[6];

     if ($p2Rebels < 100) {

         // id игрока, который затрагивается из таблицы Игроков
         $args = runQuery(" FROM Players WHERE id = '$p2OwnerId'", "name,rebels,color,borderColor,id", false, false);
         $values = explode(",", $args);
         $p2NameP = $values[0];
         $p2RebelsP = $values[1];
         $p2ColorP = $values[2];
         $p2BorderColorP = $values[3];
         $p2IdP = $values[4];

         if ($p2IdP == "")
         {
            $logMessage .= " Извините. произошла системная ошибка. Пожалуйста, попробуйте команду снова.";
            $failed = true;
            break;
         }

         // обновите таблицу Квадратов
         $p2Rebels += 1;
         $sql = "UPDATE Squares SET rebels="$p2Rebels" WHERE id = '$randSquares[$i]'";
         if (!mysql_query($sql))  
            $textObj->logError($sql);   

         // обновите таблицу Игроков
         // ИМЕННО ТУТ У ИГРОКА, ВЫДАЮЩЕГО КОМАНДУ, УВЕЛИЧИВАЕТСЯ КОЛИЧЕСТВО ПОВСТАНЦЕВ
         $p2RebelsP += 1;
         $sql = "UPDATE Players SET rebels="$p2RebelsP" WHERE id = '$p2IdP'";
         if (!mysql_query($sql))  
            $textObj->logError($sql);   

         
      }
}

Я не вижу ничего плохого в коде. $p2RebelsP += 1; // он просто добавляет 1 повстанца на каждой итерации, верно? посмотрите визуализацию здесь

Игровой сервер здесь http://codeelf.com/games/the-grid-2/grid/

Ответ или решение

Доброго дня!

Я понимаю, что данная проблема может быть запутанной, и, возможно, её источник неочевиден. Давайте внимательно разберёмся с вашим кодом и выясним, почему количество восставших (rebels) у игрока, который выполняет команду «pop rebels», увеличивается до таких масштабов.

Анализ проблемы

В вашем коде видно, что вы перебираете количество восставших (34 в данном случае) и выполняете определенные действия для каждой итерации цикла. Проблема может заключаться в неправильной идентификации игрока при обновлении таблицы Players. Давайте разберёмся в этом подробнее.

  1. Переменная $p2IdP: Вы получаете идентификатор владельца площади из таблицы Squares. Далее вы используете этот идентификатор для обновления таблицы Players. Если это действительно идентификатор соперника (не игрока, который инициировал команду), то это может вызвать увеличение числа восставших у другого игрока, что может объяснить, почему количество восставших у blueguyz увеличивается.

  2. Логика обновления: Вы выполняете обновление для игрока, у которого меньше 100 восставших. Это может приводить к ситуации, когда несколько итераций цикла обновляют одну и ту же запись в таблице Players, если несколько случайных квадратов имеют одного и того же владельца.

Рекомендации по исправлению

  1. Проверка идентификатора владельца: Убедитесь, что вы обновляете записи только для правильного игрока. Возможно, вам следует убедиться, что $p2IdP не равен идентификатору игрока, который инициировал действие, чтобы не изменять его игровой прогресс.

  2. Изменение логики обновления: Вместо того чтобы обновлять записи в Players для каждого восставшего сразу, рассмотрите возможность обновления только один раз после завершения цикла, где вы накопите количество восставших для каждого игрока.

Пример исправленного кода

Вот пример подхода, который учитывает вышесказанное:

$totalSquares = 44; // количество квадратов
$multipliedRebs = 34; // количество восставших

$updates = []; // массив для накопления изменений

// определяем квадраты для размещения новых восставших
for ($i = 0; $i < $multipliedRebs; $i++) {
    $randSquare = rand(1, $totalSquares);
    $squareList .= $randSquare . ", ";

    // Получаем информацию о квадрате
    $args = runQuery(" FROM Squares WHERE id = '$randSquare'", "owner, rebels, ownerId", false, false);
    $values = explode(",", $args);
    $p2OwnerId = $values[2];
    $p2Rebels = $values[1];

    if ($p2Rebels < 100) {
        // Увеличиваем количество восставших для квадрата
        $p2Rebels += 1;
        $sql = "UPDATE Squares SET rebels='$p2Rebels' WHERE id = '$randSquare'";
        if (!mysql_query($sql))  
            $textObj->logError($sql);   

        // Увеличиваем количество восставших для игрока
        if (!isset($updates[$p2OwnerId])) {
            $updates[$p2OwnerId] = 0; // Инициализируем счетчик для игрока
        }
        $updates[$p2OwnerId] += 1; // Увеличиваем количество восставших для этого игрока
    }
}

// Обновляем количество восставших для каждого игрока один раз
foreach ($updates as $ownerId => $count) {
    $args = runQuery(" FROM Players WHERE id = '$ownerId'", "rebels", false, false);
    $values = explode(",", $args);
    $currentRebels = $values[0];

    $currentRebels += $count;
    $sql = "UPDATE Players SET rebels='$currentRebels' WHERE id = '$ownerId'";
    if (!mysql_query($sql))  
        $textObj->logError($sql);   
}

Заключение

Этот подход должен помочь избежать многократного увеличения восставших у одного и того же игрока за одну команду. Убедитесь, что вы тестируете обновлённый код, чтобы убедиться в его правильной работе. Если у вас возникнут дополнительные вопросы или потребуется дальнейшая помощь, не стесняйтесь обращаться.

Удачи с вашим проектом!

Оцените материал
Добавить комментарий

Капча загружается...