@@ -377,7 +377,6 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
377377 // hidden -> appearing -> visible
378378 // Successful pick up
379379 // claimed -> (granted) -> owned
380- // TODO: Denied pick up
381380 // Hyper bomber death sequence:
382381 // owned -> released (with coords, unk1=1) -> (lost) -> appearing -> visible
383382 for (unsigned i = 0 ; i < powerUps.size (); i++)
@@ -431,8 +430,10 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
431430 releaseBombSlot (pup.slot , i);
432431 }
433432 else if (pup.state != PowerUp::Owned) {
434- WARN_LOG (game, " PowerUp transitioning from owned to %x? slot %d" ,
433+ DEBUG_LOG (game, " PowerUp transitioning from owned to %x? slot %d" ,
435434 pup.state , pup.slot );
435+ // end of game?
436+ powerUps[i] = pup;
436437 }
437438 }
438439 break ;
@@ -480,10 +481,8 @@ void BMRoom::savePowerUps(Player *player, const uint8_t *data)
480481 break ;
481482
482483 default :
483- if (powerUps[i].param == 0 )
484+ if (powerUps[i].param == 0 || pup. slot == powerUps[i]. slot )
484485 powerUps[i] = pup;
485- else
486- WARN_LOG (game, " PowerUp current state not handled: %x -> %x" , curState, pup.state );
487486 break ;
488487 }
489488 }
@@ -718,13 +717,13 @@ void BMRoom::releaseBombSlot(int slot, int powerUpIdx)
718717
719718bool BMRoom::checkEndOfGame (Player *player, uint8_t command, uint8_t mark)
720719{
721- if (mark == 0 )
722- return false ;
723720 State& playerState = states[getPlayerIndex (player)];
724721 if (playerState.status != State::InGame)
725722 return false ;
726- DEBUG_LOG (game, " [%s] Game end" , player->getName ().c_str ());
727- playerState.endOfGameMask |= 1 << (command - 1 );
723+ if (mark != 0 )
724+ playerState.endOfGameMask |= 1 << (command - 1 );
725+ if (playerState.endOfGameMask == 7 )
726+ DEBUG_LOG (game, " [%s] Game end" , player->getName ().c_str ());
728727 return playerState.endOfGameMask == 7 ;
729728}
730729
@@ -737,9 +736,27 @@ void BMRoom::sendEndOfGame(Player *player, Packet& reply, Packet& relay)
737736 return ;
738737 state.status = State::GameEnding;
739738 inGame = false ;
740- for (unsigned i = 0 ; i < players.size (); i++)
741- if (states[i].endOfGameMask != 7 )
739+ if (rules[0 ] == 0 )
740+ {
741+ // survival mode: wait until all players have agreed on the end of game
742+ for (unsigned i = 0 ; i < players.size (); i++)
743+ if (states[i].endOfGameMask != 7 )
744+ return ;
745+ }
746+ else
747+ {
748+ // hyper bomber mode: one player is enough
749+ bool allPlayersDone = true ;
750+ for (unsigned i = 0 ; i < players.size (); i++)
751+ {
752+ if (states[i].endOfGameMask != 7 ) {
753+ states[i].endOfGameMask = 7 ;
754+ allPlayersDone = false ;
755+ }
756+ }
757+ if (!allPlayersDone)
742758 return ;
759+ }
743760 if (!reply.empty ()) {
744761 player->send (reply);
745762 reply.reset ();
@@ -1174,10 +1191,20 @@ bool Map::append(const uint8_t *data, unsigned size)
11741191 if (this ->data .size () < blockCount * sizeof (Block))
11751192 return false ;
11761193
1177- this ->data .reserve (blockCount);
1194+ blocks.clear ();
1195+ blocks.reserve (blockCount);
11781196 for (unsigned i = 0 ; i < blockCount; i++)
11791197 blocks.emplace_back (&this ->data [i * sizeof (Block)]);
11801198
1199+ for (unsigned i = 0 ; i < blockCount; i++)
1200+ {
1201+ if (blocks[i].type != Wall && blocks[i].type != Brick
1202+ && blocks[i].type != PowerUp && blocks[i].type != Gate
1203+ && blocks[i].type != TargetPanel)
1204+ WARN_LOG (Game::Bomberman, " Unknown map block type %d at index %d pos %d,%d" ,
1205+ blocks[i].type , i, blocks[i].col , blocks[i].row );
1206+ }
1207+
11811208 return true ;
11821209}
11831210
@@ -1187,6 +1214,26 @@ std::array<uint8_t, 16> Map::getBrickMap() const
11871214 for (const Block& block : blocks)
11881215 if (block.type == Brick)
11891216 map[block.order / 8 ] |= 1 << (block.order % 8 );
1217+ bool ones = true ;
1218+ for (uint8_t v : map)
1219+ if (v == 0 ) {
1220+ ones = false ;
1221+ }
1222+ else
1223+ {
1224+ if (!ones) {
1225+ WARN_LOG (Game::Bomberman, " Brick map has holes" );
1226+ break ;
1227+ }
1228+ if (v != 0xff )
1229+ {
1230+ if (((v + 1 ) & v) != 0 ) {
1231+ WARN_LOG (Game::Bomberman, " Brick map ones don't end properly: %02x" , v);
1232+ break ;
1233+ }
1234+ ones = false ;
1235+ }
1236+ }
11901237 return map;
11911238}
11921239
@@ -1196,15 +1243,23 @@ std::array<PowerUp, 28> Map::getPowerUps() const
11961243 indexes.fill (-1 );
11971244 for (unsigned i = 0 ; i < blocks.size (); i++)
11981245 if (blocks[i].type == PowerUp)
1246+ {
1247+ if (indexes[blocks[i].order ] != -1 )
1248+ WARN_LOG (Game::Bomberman, " PowerUp[%d] already used by block %d" , indexes[blocks[i].order ]);
11991249 indexes[blocks[i].order ] = i;
1250+ }
12001251 std::array<::PowerUp, 28 > pups {};
1252+ unsigned pupMap = 0 ;
12011253 for (unsigned i = 0 ; i < pups.size (); i++)
12021254 if (indexes[i] != -1 )
12031255 {
12041256 const Block& block = blocks[indexes[i]];
12051257 pups[i].pos .x = block.col ;
12061258 pups[i].pos .y = block.row ;
12071259 pups[i].state = PowerUp::Hidden;
1260+ pupMap |= 1 << i;
12081261 }
1262+ if (((pupMap + 1 ) & pupMap) != 0 )
1263+ WARN_LOG (Game::Bomberman, " PowerUp list has holes: %07x" , pupMap);
12091264 return pups;
12101265}
0 commit comments