📄 boxman.c
字号:
#define _BOXMAN_C_
#pragma NOAREGS
#include "general.h"
#include "osdshow.h"
#ifdef OSD_GAME_SOKOBAN
///////////////////////////////////////////////////////////////////////////////
// #define _BOX_DEBUG_
// #define _BOX_ASSERT_
extern void DRS232LogS(char *pcStr);
extern void DRS232LogB(BYTE bV1, BYTE bV2, BYTE bV3, BYTE bV4);
#ifdef _BOX_DEBUG_
#define BOX_DBGLogB(b1, b2, b3, b4) DRS232LogB(b1, b2, b3, b4)
#define BOX_DBGLogW(wTemp) DRS232LogB(0, 0, bHiByte(wTemp), bLoByte(wTemp))
#define BOX_DBGLogDW(dwTemp) DRS232LogB(bHiByte(wHiWord(dwTemp)), bLoByte(wHiWord(dwTemp)), bHiByte(wLoWord(dwTemp)), bLoByte(wLoWord(dwTemp)))
#define BOX_DBGLogS(s) DRS232LogS(s)
#else
#define BOX_DBGLogB(b1, b2, b3, b4)
#define BOX_DBGLogW(wTemp)
#define BOX_DBGLogDW(dwTemp)
#define BOX_DBGLogS(s)
#endif
#ifdef _BOX_ASSERT_
#define BOX_ASSERT(fgAssert) \
do \
{ \
if(!(fgAssert)) \
{ \
DRS232LogS("\nAssert Error!"); \
DRS232LogS(_FILE_); \
DRS232LogB((BYTE)(_LINE_ >> 24), (BYTE)(_LINE_ >> 16), (BYTE)(_LINE_ >> 8), (BYTE)(_LINE_ >> 0)); \
} \
}while(0)
#else
#define BOX_ASSERT(fgAssert)
#endif
///////////////////////////////////////////////////////////////////////////////
static void vBoxManVarInit(void) large
{
_bGameState = 0;
_bGameSubState = 0;
_bGameItem = 0;
_bGameGrade = 0;
#ifdef OSD_GAME_SOUND
_bGameSndTimer = 0;
_bGameSndId = 0;
#endif
}
static void vBoxManNewTurnInit(void) large
{
BYTE i;
vSetSharedInfo(SI_MAN_X, pMap[_bGameGrade]->rManPos.x);
vSetSharedInfo(SI_MAN_Y, pMap[_bGameGrade]->rManPos.y);
for (i = 0; i < pMap[_bGameGrade]->bBoxNo; i++)
{
vSetSharedInfo(SI_BOX_X(i), pMap[_bGameGrade]->rBoxPos[i].x);
vSetSharedInfo(SI_BOX_Y(i), pMap[_bGameGrade]->rBoxPos[i].y);
}
//clear all flag of box
_bfgApBox = 0x00;
_bNowRebackNo = 0x00;
_bNowRebackedNo = REBACK_NS;
_bPushBoxNo = 0x00;
_bOren = THINK;
_fgCanShift = FALSE;
_fgGameOver = FALSE;
_fgManPushBox = FALSE; // user has push the box initial at map change
_fgLastStep = FALSE;
_fgManNextBox = FALSE; // set or not when judge at next to box
_fgBadPosiWarn = FALSE;
_fgAnswer = FALSE;
_bLastStepStack = 0;
_bNowNextBoxId = 0;
_bBMShowTimer = 0;
_wAswStep = 0;
}
static void vBoxManOsdInit(void) large
{
vOsdSetSt(OSD_ST_BURST);
vCreateWB(WB_OSD_GAME, TRUE);
vSetWBTcColor(WB_OSD_GAME);
vSetTransEn(WB_OSD_GAME, 0);
vBoxManShowMap();
vBoxManShowInfo(BM_INFO_ALL1);
vHiliBoxManMenuItem(_bGameItem, ITEM_HILI);
vEnableWB(WB_OSD_GAME);
}
static void vGameBoxManOsdRecover(void) large
{
vBoxManNewTurnInit();
vBoxManShowMap();
vBoxManShowInfo(BM_INFO_ALL2);
}
static void vChangDisplay(void) large
{
BYTE i;
if (_fgCanShift || _fgLastStep)
{
if (_fgCanShift && _fgManNextBox)
{
_bPushBoxNo++;
vBoxManShowInfo(BM_INFO_PUSH_STEP);
//show the push box step
}
vDrawMap(_bStartPosBmpId, bSharedInfo(SI_SHIFT_SR_X), bSharedInfo(SI_SHIFT_SR_Y));
vDrawBox(_bNowNextBoxId);
if (_fgLastStep)
{
vDrawMap(_bEndPosBmpId, bSharedInfo(SI_SHIFT_DS_X), bSharedInfo(SI_SHIFT_DS_Y));
_bPushBoxNo-- ;
if (_bPushBoxNo == 0)
{
_fgManPushBox = FALSE;
}
//show the push box step
vBoxManShowInfo(BM_INFO_PUSH_STEP);
// _bNowNextBoxId = bSharedInfo(SI_MEM_BOXID((_bLastStepStack - 1)));
}
vDrawMan(bSharedInfo(SI_MAN_X), bSharedInfo(SI_MAN_Y));
_fgLastStep = FALSE;
_fgCanShift = FALSE;
_fgManNextBox = FALSE;
}
if (!_fgGameOver)
{
// judge the flag
for ( i = 0; i < pMap[_bGameGrade]->bBoxNo; i++)
{
if (!fgBox(i))
{
break;
}
}
if (i < pMap[_bGameGrade]->bBoxNo)
{
_fgGameOver = FALSE;
}
else
{
_fgGameOver = TRUE;
}
if (_fgGameOver)
{
#ifdef OSD_GAME_SOUND
vGameDelayMs(10);
vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, CLIP_WIN, 0);
_bGameSndId = 0xFF;
_bGameSndTimer = 75;
#endif
if (_fgAnswer)
{
vChgGameState(BM_DIALOG_STATE);
vChgGameSubState(BM_DIALOG_TRY_STATE);
vBoxManShowDialog();
}
else
{
vChgGameState(BM_DIALOG_STATE);
vChgGameSubState(BM_DIALOG_NEXT_STATE);
vBoxManShowDialog();
}
}
}
#ifdef OSD_GAME_SOUND
// Pupop & Walk
if (_bGameSndId < CLIP_NS)
{
vGameDelayMs(10);
vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, _bGameSndId, 0);
_bGameSndId = 0xFF;
_bGameSndTimer = 15;
}
#endif
}
//find the index of the box from map
static BOOL fgJudgeNextBox(BYTE x, BYTE y, BOOL fgManJudgeNextBox) large
{
BOOL fgNextBox;
BYTE i;
i = 0;
fgNextBox = FALSE;
while((!fgNextBox) && (i < pMap[_bGameGrade]->bBoxNo))
{
// if ((x == rNowBoxPos[i].x) && (y == rNowBoxPos[i].y))
if ((x == bSharedInfo(SI_BOX_X(i))) && (y == bSharedInfo(SI_BOX_Y(i))))
{
if (fgManJudgeNextBox)
{
//when the man is next to the box then get now push box id
_bNowNextBoxId = i;
}
fgNextBox = TRUE;
}
i++;
}
return fgNextBox;
}
static code char cStepx[] = {0, 1, 0, -1, 0, 0};
static code char cStepy[] = {0, 0, -1, 0, 1, 0};
static void vJudgeCanShift(BYTE bOren) large
{
sBMANPos rJudgePos;
BOOL fgManJudgeNextBox;
BYTE i;
fgManJudgeNextBox = TRUE;
_fgManNextBox = FALSE;
_fgCanShift = FALSE;
rJudgePos.x = bSharedInfo(SI_MAN_X) + cStepx[bOren];
rJudgePos.y = bSharedInfo(SI_MAN_Y) + cStepy[bOren];
if (fgJudgeNextBox(rJudgePos.x, rJudgePos.y, fgManJudgeNextBox)) // the next is box
{
fgManJudgeNextBox = FALSE;
_fgManNextBox = TRUE;
if ( fgJudgeNextBox(rJudgePos.x + cStepx[bOren], // the next to next is box
rJudgePos.y + cStepy[bOren],
fgManJudgeNextBox)
|| (pMap[_bGameGrade]->bMapData[rJudgePos.y + cStepy[bOren]][rJudgePos.x + cStepx[bOren]] == WALL))
{
_fgCanShift = FALSE;
}
else if (pMap[_bGameGrade]->bMapData[rJudgePos.y + cStepy[bOren]][rJudgePos.x + cStepx[bOren]] == BADPOS)
{
// here add the conditon judge is bad positon or not;
_fgCanShift = FALSE;
// show the warning osd
// ShowMessage("the positon is bad positon, please think another way");
vShowBmBadPosiWarn();
_bBMShowTimer = BAD_POSI_INT;
_fgBadPosiWarn = TRUE;
#ifdef OSD_GAME_SOUND
vGameDelayMs(10);
vSendUopCmd(UOP_AUDIO_CLIP, SV_ACLIP_FLASH, CLIP_WARNING, 0);
_bGameSndId = 0xFF;
_bGameSndTimer = 15;
#endif
}
else
{
_fgCanShift = TRUE;
}
}
else if (pMap[_bGameGrade]->bMapData[rJudgePos.y][rJudgePos.x] == WALL) //it is wall
{
_fgCanShift = FALSE;
}
else
{
_fgCanShift = TRUE;
}
if (_fgCanShift)
{
// draw start and dram man
_bStartPosBmpId = pMap[_bGameGrade]->bMapData[bSharedInfo(SI_MAN_Y)][bSharedInfo(SI_MAN_X)];
vSetSharedInfo(SI_SHIFT_SR_X, bSharedInfo(SI_MAN_X));
vSetSharedInfo(SI_SHIFT_SR_Y, bSharedInfo(SI_MAN_Y));
vSetSharedInfo(SI_MAN_X, rJudgePos.x);
vSetSharedInfo(SI_MAN_Y, rJudgePos.y);
if (_fgManNextBox) // draw box
{
vSetSharedInfo(SI_BOX_Y(_bNowNextBoxId), rJudgePos.y + cStepy[bOren]);
vSetSharedInfo(SI_BOX_X(_bNowNextBoxId), rJudgePos.x + cStepx[bOren]);
_fgManPushBox = TRUE;
//when the remember stack is full then push the stack
if ((_bLastStepStack) == MAX_REBACK_STEP)
{
for ( i = 0; i < MAX_REBACK_STEP - 1; i++)
{
vSetSharedInfo(SI_MEM_BOXID(i), bSharedInfo(SI_MEM_BOXID((i + 1))));
vSetSharedInfo(SI_MEM_OREN(i), bSharedInfo(SI_MEM_OREN((i + 1))));
}
_bLastStepStack = MAX_REBACK_STEP - 1;
}
//remember the box id of last step
vSetSharedInfo(SI_MEM_BOXID(_bLastStepStack), _bNowNextBoxId);
//remember the orientation of last step
vSetSharedInfo(SI_MEM_OREN(_bLastStepStack), (bOren + 1) % 4 + 1);
//remember stack pointer add
_bLastStepStack++;
BOX_DBGLogB(0, 0, 0, _bLastStepStack);
//show the number step to reback
}
#ifdef OSD_GAME_SOUND
_bGameSndId = CLIP_POPUP;
_bGameSndTimer = 15;
#endif
}
}
static void vLeftClick(void) large
{
_bOren = LEFT;
_bBMShowTimer = MAN_SHOW_INT;
vJudgeCanShift(_bOren);
vChangDisplay();
}
static void vUpClick(void) large
{
_bOren = UP;
_bBMShowTimer = MAN_SHOW_INT;
vJudgeCanShift( _bOren);
vChangDisplay();
}
static void vDownClick(void) large
{
_bOren = DOWN;
_bBMShowTimer = MAN_SHOW_INT;
vJudgeCanShift(_bOren);
vChangDisplay();
}
static void vRightClick(void) large
{
_bOren = RIGHT;
_bBMShowTimer = MAN_SHOW_INT;
vJudgeCanShift(_bOren);
vChangDisplay();
}
static void vReback(void) large
{
if (_bLastStepStack == 0)
{
// ShowMessage("have return the end");
return;
}
if (_fgManPushBox && _bNowRebackedNo)
{
char x;
char y;
//get the reverse of last push orientation
x = cStepx[bSharedInfo(SI_MEM_OREN(_bLastStepStack - 1))];
y = cStepy[bSharedInfo(SI_MEM_OREN(_bLastStepStack - 1))];
if (_bLastStepStack > 0)
{
_bNowNextBoxId = bSharedInfo(SI_MEM_BOXID(_bLastStepStack - 1));
}
// the space man stand in
_bStartPosBmpId = pMap[_bGameGrade]->bMapData[ bSharedInfo(SI_MAN_Y)][ bSharedInfo(SI_MAN_X)];
vSetSharedInfo(SI_SHIFT_SR_X, bSharedInfo(SI_MAN_X));
vSetSharedInfo(SI_SHIFT_SR_Y, bSharedInfo(SI_MAN_Y));
// the space box stand in
_bEndPosBmpId = pMap[_bGameGrade]->bMapData[bSharedInfo(SI_BOX_Y(_bNowNextBoxId))][bSharedInfo(SI_BOX_X(_bNowNextBoxId))];
vSetSharedInfo(SI_SHIFT_DS_X, bSharedInfo(SI_BOX_X(_bNowNextBoxId)));
vSetSharedInfo(SI_SHIFT_DS_Y, bSharedInfo(SI_BOX_Y(_bNowNextBoxId)));
// the box position back for one step
vSetSharedInfo(SI_BOX_Y(_bNowNextBoxId), bSharedInfo(SI_SHIFT_DS_Y) + y);
vSetSharedInfo(SI_BOX_X(_bNowNextBoxId), bSharedInfo(SI_SHIFT_DS_X) + x);
// the man position back for one step
vSetSharedInfo(SI_MAN_X, bSharedInfo(SI_BOX_X(_bNowNextBoxId)) + x);
vSetSharedInfo(SI_MAN_Y, bSharedInfo(SI_BOX_Y(_bNowNextBoxId)) + y);
BOX_DBGLogB(0, _bNowRebackNo, _bNowRebackedNo, _bLastStepStack);
//if user reback the number add
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -