Hikayeler

Reklam vermek için turkmmo@gmail.com

ITJA - SATRANC OYUN SİSTEMİ (FULL SYSTEM - FULL UI)

Metin2 EP, Valorant VP dahil tüm oyun ürünlerini en uygun fiyatlarla bulabilir, Item ve Karakterlerinizi hızlıca satabilirsiniz. HEMEN TIKLA!

kodunuzda leak mevcut,

=============

C++:
void CChessManager::StartBot(LPCHARACTER pkChr)
{
    CChessGame* pkGame = new CChessGame(pkChr, NULL, true);
    m_mapGames[pkChr->GetPlayerID()] = pkGame; // leak
    pkGame->SendGameState(pkChr);
}

"StartBot" fonksiyonunu aynı oyuncu birden fazla kez invoke ederse sırayla şunlar gerçekleşir;
-> "m_mapGames" içinde alakalı player id aranır
-> alakalı containerda bu id key olarak tutuluyorsa square brackets(köşeli parantez) operatörü bir "mapped_type&"(lvalue ref) döner, yani sizin durumunuzda (CChessGame*&)
-> ilk invoke'da sorun yok, keyi bulamaz, id'yi containera ekler ve değeri value-initialize eder(bu durumda bir ptr zero-initialized edildiğinde nullptr olur) sonrasında bir value-copy gerçekleşir
-> containerdan silinmeden önce ikinci kez invokelarsa heapde yeni bir alan oluşturup, keyin artık bu objeyi göstermesine sebep olur
-> ve artık eski göstediği alan serbest bırakılmamış olur, bildiğiniz leak hikayesi


keza "Accept" member functionda da aynı durum var.

================

aynı anda iki davet atılabilir gibi duruyor

================

C++:
                for (int dy = -1; dy <= 1; ++dy)
                {
                    for (int dx = -1; dx <= 1; ++dx)


bu kontrol sanki oyunu kilitleyebilir gibi duruyor, 1 karelik alan kontrol edilmiş sadece

ufak bir göz gezdirmede göze çarpanlar bunlar; şahsi algılamayın ama lütfen Modern C++ kullanın ve "design" konusunun üzerinde durun, şu an pek kullanılabilir durumda gibi görünmüyor şahsımca.

elinize sağlık.
AKTARDIĞINIZ LEAK VE HATA fixlenmiştir.

chess.cpp:
#include "stdafx.h"
#i[HASH=2388]#include[/HASH]chess.h"
#i[HASH=2388]#include[/HASH]char.h"
#i[HASH=2388]#include[/HASH]packet.h"
#i[HASH=2388]#include[/HASH]desc.h"
#i[HASH=2388]#include[/HASH]char_manager.h"
#i[HASH=2388]#include[/HASH]utils.h"

#i[HASH=2]#ifdef[/HASH]NABLE_CHESS_SYSTEM

CChessGame::CChessGame(LPCHARACTER pkWhite, LPCHARACTER pkBlack, bool bIsBot)
    : m_pkWhite(pkWhite), m_pkBlack(pkBlack), m_bIsBot(bIsBot), m_bWhiteTurn(true)
{
    InitializeBoard();
}

CChessGame::~CChessGame()
{
}

void CChessGame::InitializeBoard()
{
    memset(m_board, 0, sizeof(m_board));

    // White pieces
    m_board[0][0] = CHESS_PIECE_W_ROOK;
    m_board[0][1] = CHESS_PIECE_W_KNIGHT;
    m_board[0][2] = CHESS_PIECE_W_BISHOP;
    m_board[0][3] = CHESS_PIECE_W_QUEEN;
    m_board[0][4] = CHESS_PIECE_W_KING;
    m_board[0][5] = CHESS_PIECE_W_BISHOP;
    m_board[0][6] = CHESS_PIECE_W_KNIGHT;
    m_board[0][7] = CHESS_PIECE_W_ROOK;
    for (int i = 0; i < 8; ++i) m_board[1][i] = CHESS_PIECE_W_PAWN;

    // Black pieces
    m_board[7][0] = CHESS_PIECE_B_ROOK;
    m_board[7][1] = CHESS_PIECE_B_KNIGHT;
    m_board[7][2] = CHESS_PIECE_B_BISHOP;
    m_board[7][3] = CHESS_PIECE_B_QUEEN;
    m_board[7][4] = CHESS_PIECE_B_KING;
    m_board[7][5] = CHESS_PIECE_B_BISHOP;
    m_board[7][6] = CHESS_PIECE_B_KNIGHT;
    m_board[7][7] = CHESS_PIECE_B_ROOK;
    for (int i = 0; i < 8; ++i) m_board[6][i] = CHESS_PIECE_B_PAWN;
}

bool CChessGame::MakeMove(LPCHARACTER pkChr, int from_x, int from_y, int to_x, int to_y)
{
    bool bWhite = (pkChr == m_pkWhite);
    if (bWhite != m_bWhiteTurn) return false;

    if (!IsValidMove(from_x, from_y, to_x, to_y, bWhite)) return false;

    m_board[to_y][to_x] = m_board[from_y][from_x];
    m_board[from_y][from_x] = CHESS_PIECE_EMPTY;

    m_bWhiteTurn = !m_bWhiteTurn;

    SendMove(m_pkWhite, from_x, from_y, to_x, to_y);
    if (!m_bIsBot && m_pkBlack) SendMove(m_pkBlack, from_x, from_y, to_x, to_y);

    if (m_bIsBot && !m_bWhiteTurn)
    {
        ExecuteBotMove();
    }

    return true;
}

bool CChessGame::IsValidMove(int from_x, int from_y, int to_x, int to_y, bool bWhite)
{
    if (from_x < 0 || from_x > 7 || from_y < 0 || from_y > 7) return false;
    if (to_x < 0 || to_x > 7 || to_y < 0 || to_y > 7) return false;

    BYTE piece = m_board[from_y][from_x];
    if (piece == CHESS_PIECE_EMPTY) return false;

    bool bPieceWhite = (piece >= CHESS_PIECE_W_PAWN && piece <= CHESS_PIECE_W_KING);
    if (bPieceWhite != bWhite) return false;

    // Basic check: can't move to a square occupied by your own piece
    BYTE target = m_board[to_y][to_x];
    if (target != CHESS_PIECE_EMPTY)
    {
        bool bTargetWhite = (target >= CHESS_PIECE_W_PAWN && target <= CHESS_PIECE_W_KING);
        if (bTargetWhite == bWhite) return false;
    }

    // For now, allow all moves that aren't to the same square
    if (from_x == to_x && from_y == to_y) return false;

    int dx = to_x - from_x;
    int dy = to_y - from_y;
    int abs_dx = abs(dx);
    int abs_dy = abs(dy);

    switch (piece)
    {
    case CHESS_PIECE_W_PAWN:
        if (dx == 0)
        {
            if (dy == 1 && target == CHESS_PIECE_EMPTY) return true;
            if (from_y == 1 && dy == 2 && target == CHESS_PIECE_EMPTY && m_board[2][from_x] == CHESS_PIECE_EMPTY) return true;
        }
        else if (abs_dx == 1 && dy == 1 && target != CHESS_PIECE_EMPTY) return true;
        return false;

    case CHESS_PIECE_B_PAWN:
        if (dx == 0)
        {
            if (dy == -1 && target == CHESS_PIECE_EMPTY) return true;
            if (from_y == 6 && dy == -2 && target == CHESS_PIECE_EMPTY && m_board[5][from_x] == CHESS_PIECE_EMPTY) return true;
        }
        else if (abs_dx == 1 && dy == -1 && target != CHESS_PIECE_EMPTY) return true;
        return false;

    case CHESS_PIECE_W_KNIGHT:
    case CHESS_PIECE_B_KNIGHT:
        return (abs_dx == 1 && abs_dy == 2) || (abs_dx == 2 && abs_dy == 1);

    case CHESS_PIECE_W_BISHOP:
    case CHESS_PIECE_B_BISHOP:
        if (abs_dx != abs_dy) return false;
        break; // Check path below

    case CHESS_PIECE_W_ROOK:
    case CHESS_PIECE_B_ROOK:
        if (dx != 0 && dy != 0) return false;
        break; // Check path below

    case CHESS_PIECE_W_QUEEN:
    case CHESS_PIECE_B_QUEEN:
        if (abs_dx != abs_dy && dx != 0 && dy != 0) return false;
        break; // Check path below

    case CHESS_PIECE_W_KING:
    case CHESS_PIECE_B_KING:
        return abs_dx <= 1 && abs_dy <= 1;

    default:
        return false;
    }

    // Path checking for sliding pieces (Bishop, Rook, Queen)
    int step_x = (dx == 0) ? 0 : (dx > 0 ? 1 : -1);
    int step_y = (dy == 0) ? 0 : (dy > 0 ? 1 : -1);
    int cur_x = from_x + step_x;
    int cur_y = from_y + step_y;

    while (cur_x != to_x || cur_y != to_y)
    {
        if (m_board[cur_y][cur_x] != CHESS_PIECE_EMPTY) return false;
        cur_x += step_x;
        cur_y += step_y;
    }

    return true;
}

void CChessGame::ExecuteBotMove()
{
    // Search all pieces
    for (int y = 7; y >= 0; --y)
    {
        for (int x = 0; x < 8; ++x)
        {
            BYTE piece = m_board[y][x];
            if (piece >= CHESS_PIECE_B_PAWN && piece <= CHESS_PIECE_B_KING)
            {
                // Check all board squares for a valid move instead of just adjacent ones
                for (int ty = 0; ty < 8; ++ty)
                {
                    for (int tx = 0; tx < 8; ++tx)
                    {
                        if (IsValidMove(x, y, tx, ty, false))
                        {
                            m_board[ty][tx] = m_board[y][x];
                            m_board[y][x] = CHESS_PIECE_EMPTY;
                            m_bWhiteTurn = true;
                            SendMove(m_pkWhite, x, y, tx, ty);
                            return;
                        }
                    }
                }
            }
        }
    }
}

void CChessGame::SendGameState(LPCHARACTER pkChr)
{
    if (!pkChr || !pkChr->GetDesc()) return;

    TPacketGCChess pack;
    pack.header = HEADER_GC_CHESS;
    pack.subheader = CHESS_SUBHEADER_GC_START;
    pack.arg1 = m_bIsBot ? 1 : 0;
    pack.arg2 = m_bWhiteTurn ? 1 : 0;
    strlcpy(pack.szName, m_pkBlack ? m_pkBlack->GetName() : "Bot", sizeof(pack.szName));
    pkChr->GetDesc()->Packet(&pack, sizeof(pack));

    // Send board state
    for (int y = 0; y < 8; ++y)
    {
        for (int x = 0; x < 8; ++x)
        {
            if (m_board[y][x] != CHESS_PIECE_EMPTY)
            {
                TPacketGCChess update;
                update.header = HEADER_GC_CHESS;
                update.subheader = CHESS_SUBHEADER_GC_UPDATE;
                update.arg1 = (x << 8) | y;
                update.arg2 = m_board[y][x];
                pkChr->GetDesc()->Packet(&update, sizeof(update));
            }
        }
    }
}

void CChessGame::SendMove(LPCHARACTER pkChr, int from_x, int from_y, int to_x, int to_y)
{
    if (!pkChr || !pkChr->GetDesc()) return;

    TPacketGCChess pack;
    pack.header = HEADER_GC_CHESS;
    pack.subheader = CHESS_SUBHEADER_GC_MOVE;
    pack.arg1 = (from_x << 8) | from_y;
    pack.arg2 = (to_x << 8) | to_y;
    pkChr->GetDesc()->Packet(&pack, sizeof(pack));
}

CChessManager::CChessManager()
{
}

CChessManager::~CChessManager()
{
}

void CChessManager::Invite(LPCHARACTER pkChr, const char* szName)
{
    LPCHARACTER pkTarget = CHARACTER_MANAGER::instance().FindPC(szName);
    if (!pkTarget)
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "Target not found.");
        return;
    }

    if (pkTarget == pkChr)
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "You cannot invite yourself.");
        return;
    }

    // Check if already in a game
    if (m_mapGames.find(pkChr->GetPlayerID()) != m_mapGames.end())
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "You are already in a game.");
        return;
    }
    
    if (m_mapGames.find(pkTarget->GetPlayerID()) != m_mapGames.end())
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "Target player is already in a game.");
        return;
    }

    // Restrict multiple invitations overriding
    if (m_mapInvitations.find(pkChr->GetPlayerID()) != m_mapInvitations.end())
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "You already have a pending invitation sent.");
        return;
    }

    m_mapInvitations[pkChr->GetPlayerID()] = pkTarget->GetPlayerID();

    TPacketGCChess pack;
    pack.header = HEADER_GC_CHESS;
    pack.subheader = CHESS_SUBHEADER_GC_INVITE;
    strlcpy(pack.szName, pkChr->GetName(), sizeof(pack.szName));
    pkTarget->GetDesc()->Packet(&pack, sizeof(pack));

    pkChr->ChatPacket(CHAT_TYPE_INFO, "Invitation sent to %s.", szName);
}

