📄 cbeyes.cpp
字号:
/////////////
// CBEyes.cpp : v0020
// Written by : Liu Gang
// Compiler : Microsoft Visual C++ 4.2
// Copyright (C) : 1996 WayAhead Corporation
// v0010 : Feb.26.1997
// v0020 : Apr.29.1997, add so many functions
/////////////
// implementation file
// This file is to give thinking methods information they need.
// so call them Eyes.
#include "stdafx.h"
#include "Assert.h"
#include "CBGame.h"
#include "CBMAP.h"
#include "CBCTrl.h"
#include "CBEyes.h"
#include "CBData.h"
#include "CBRDelay.h"
//added by tian yue
#include <math.h>
/////////////
// externals
// declared in CBMap.cpp
extern POINT MAP_ptSenser[2][MAP_SENSER_MAX][8*MAP_SENSER_MAX];
extern POINT MAP_ptLocation[2][MAP_LOCATION_MAX];
extern int MAP_nLocationNum[4];
/////////////
// 本能策略
/////////////
// 取得本单元附近的(视野内)其它单元的ID
// bFriend : 输入,0——取得所有单元,1——取得我方单元,2——取得敌方单元
// wThis : 输入,本单元ID
// pwArray : 输出,其它单元的ID数组
// nNum : 输入,需要的其它单元的数量;输出,实际返回的单元数量
void EYE_GetUnitInSight( int bFriend, WORD wThis, WORD *pwArray, int *pnNum )
{
struct UNIT_STRUCT *pUnit;
int nSight;
BOOL bOdd;
int nX, nY, nNewX, nNewY;
int nCounter=0;
WORD codeUEx;
WORD *pwCurrent;
pUnit = MAP_GetUnit( wThis );
Assert( pUnit );
nSight = EYE_GetViewRange( &pUnit->Draw );
bOdd = pUnit->Draw.nY%2;
nX = pUnit->Draw.nX, nY = pUnit->Draw.nY;
pwCurrent = pwArray;
for( int i=0; i<nSight; i++ )
for( int j=0; j<((i+1)<<3); j++ )
{
if( nCounter >= *pnNum ) break;
nNewX = nX + MAP_ptSenser[bOdd][i][j].x;
nNewY = nY + MAP_ptSenser[bOdd][i][j].y;
if( EYE_IfOutOfRange( nNewX, nNewY ) )
continue;
codeUEx = MAP_GetUnitDataEx( nNewX, nNewY );
if( codeUEx != MAP_DATA_NONE )
{
if( bFriend == 1 )
{ // 只选择我方
struct UNIT_STRUCT *p = MAP_GetUnit( codeUEx );
Assert( p );
if( pUnit->Draw.nPlayer != p->Draw.nPlayer )
{ // 是敌方,略过
continue;
}
if( EYE_IfUnitIsDead( p ) ) continue;
}
else if( bFriend == 2 )
{ // 只选择敌人
struct UNIT_STRUCT *p = MAP_GetUnit( codeUEx );
Assert( p );
if( EYE_PlayerIsAllied( pUnit->Draw.nPlayer, p->Draw.nPlayer ) )
{// 是同盟者,略过
continue;
}
if( pUnit->Status.nTaskID == MFU )
{// 该部队正在埋伏
continue;
}
//add by tian yue
if( EYE_IfUnitIsDead( p ) ) continue;
}
*pwCurrent = codeUEx;
nCounter++;
pwCurrent++;
}
}
*pnNum = nCounter;
}
// 取得本部队的其它单元的ID
// bFriend : 输入,0——取得所有单元,1——取得我方单元,2——取得敌方单元
// wThis : 输入,本单元ID
// pwArray : 输出,其它单元的ID数组
// nNum : 输入,需要的其它单元的数量;输出,实际返回的单元数量
void EYE_GetUnitInGroup( int bFriend, WORD wThis, WORD *pwArray, int *pnNum )
{
struct UNIT_STRUCT *pUnit;
int nPlayer;
BOOL bOdd;
int nX, nY;
int nCounter=0;
WORD codeUEx;
WORD *pwCurrent;
pUnit = MAP_GetUnit( wThis );
Assert( pUnit );
nPlayer = pUnit->Draw.nPlayer;
if( EYE_IfUnitIsSoldier( pUnit ) )
{
if( pUnit->Soldier.nGenID == MAP_DATA_NONE )
{
*pnNum = 0;
return;
}
wThis = pUnit->Soldier.nGenID; // 把自己变成将领
pUnit = MAP_GetUnit( wThis );
Assert( pUnit );
Assert( pUnit->nType == MAP_UNIT_TYPE_GEN
|| pUnit->nType == MAP_UNIT_TYPE_WGEN
|| pUnit->nType == MAP_UNIT_TYPE_SGEN );
}
bOdd = pUnit->Draw.nY%2;
nX = pUnit->Draw.nX, nY = pUnit->Draw.nY;
pwCurrent = pwArray;
for( int i=0; i<GENERAL_TROOP_MAX; i++ )
{
if( nCounter >= *pnNum ) break;
codeUEx = pUnit->Gen.wTroop[i];
if( codeUEx != MAP_DATA_NONE )
{
if( bFriend == 1 )
{ // 只选择我方
struct UNIT_STRUCT *p = MAP_GetUnit( codeUEx );
Assert( p );
if( pUnit->Draw.nPlayer != p->Draw.nPlayer )
{ // 是敌方,略过
continue;
}
if( EYE_IfUnitIsDead( p ) ) continue;
}
else if( bFriend == 2 )
{ // 只选择敌人
struct UNIT_STRUCT *p = MAP_GetUnit( codeUEx );
Assert( p );
if( EYE_PlayerIsAllied( pUnit->Draw.nPlayer, p->Draw.nPlayer ) )
{// 是同盟者,略过
continue;
}
if( EYE_IfUnitIsDead( p ) ) continue;
}
*pwCurrent = codeUEx;
nCounter++;
pwCurrent++;
}
}
*pnNum = nCounter;
}
// 检测目的单元是否在视野内
// wThis : 本单元ID
// wThat : 目的单元ID
// nRange : 视野范围,缺省(-1)时为第一个单元的视野
// return : -1,不在视野以内,0-7是方向
int EYE_IfUnitIsInSight( WORD wThis, WORD wThat, int nRange/*= -1*/ )
{
struct UNIT_STRUCT *pUnit, *pUnit2;
int nSight;
int nX, nY, bOdd, nXNext, nYNext;
pUnit = MAP_GetUnit( wThis );
Assert( pUnit );
pUnit2 = MAP_GetUnit( wThat );
Assert( pUnit2 );
if( pUnit2->Status.bIRQ == TRUE
&& !EYE_IfUnitIsBuild( pUnit2 ) ) // 士兵在建筑之中,看不见
return -1;
if( nRange > 10 )
{
if( pUnit->Draw.nX > pUnit2->Draw.nX-nRange
&& pUnit->Draw.nY > pUnit2->Draw.nY-nRange
&& pUnit->Draw.nX < pUnit2->Draw.nX+nRange
&& pUnit->Draw.nY < pUnit2->Draw.nY+nRange )
{
return 1;
}
else
return -1;
}
else if( nRange == - 1 )
nSight = EYE_GetViewRange( &pUnit->Draw );
else
nSight = nRange;
bOdd = pUnit->Draw.nY%2;
nX = pUnit->Draw.nX, nY = pUnit->Draw.nY;
for( int i=0; i<nSight; i++ )
for( int j=0; j<((i+1)<<3); j++ )
{
nXNext = nX + MAP_ptSenser[bOdd][i][j].x,
nYNext = nY + MAP_ptSenser[bOdd][i][j].y;
if( EYE_IfOutOfRange( nXNext, nYNext ) )
continue;
WORD codeUEx = MAP_GetUnitDataEx( nXNext, nYNext );
if( codeUEx == wThat )
return (j>>i);
}
return -1;
}
// 检测目的单元是否在攻击范围内
// wThis : 本单元ID
// wThat : 目的单元ID
// nRange : 硬性规定的判定范围,缺省时为部队的攻击范围
// return : -1,不在射程以内,0-7是方向
int EYE_IfUnitIsInRange( WORD wThis, WORD wThat, int nRange/* = -1*/ )
{
struct UNIT_STRUCT *pUnit, *pUnit2;
int nX, nY, bOdd, nXNext, nYNext, bOdd2;
pUnit = MAP_GetUnit( wThis );
Assert( pUnit );
pUnit2 = MAP_GetUnit( wThat );
Assert( pUnit2 );
if( pUnit2->nHasShadow == FALSE
&& !EYE_IfUnitIsBuild( pUnit2 ) ) // 士兵在建筑之中,看不见
return -2;
// 设置判定范围,为-1时为部队的攻击范围
if( nRange == -1 )
{
nRange = DATA_Lib.Unit[pUnit->Draw.nFile].nFightRange;
if( CTRL_GetSTG( &pUnit->Draw, GUNMU ) == TRUE
&& (pUnit->Draw.nFile == 32 || pUnit->Draw.nFile == 45) )
{ // 使用滚木计谋,攻击范围是视野
nRange = DATA_Lib.Unit[pUnit->Draw.nFile].nViewRange;
}
}
bOdd = pUnit->Draw.nY&1;
nX = pUnit->Draw.nX, nY = pUnit->Draw.nY;
// 对于远程攻击部队,只判断实在点的位置,以加快判断速度
if( nRange > 1 )
{
for( int i=0; i<nRange; i++ )
for( int j=0; j<((i+1)<<3); j++ )
{
nXNext = nX + MAP_ptSenser[bOdd][i][j].x,
nYNext = nY + MAP_ptSenser[bOdd][i][j].y;
if( EYE_IfOutOfRange( nXNext, nYNext ) )
continue;
WORD codeUEx = MAP_GetUnitDataEx( nXNext, nYNext );
if( codeUEx == wThat )
{ // 得到方向
j = j/(i+1);
return j;
}
}
}
else
{ // 对于近程攻击部队,要判断该部队所占据的所有点
for( int x=0; x< MAP_nLocationNum[pUnit->Draw.nLocationSize]; x++ )
{
nX = pUnit->Draw.nX+MAP_ptLocation[bOdd][x].x,
nY = pUnit->Draw.nY+MAP_ptLocation[bOdd][x].y;
if( EYE_IfOutOfRange( nX, nY ) )
continue;
bOdd2 = nY&1;
for( int j=0; j<8; j++ )
{
nXNext = nX + MAP_ptSenser[bOdd2][0][j].x,
nYNext = nY + MAP_ptSenser[bOdd2][0][j].y;
if( EYE_IfOutOfRange( nXNext, nYNext ) )
continue;
WORD codeUEx = MAP_GetUnitDataEx( nXNext, nYNext );
if( codeUEx == wThat )
return j;
}
}
}
return -1;
}
// 检测目的位置是否在某单元位置一格范围内
// pUnit : 被检测的单元
// nEndX, nEndY : 被检测的目的地形位置
// return : -1,不在射程以内,0-7是方向
int EYE_IfShipYardIsInRange( struct UNIT_STRUCT *pUnit, int nEndX, int nEndY )
{
BOOL bOdd = pUnit->Draw.nY&1;
BOOL bOdd2 = nEndY&1;
WORD codeG;
struct MAP_GROUND_CODE_STRUCT stctG;
int nX, nY, nX2, nY2;
for( int i=0; i<8; i++ )
{
nX = pUnit->Draw.nX+MAP_ptSenser[bOdd][0][i].x,
nY = pUnit->Draw.nY+MAP_ptSenser[bOdd][0][i].y;
for( int j=0; j<9; j++ )
{
nX2 = nEndX + MAP_ptLocation[bOdd2][j].x,
nY2 = nEndY + MAP_ptLocation[bOdd2][j].y;
if( nX == nX2 && nY == nY2 )
return i;
}
codeG = MAP_GetGroundData( 0, nX, nY );
Assert( codeG!= MAP_DATA_NONE );
MAP_GroundDeCode( codeG, &stctG );
if( stctG.nFile == 3 )// 岸边
return i;
}
return -1;
}
/////////////
/////////////
// 检测该单元是否是有效
inline BOOL EYE_IfUnitIsUnit( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType != MAP_UNIT_TYPE_NONE ) // 无类型
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是建筑
inline BOOL EYE_IfUnitIsBuild( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_BUILDING // 建筑
|| pUnit->nType == MAP_UNIT_TYPE_RESOURCE // 资源
|| pUnit->nType == MAP_UNIT_TYPE_FLAG // 大旗
|| pUnit->nType == MAP_UNIT_TYPE_SHIPYARD // 船坞
)
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是将领
inline BOOL EYE_IfUnitIsGen( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_GEN
|| pUnit->nType == MAP_UNIT_TYPE_WGEN
|| pUnit->nType == MAP_UNIT_TYPE_SGEN ) // 将领
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是文将
inline BOOL EYE_IfUnitIsWorkerGen( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
//if( pUnit->Draw.nFile == 29 ) // 文将
if( pUnit->nType == MAP_UNIT_TYPE_WGEN ) // 将领
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是工人
inline BOOL EYE_IfUnitIsWorker( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_WORKER ) // 工人
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是平民
inline BOOL EYE_IfUnitIsMan( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_MAN ) // 平民
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是资源
inline BOOL EYE_IfUnitIsRes( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_RESOURCE )// 资源
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否是特殊图素
inline BOOL EYE_IfUnitIsSpec( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_SPECIAL ) // 特殊图素
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否有Soldier域,可以组建成部队
inline BOOL EYE_IfUnitIsSoldier( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_SOLDIER // 士兵
|| pUnit->nType == MAP_UNIT_TYPE_SHIP // 战船
|| pUnit->nType == MAP_UNIT_TYPE_LADDER // 云梯
|| pUnit->nType == MAP_UNIT_TYPE_WORKER // 工人
|| pUnit->nType == MAP_UNIT_TYPE_MAN // 平民
)
{
return TRUE;
}
return FALSE;
}
// 检测该单元是否可以移动
inline BOOL EYE_IfUnitIsMovable( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->nType == MAP_UNIT_TYPE_SOLDIER // 士兵
|| pUnit->nType == MAP_UNIT_TYPE_SHIP // 战船
|| pUnit->nType == MAP_UNIT_TYPE_LADDER // 云梯
|| pUnit->nType == MAP_UNIT_TYPE_GEN // 将领
|| pUnit->nType == MAP_UNIT_TYPE_SGEN // 水军将领
|| pUnit->nType == MAP_UNIT_TYPE_WGEN // 文将
|| pUnit->nType == MAP_UNIT_TYPE_MAN // 平民
|| pUnit->nType == MAP_UNIT_TYPE_WORKER // 工人
)
{
return TRUE;
}
return FALSE;
}
// 查看该单元是否是弓箭手
inline BOOL EYE_IfUnitIsArcher( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->Draw.nFile == 33
|| pUnit->Draw.nFile == 45
|| pUnit->Draw.nFile == 39
|| pUnit->Draw.nFile == 42
|| pUnit->Draw.nFile == 44 )
{
return TRUE;
}
return FALSE;
}
// 查看该单元是否是箭楼
inline BOOL EYE_IfUnitIsTower( struct UNIT_STRUCT *pUnit )
{
Assert( pUnit );
if( pUnit->Draw.nFile == 18
|| pUnit->Draw.nFile == 19 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -