- Katılım
- 23 Haz 2010
- Konular
- 57
- Mesajlar
- 310
- Online süresi
- 1ay 77198s
- Reaksiyon Skoru
- 190
- Altın Konu
- 0
- Başarım Puanı
- 149
- Yaş
- 28
- TM Yaşı
- 15 Yıl 10 Ay 3 Gün
- MmoLira
- 4,530
- DevLira
- 36
Metin2 EP, Valorant VP dahil tüm oyun ürünlerini en uygun fiyatlarla bulabilir, Item ve Karakterlerinizi hızlıca satabilirsiniz. HEMEN TIKLA!
AKTARDIĞINIZ LEAK VE HATA fixlenmiştir.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.
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]
- Katılım
- 20 Eki 2017
- Konular
- 468
- Mesajlar
- 9,365
- Online süresi
- 11ay 26g
- Reaksiyon Skoru
- 8,223
- Altın Konu
- 47
- Başarım Puanı
- 326
- Yaş
- 25
- TM Yaşı
- 8 Yıl 6 Ay 2 Gün
- MmoLira
- 93,217
- DevLira
- 242
Yapay zeka hata yapmış yapıyor arada öyle şeyler kusuruna bakmayın mxkxxkdjxkdkodunuzda 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.