void CChessManager::Accept(LPCHARACTER pkChr, const char* szName)
{
    LPCHARACTER pkInviter = CHARACTER_MANAGER::instance().FindPC(szName);
    if (!pkInviter) return;

    auto it = m_mapInvitations.find(pkInviter->GetPlayerID());
    if (it == m_mapInvitations.end() || it->second != pkChr->GetPlayerID()) return;

    m_mapInvitations.erase(it);

    // Prevent leak: do not accept if either player is already in a game
    if (m_mapGames.find(pkInviter->GetPlayerID()) != m_mapGames.end() ||
        m_mapGames.find(pkChr->GetPlayerID()) != m_mapGames.end())
    {
        pkChr->ChatPacket(CHAT_TYPE_INFO, "One of the players is already in a game.");
        return;
    }

    CChessGame* pkGame = new CChessGame(pkInviter, pkChr);
    m_mapGames[pkInviter->GetPlayerID()] = pkGame;
    m_mapGames[pkChr->GetPlayerID()] = pkGame;

    pkGame->SendGameState(pkInviter);
    pkGame->SendGameState(pkChr);
}

void CChessManager::Decline(LPCHARACTER pkChr, const char* szName)
{
    LPCHARACTER pkInviter = CHARACTER_MANAGER::instance().FindPC(szName);
    if (!pkInviter) return;

    m_mapInvitations.erase(pkInviter->GetPlayerID());
    pkInviter->ChatPacket(CHAT_TYPE_INFO, "%s declined your invitation.", pkChr->GetName());
}

void CChessManager::StartBot(LPCHARACTER pkChr)
{
    // Fix memory leak: end the previous game if the player asks for a new bot game
    auto it = m_mapGames.find(pkChr->GetPlayerID());
    if (it != m_mapGames.end())
    {
        Quit(pkChr); // Gracefully terminate the old game to release memory
    }

    CChessGame* pkGame = new CChessGame(pkChr, NULL, true);
    m_mapGames[pkChr->GetPlayerID()] = pkGame;
    pkGame->SendGameState(pkChr);
}

void CChessManager::Move(LPCHARACTER pkChr, int from_x, int from_y, int to_x, int to_y)
{
    auto it = m_mapGames.find(pkChr->GetPlayerID());
    if (it == m_mapGames.end()) return;

    it->second->MakeMove(pkChr, from_x, from_y, to_x, to_y);
}

void CChessManager::Quit(LPCHARACTER pkChr)
{
    auto it = m_mapGames.find(pkChr->GetPlayerID());
    if (it == m_mapGames.end()) return;

    CChessGame* pkGame = it->second;
    LPCHARACTER pkWhite = pkGame->GetWhitePlayer();
    LPCHARACTER pkBlack = pkGame->GetBlackPlayer();

    if (pkWhite) m_mapGames.erase(pkWhite->GetPlayerID());
    if (pkBlack) m_mapGames.erase(pkBlack->GetPlayerID());

    delete pkGame;
}

void CChessManager::OnLogout(LPCHARACTER pkChr)
{
    Quit(pkChr);
    m_mapInvitations.erase(pkChr->GetPlayerID());
}

#e[HASH=3]#endif[/HASH]/CODE]
 
kodunuzda leak mevcut,

=============

C++:
void CChessManager::StartBot(LPCHARACTER pkChr)
{
    CChessGame* pkGame = new CChessGame(pkChr, NULL, true);
    m_mapGames[pkChr->GetPlayerID()] = pkGame; // leak
    pkGame->SendGameState(pkChr);
}

"StartBot" fonksiyonunu aynı oyuncu birden fazla kez invoke ederse sırayla şunlar gerçekleşir;
-> "m_mapGames" içinde alakalı player id aranır
-> alakalı containerda bu id key olarak tutuluyorsa square brackets(köşeli parantez) operatörü bir "mapped_type&"(lvalue ref) döner, yani sizin durumunuzda (CChessGame*&)
-> ilk invoke'da sorun yok, keyi bulamaz, id'yi containera ekler ve değeri value-initialize eder(bu durumda bir ptr zero-initialized edildiğinde nullptr olur) sonrasında bir value-copy gerçekleşir
-> containerdan silinmeden önce ikinci kez invokelarsa heapde yeni bir alan oluşturup, keyin artık bu objeyi göstermesine sebep olur
-> ve artık eski göstediği alan serbest bırakılmamış olur, bildiğiniz leak hikayesi


keza "Accept" member functionda da aynı durum var.

================

aynı anda iki davet atılabilir gibi duruyor

================

C++:
                for (int dy = -1; dy <= 1; ++dy)
                {
                    for (int dx = -1; dx <= 1; ++dx)


bu kontrol sanki oyunu kilitleyebilir gibi duruyor, 1 karelik alan kontrol edilmiş sadece

ufak bir göz gezdirmede göze çarpanlar bunlar; şahsi algılamayın ama lütfen Modern C++ kullanın ve "design" konusunun üzerinde durun, şu an pek kullanılabilir durumda gibi görünmüyor şahsımca.

elinize sağlık.
Yapay zeka hata yapmış yapıyor arada öyle şeyler kusuruna bakmayın mxkxxkdjxkd
 

Şu an konuyu görüntüleyenler (Toplam : 1, Üye: 0, Misafir: 1)

Geri
Üst