/** * Menuliskan isi buffer ke filesystem * @param position * @param buffer * @param size * @param offset * @return */ int POI::writeBlock(Block position, const char *buffer, int size, int offset) { /* kalau sudah di END_BLOCK, return */ if (position == END_BLOCK) { return 0; } /* kalau offset >= BLOCK_SIZE */ if (offset >= BLOCK_SIZE) { /* kalau nextBlock tidak ada, alokasikan */ if (nextBlock[position] == END_BLOCK) { setNextBlock(position, allocateBlock()); } return writeBlock(nextBlock[position], buffer, size, offset - BLOCK_SIZE); } file.seekp(BLOCK_SIZE * DATA_POOL_OFFSET + position * BLOCK_SIZE + offset); int size_now = size; if (offset + size_now > BLOCK_SIZE) { size_now = BLOCK_SIZE - offset; } file.write(buffer, size_now); /* kalau size > block size, lanjutkan di nextBlock */ if (offset + size > BLOCK_SIZE) { /* kalau nextBlock tidak ada, alokasikan */ if (nextBlock[position] == END_BLOCK) { setNextBlock(position, allocateBlock()); } return size_now + writeBlock(nextBlock[position], buffer + BLOCK_SIZE, offset + size - BLOCK_SIZE); } return size_now; }
/** * Membebaskan blok * @param position pointer yang dibebaskan */ void POI::freeBlock(Block position) { if (position == EMPTY_BLOCK) { return; } while (position != END_BLOCK) { Block temp = nextBlock[position]; setNextBlock(position, EMPTY_BLOCK); position = temp; available--; } writeVolumeInformation(); }
/** mendapatkan first Empty yang berikutnya */ ptr_block CCFS::allocateBlock() { ptr_block result = firstEmpty; setNextBlock(result, END_BLOCK); while (nextBlock[firstEmpty] != 0x0000) { firstEmpty++; } available--; writeVolumeInformation(); return result; }
void CPlayer::networkProcess(double nowTime) { bool value; int i,j,temp; bool isDropped=false; int deletedLine; //EnterCriticalSection(&criticalSection); //블록을 움직여야 하고 특정 시간이 지난 경우(너무 빨리 놓는 일 없게) if(isAutoMoving) { int xx=3; int tt=0; if(nowTime-messageSendedTime>CState_CustomSetting::GetLimitRespondTime()) { // MYTRACE("[%d]AUTUMOVE:%d %f %f",playerNum,isAutoMoving?1:0,nowTime-messageSendedTime,CState_CustomSetting::GetLimitRespondTime()); double remainedProcessTime=nowTime-messageSendedTime-CState_CustomSetting::GetLimitRespondTime(); int iteration=remainedProcessTime/CState_CustomSetting::GetAutoMoveDelay(); if(!decisionInfo.useHold) //홀드 사용안하는 경우 { //벽에 부딪힌다거나 놓을 수 없는경우 if(board.chkBlock(decisionInfo.posX,0,CBlockMgr::getBlock(playerNum,playInfo.turnNum),decisionInfo.turn)!=CBoard::ONNOTHING) { MYTRACE("[%d]### Death by collision (posX=%d turn=%d turnNum=%d blockNum=%d)",playerNum,decisionInfo.posX,decisionInfo.turn,playInfo.turnNum, CBlockMgr::getBlock(playerNum,playInfo.turnNum)); setDead(); //죽는다. return; } } for(i=0;i<iteration;i++) { if(decisionInfo.useHold)//홀드 사용한 경우 { if(playInfo.isOnHold) //사용할수 없는데 사용한 경우 { game.ogg.Play(OGG_HOLDFAIL); setDead(); //죽는다. MessageBox(NULL,L"Invalid use of 'Hold'",L"Rule violation",MB_OK); MYTRACE("[%d]### Death by invalid use of 'Hold'(Rule violation)(blockNum=%d)",playerNum, CBlockMgr::getBlock(playerNum,playInfo.turnNum)); return; } else { playInfo.holdCount++; playInfo.isOnHold=TRUE; game.ogg.Play(OGG_HOLD); if(playInfo.holdNum==0) { playInfo.holdNum=CBlockMgr::getBlock(playerNum,playInfo.turnNum); setNextBlock(nowTime); } else { int holdBlock=CBlockMgr::getBlock(playerNum,playInfo.turnNum); CBlockMgr::setBlock(playerNum,playInfo.turnNum,playInfo.holdNum); playInfo.holdNum=holdBlock; playInfo.turnNum--; setNextBlock(nowTime); //다음 메시지를 받도록 한다. } } isAutoMoving=false; isMessageWait=false; isMessageReceived=false; break; } else //홀드 사용이 아닌 경우 { if(decisionInfo.posX-xx<0) xx--; else if(decisionInfo.posX-xx>0) xx++; else if(decisionInfo.turn-tt<0) tt--; else if(decisionInfo.turn-tt>0) tt++; else { //원하는 위치로 되었으면 isDropped=true; isAutoMoving=false; isMessageWait=false; isMessageReceived=false; break; } } } } //현재의 블록 움직임 설정 playInfo.nowXPos=xx; playInfo.nowYPos=0; playInfo.nowTurn=tt; } else { if(isMessageWait) //응답을 기다리는 중이라면 { if(isMessageReceived) //응답을 받았다면 { //줄 높이기 이벤트를 처리한다. eventProcess(nowTime); isMessageWait=false; isAutoMoving=true; isMessageReceived=false; MYTRACE("[%d]RECEIVED(useHold:%d posX:%d turn:%d)",playerNum,decisionInfo.useHold,decisionInfo.posX,decisionInfo.turn); //메시지를 설정한다 if(((WCHAR*)decisionInfo.message)[0]!=NULL) //null이 아니면(바꿔야 하는 상황이면) { memcpy(message,(char*)decisionInfo.message,sizeof(message)); } } } else //요청을 해야할 때라면 { MYTRACE("[%d]REQUEST:start",playerNum); sendRequestMessage(); isMessageWait=true; MYTRACE("[%d]REQUEST:end",playerNum); messageSendedTime=nowTime; } } if(isDropped) { playInfo.isOnHold=FALSE; game.ogg.Stop(OGG_HARDDROP);game.ogg.Play(OGG_HARDDROP); //블럭을 놓는다. board.putBlock(playInfo.nowXPos,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn); //꽉찬 줄을 지운다. if((deletedLine=board.deleteFilledLine())>0) { playInfo.lineDeletionCount+=deletedLine; switch(deletedLine) { case 1: game.ogg.Stop(OGG_SINGLE);game.ogg.Play(OGG_SINGLE,false); playInfo.isBackToBack=FALSE; break; case 2: game.ogg.Stop(OGG_DOUBLE);game.ogg.Play(OGG_DOUBLE,false); playInfo.isBackToBack=FALSE; if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(1,false));//old 0 break; case 3: game.ogg.Stop(OGG_TRIPLE);game.ogg.Play(OGG_TRIPLE,false); playInfo.isBackToBack=FALSE; if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(2,false));//old 1 break; case 4: if(playInfo.isBackToBack) { game.ogg.Stop(OGG_BACKTOBACK_TETRIS);game.ogg.Play(OGG_BACKTOBACK_TETRIS); if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(5,false));//old 4 } else { game.ogg.Stop(OGG_TETRIS);game.ogg.Play(OGG_TETRIS); if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(4,false));//old 3 } playInfo.isBackToBack=TRUE; break; } //콤보 수 증가. playInfo.nowCombo++; //콤보에 따른 라인 추가 if(playInfo.nowCombo>=3 && playInfo.nowCombo<=4) { if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(1,false)); }else if(playInfo.nowCombo>=5 && playInfo.nowCombo<=6){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(2,false)); }else if(playInfo.nowCombo>=7 && playInfo.nowCombo<=8){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(3,false)); }else if(playInfo.nowCombo>=9){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(4,false)); } //콤보 음성효과 switch(playInfo.nowCombo) { case 0: case 1:break; case 2:game.ogg.Stop(OGG_COMBO1);game.ogg.Play(OGG_COMBO1);break; case 3:game.ogg.Stop(OGG_COMBO2);game.ogg.Play(OGG_COMBO2);break; case 4:game.ogg.Stop(OGG_COMBO3);game.ogg.Play(OGG_COMBO3);break; case 5:game.ogg.Stop(OGG_COMBO4);game.ogg.Play(OGG_COMBO4);break; case 6:game.ogg.Stop(OGG_COMBO5);game.ogg.Play(OGG_COMBO5);break; case 7:game.ogg.Stop(OGG_COMBO6);game.ogg.Play(OGG_COMBO6);break; case 8:game.ogg.Stop(OGG_COMBO7);game.ogg.Play(OGG_COMBO7);break; default:game.ogg.Stop(OGG_COMBO8);game.ogg.Play(OGG_COMBO8);break; } //콤보 애니메이션 if(playInfo.nowCombo>1) { if(playInfo.nowCombo<18) game.effectCollection.insertEffect(ANI_COMBO2+playInfo.nowCombo-2,CBoard::boardPosition[playerNum].x+30,270,nowTime); else game.effectCollection.insertEffect(ANI_COMBOWOW,CBoard::boardPosition[playerNum].x+30,270,nowTime); } //터진 것에 대한 effect를 준다 for(i=0;i<21;i++) { if(board.deletedLine[i]) //지워진 라인에 대해서 effect를 준다. { game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x,CBoard::boardPosition[playerNum].y+i*22,nowTime); game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x+64,CBoard::boardPosition[playerNum].y+i*22,nowTime); game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x+128,CBoard::boardPosition[playerNum].y+i*22,nowTime); } } } else //라인이 지워지지 않았다면 { playInfo.nowCombo=0; //콤보 초기화. if(CBlockMgr::getBlock(playerNum,playInfo.turnNum)==5) playInfo.isBackToBack=FALSE; } setNextBlock(nowTime); playInfo.nowXPos=3; playInfo.nowYPos=0; playInfo.nowTurn=0; } //LeaveCriticalSection(&criticalSection); }
void CPlayer::keyboardProcess(double nowTime) { bool value; int i,j,temp; bool isDropped; int deletedLine; temp=board.chkBlock(playInfo.nowXPos,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn); if(temp==CBoard::ONCOLLISION) //보드가 꽉차서 죽는경우., { MYTRACE("[%d]### Death by collision (posX=%d turn=%d turnNum=%d blockNum=%d)",playerNum,decisionInfo.posX,decisionInfo.turn,playInfo.turnNum, CBlockMgr::getBlock(playerNum,playInfo.turnNum)); setDead(); return; } isDropped=false; for(i=0;i<6;i++) { value=DXUTIsKeyDown(keyPad[kbdType][playerNum][i]); if(value==false) isRepeated[i]=false; //일정 시간이 지나지 않았다면 입력받지 않는다. if(isRepeated[i]==true && nowTime-lastKeyboardTime[i]<=keyboardInputLimitTime[i]) { continue; } else { isKeyDown[i]=isKeyDown[i] | value; } if(!isKeyDown[i]) continue; //첫입력은 약간의 딜레이를 준다. if(isRepeated[i]==false) { isRepeated[i]=true; if(i==0 || i==4) //UP키나 스페이스 키라면 딜레이를 많이 준다. keyboardInputLimitTime[i]=100; else keyboardInputLimitTime[i]=keyBoardInterval; //약간의 딜레이 } else { if(i==3)//Down이라면 keyboardInputLimitTime[i]=keyBoardRepeatInterval*1.2; //조금 더 늦게 반응 else keyboardInputLimitTime[i]=keyBoardRepeatInterval; //적은 딜레이 } lastKeyboardTime[i]=nowTime; isKeyDown[i]=false; //키보드 처리 switch(i) { case 0:/*UP*/ temp=(playInfo.nowTurn+1)%4; //왼쪽이나 오른쪽으로 이동해서 돌릴 수 있다면 그렇게 한다. for(j=0;j<4;j++) { if(board.chkBlock(playInfo.nowXPos+j,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),temp)==CBoard::ONNOTHING) { playInfo.nowTurn=temp; playInfo.nowXPos+=j; game.ogg.Play(OGG_MOVE); break; } if(board.chkBlock(playInfo.nowXPos-j,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),temp)==CBoard::ONNOTHING) { playInfo.nowTurn=temp; playInfo.nowXPos-=j; game.ogg.Play(OGG_MOVE); break; } } break; case 1:/*LEFT*/ if(board.chkBlock(playInfo.nowXPos-1,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn)==CBoard::ONNOTHING) { playInfo.nowXPos--; game.ogg.Play(OGG_MOVE); } break; case 2:/*RIGHT*/ if(board.chkBlock(playInfo.nowXPos+1,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn)==CBoard::ONNOTHING) { playInfo.nowXPos++; game.ogg.Play(OGG_MOVE); } break; case 3:/*DOWN*/ playInfo.nowYPos++; lastDownTime=nowTime; game.ogg.Play(OGG_SOFTDROP); break; case 4:/*DROP*/ isDropped=true; keyboardInputLimitTime[i]=dropInterval; playInfo.isOnHold=FALSE; break; case 5:/*HOLD*/ if(playInfo.isOnHold) { game.ogg.Play(OGG_HOLDFAIL); } else { playInfo.holdCount++; playInfo.isOnHold=TRUE; game.ogg.Play(OGG_HOLD); keyboardInputLimitTime[i]=holdInterval; if(playInfo.holdNum==0) { playInfo.holdNum=CBlockMgr::getBlock(playerNum,playInfo.turnNum); setNextBlock(nowTime); } else { int holdBlock=CBlockMgr::getBlock(playerNum,playInfo.turnNum); CBlockMgr::setBlock(playerNum,playInfo.turnNum,playInfo.holdNum); playInfo.holdNum=holdBlock; playInfo.turnNum--; setNextBlock(nowTime); return; } } break; } } //일정시간이 지났다면 떨어짐. if(nowTime-lastDownTime>1.0) // 1.0을 시간이 지남에 따라서 줄어들게 만들어야 함 { lastDownTime=nowTime; playInfo.nowYPos++; } //충돌하였다면. temp=board.chkBlock(playInfo.nowXPos,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn); if(isDropped || temp==CBoard::ONCOLLISION) { game.ogg.Stop(OGG_HARDDROP);game.ogg.Play(OGG_HARDDROP); //블럭을 놓는다. board.putBlock(playInfo.nowXPos,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn); //꽉찬 줄을 지운다. if((deletedLine=board.deleteFilledLine())>0) { playInfo.lineDeletionCount+=deletedLine; switch(deletedLine) { case 1: game.ogg.Stop(OGG_SINGLE);game.ogg.Play(OGG_SINGLE,false); playInfo.isBackToBack=FALSE; break; case 2: game.ogg.Stop(OGG_DOUBLE);game.ogg.Play(OGG_DOUBLE,false); playInfo.isBackToBack=FALSE; if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(1,false));//old 0 break; case 3: game.ogg.Stop(OGG_TRIPLE);game.ogg.Play(OGG_TRIPLE,false); playInfo.isBackToBack=FALSE; if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(2,false)); //old 1 break; case 4: if(playInfo.isBackToBack) { game.ogg.Stop(OGG_BACKTOBACK_TETRIS);game.ogg.Play(OGG_BACKTOBACK_TETRIS); if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(5,false));//old 4 } else { game.ogg.Stop(OGG_TETRIS);game.ogg.Play(OGG_TETRIS); if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(4,false));//old 3 } playInfo.isBackToBack=TRUE; break; } //콤보 수 증가. playInfo.nowCombo++; //콤보에 따른 라인 추가 if(playInfo.nowCombo>=3 && playInfo.nowCombo<=4) { if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(1,false)); }else if(playInfo.nowCombo>=5 && playInfo.nowCombo<=6){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(2,false)); }else if(playInfo.nowCombo>=7 && playInfo.nowCombo<=8){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(3,false)); }else if(playInfo.nowCombo>=9){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(4,false)); } /* old if(playInfo.nowCombo>=3 && playInfo.nowCombo<=7) { if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(1)); }else if(playInfo.nowCombo>=8 && playInfo.nowCombo<=13){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(2)); }else if(playInfo.nowCombo>=14){ if(targetPlayer!=NULL) targetPlayer->getEventQueue()->push_back(makePushEvent(3)); } */ //콤보 음성효과 switch(playInfo.nowCombo) { case 0: case 1:break; case 2:game.ogg.Stop(OGG_COMBO1);game.ogg.Play(OGG_COMBO1);break; case 3:game.ogg.Stop(OGG_COMBO2);game.ogg.Play(OGG_COMBO2);break; case 4:game.ogg.Stop(OGG_COMBO3);game.ogg.Play(OGG_COMBO3);break; case 5:game.ogg.Stop(OGG_COMBO4);game.ogg.Play(OGG_COMBO4);break; case 6:game.ogg.Stop(OGG_COMBO5);game.ogg.Play(OGG_COMBO5);break; case 7:game.ogg.Stop(OGG_COMBO6);game.ogg.Play(OGG_COMBO6);break; case 8:game.ogg.Stop(OGG_COMBO7);game.ogg.Play(OGG_COMBO7);break; default:game.ogg.Stop(OGG_COMBO8);game.ogg.Play(OGG_COMBO8);break; } //콤보 애니메이션 if(playInfo.nowCombo>1) { if(playInfo.nowCombo<18) game.effectCollection.insertEffect(ANI_COMBO2+playInfo.nowCombo-2,CBoard::boardPosition[playerNum].x+30,270,nowTime); else game.effectCollection.insertEffect(ANI_COMBOWOW,CBoard::boardPosition[playerNum].x+30,270,nowTime); } //터진 것에 대한 effect를 준다 for(i=0;i<21;i++) { if(board.deletedLine[i]) //지워진 라인에 대해서 effect를 준다. { game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x,CBoard::boardPosition[playerNum].y+i*22,nowTime); game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x+64,CBoard::boardPosition[playerNum].y+i*22,nowTime); game.effectCollection.insertEffect(ANI_BOMB,CBoard::boardPosition[playerNum].x+128,CBoard::boardPosition[playerNum].y+i*22,nowTime); } } } else //라인이 지워지지 않았다면 { playInfo.nowCombo=0; //콤보 초기화. if(CBlockMgr::getBlock(playerNum,playInfo.turnNum)==5) playInfo.isBackToBack=FALSE; } setNextBlock(nowTime); } }
void CPlayer::eventProcess(double nowTime) { int i,j,k; stEvent event; std::list<stEvent>::iterator iter; if(eventQueue.empty()) return; for(iter=eventQueue.begin();iter!=eventQueue.end();) { bool erased=false; event=(stEvent)(*iter); switch(playMode) { case PERSON: case NETWORK: switch(event.eventName) { case PUSHLINE: //라인수 늘리기 //음성효과 game.ogg.Stop(OGG_LINE_ATTACKED); game.ogg.Play(OGG_LINE_ATTACKED); //넘치는거 체크 제외 /* for(j=0;j<event.numOfLines;j++) { for(k=0;k<12;k++) { if(board.board[j][k]>0) { if(j-event.numOfLines<0) //넘쳤다면 { setDead(); //죽었다. } k=12;j=(int)event.numOfLines;//루프를 빠져나간다. break; } } } */ board.pushLine(event.numOfLines,event.posX); //만약 블록 추가로 인해서 현재 떨어지는 블록과 겹치게 된다면 현재 블록을 생략하고 다음블록으로이동. if(board.chkBlock(playInfo.nowXPos,playInfo.nowYPos,CBlockMgr::getBlock(playerNum,playInfo.turnNum),playInfo.nowTurn)==CBoard::ONCOLLISION) { setNextBlock(nowTime); } //큐에서 지운다. eventQueue.erase(iter++); erased=true; break; } break; /*case NETWORK: // //상대방에게 이벤트 전송 break;*/ } if(!erased) ++iter; //만약 네트워크 모드라면 한번에 한번 공격에 대한 것만 올라감. if(playMode==NETWORK) break; } }