Example #1
0
int main(int argc, char* argv[])
{
	bool show_console = 0;
	bool done = 0;
	int tickCounter = 0;
	int gServer = 0;
	CSocketServer server;
	CSocketClient client;
	CFont font;

	if(argc != 2)
	{
		printf("usage: mecha server|hostname\n");
		return 1;
	}

	gameInit();

	CLog::Get().Init();

	initEngine();

	font.Load("font_big.png");

	if(strcmp(argv[1], "server") == 0)
	{
		gServer = 1;
	}

	clientInit();

	if(gServer)
	{
		if(!server.Listen(4444))
		{
			CLog::Get().Write(APP_LOG, LOG_ERROR, "Listen failed");
			done = 1;
		}
		if(!client.Connect("localhost", 4444))
		{
			CLog::Get().Write(APP_LOG, LOG_ERROR, "Connection failed");
			done = 1;
		}
	}
	else
	{
		if(!client.Connect(argv[1], 4444))
		{
			CLog::Get().Write(APP_LOG, LOG_ERROR, "Connection failed");
			done = 1;
		}
	}

	while(!done)
	{
		timerUpdate();

		tickCounter += timerGetDiff();

		if(show_console)
		{
			if(inpKeyPressed(GLFW_KEY_PAGEUP)) CConsole::ScrollUp();
			if(inpKeyPressed(GLFW_KEY_PAGEDOWN)) CConsole::ScrollDown();
		}
		if(inpKeyPressed(GLFW_KEY_F1))	show_console = !show_console;
		if(inpKeyPressed(GLFW_KEY_ESC)) break;

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT| GL_STENCIL_BUFFER_BIT);
		glLoadIdentity();

		videoSetPerspective();


		glColor3f(1.0f, 1.0f, 1.0f);

		if(gServer)
			server.Tick();

		client.Tick();

//		if(client.IsConnected())
//			clientTick();

		gfxBlendNormal();

		if(client.IsConnected())
			clientRender(client.GetPreviousSnap(), client.GetCurrentSnap(), client.GetInterpolation());

		gfxSetColor(0.5f, 0.5f, 0.5f, 1.0f);
		videoSetOrtho(800, 600);
		font.Draw(10, 10, "FPS: %f", timerGetFPS());
		font.Draw(10, 25, "Ping: %d", client.m_Ping);
		font.Draw(10, 40, "Snapshot size: %d b", client.GetSnapSize());
		font.Draw(10, 55, "Num objects: %d", client.GetSnapNumObjects());
		videoSetPerspective();

		CConsole::Draw(show_console || !client.IsConnected());

		inpUpdate();

		glfwSwapBuffers();
#ifdef WIN32
		Sleep(1);
#else
		sched_yield();
#endif
	}

	client.Disconnect();
	server.Disconnect();

	closeEngine();

	return true;
}
Example #2
0
void CAiArena::Update (float DeltaTime)
{
    // Block coordinates used in many places
    int BlockX;
    int BlockY;

    // Auxiliary variables for code readability : is there a wall around the current block?
    bool IsWallHere;
    bool IsWallUp;
    bool IsWallDown;
    bool IsWallLeft;
    bool IsWallRight;
    
    // Current dead end number. Incremented each time there is a new dead end.
    int CurrentDeadEnd = 0;

    //*************
    // DEAD END
    //*************

    // Scan each block of the dead end array
    for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
    {
        for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
        {
            // Set undefined dead end (is there one? we don't know yet)
            m_DeadEnd[BlockX][BlockY] = -2;
        }
    }

    // Scan each block of the arena
    for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
    {
        for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
        {
            // If the dead end on this block is currently undefined
            if (m_DeadEnd[BlockX][BlockY] == -2)
            {
                // If the block is on the edges of the arena grid
                if (BlockX == 0 || BlockX == ARENA_WIDTH - 1 ||
                    BlockY == 0 || BlockY == ARENA_HEIGHT - 1)
                {
                    // There is definitely no dead end here
                    m_DeadEnd[BlockX][BlockY] = -1;
                }
                // If the block is not on the edges of the arena grid
                else
                {
                    // Is there a wall on this block?
                    IsWallHere = m_pArena->IsWall (BlockX, BlockY);
                    
                    // If there is no wall on this block
                    if (!IsWallHere)
                    {
                        // Is there a wall around this block?
                        IsWallUp    = m_pArena->IsWall (BlockX, BlockY - 1);
                        IsWallDown  = m_pArena->IsWall (BlockX, BlockY + 1);
                        IsWallLeft  = m_pArena->IsWall (BlockX - 1, BlockY);
                        IsWallRight = m_pArena->IsWall (BlockX + 1, BlockY);

                        // If this block is the back of a dead end ("[")
                        if (IsWallLeft && IsWallUp && IsWallDown)
                        {
                            // Start scanning the dead end on this block
                            int DeadEndBlockX = BlockX;
                            int DeadEndBlockY = BlockY;

                            // While we are still in this dead end and there is no wall blocking the way
                            while (IsWallUp && IsWallDown && !IsWallHere)
                            {
                                // Set the dead end number of the current block : it's the current dead end number
                                m_DeadEnd[DeadEndBlockX][DeadEndBlockY] = CurrentDeadEnd;

                                // Continue scanning (go right)
                                DeadEndBlockX++;

                                // Update the auxiliary variables value.
                                IsWallHere = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY);
                                IsWallUp   = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY - 1);
                                IsWallDown = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY + 1);
                            }

                            // If there is a no wall blocking the way and however the dead end was entirely scanned
                            if (!IsWallHere)
                            {
                                // Then this dead end has an exit. Record the block coordinates of this exit.
                                m_DeadEndExit[CurrentDeadEnd].BlockX = DeadEndBlockX;
                                m_DeadEndExit[CurrentDeadEnd].BlockY = DeadEndBlockY;
                            }

                            // Next dead end number
                            CurrentDeadEnd++;
                        }
                        // If this block is the back of a dead end ("Ú¿")
                        else if (IsWallUp && IsWallLeft && IsWallRight)
                        {
                            // Start scanning the dead end on this block
                            int DeadEndBlockX = BlockX;
                            int DeadEndBlockY = BlockY;

                            // While we are still in this dead end and there is no wall blocking the way
                            while (IsWallLeft && IsWallRight && !IsWallHere)
                            {
                                // Set the dead end number of the current block : it's the current dead end number
                                m_DeadEnd[DeadEndBlockX][DeadEndBlockY] = CurrentDeadEnd;

                                // Continue scanning (go down)
                                DeadEndBlockY++;

                                // Update the auxiliary variables value.
                                IsWallHere  = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY);
                                IsWallLeft  = m_pArena->IsWall (DeadEndBlockX - 1, DeadEndBlockY);
                                IsWallRight = m_pArena->IsWall (DeadEndBlockX + 1, DeadEndBlockY);
                            }

                            // If there is a no wall blocking the way and however the dead end was entirely scanned
                            if (!IsWallHere)
                            {
                                // Then this dead end has an exit. Record the block coordinates of this exit.
                                m_DeadEndExit[CurrentDeadEnd].BlockX = DeadEndBlockX;
                                m_DeadEndExit[CurrentDeadEnd].BlockY = DeadEndBlockY;
                            }

                            // Next dead end number
                            CurrentDeadEnd++;
                        }
                        // If this block is the back of a dead end ("]")
                        else if (IsWallRight && IsWallUp && IsWallDown)
                        {
                            // Start scanning the dead end on this block
                            int DeadEndBlockX = BlockX;
                            int DeadEndBlockY = BlockY;

                            // While we are still in this dead end and there is no wall blocking the way
                            while (IsWallUp && IsWallDown && !IsWallHere)
                            {   
                                // Set the dead end number of the current block : it's the current dead end number
                                m_DeadEnd[DeadEndBlockX][DeadEndBlockY] = CurrentDeadEnd;

                                // Continue scanning (go left)
                                DeadEndBlockX--;

                                // Update the auxiliary variables value.
                                IsWallHere = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY);
                                IsWallUp   = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY - 1);
                                IsWallDown = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY + 1);
                            }

                            // If there is a no wall blocking the way and however the dead end was entirely scanned
                            if (!IsWallHere)
                            {
                                // Then this dead end has an exit. Record the block coordinates of this exit.
                                m_DeadEndExit[CurrentDeadEnd].BlockX = DeadEndBlockX;
                                m_DeadEndExit[CurrentDeadEnd].BlockY = DeadEndBlockY;
                            }

                            // Next dead end number
                            CurrentDeadEnd++;
                        }
                        // If this block is the back of a dead end ("ÀÙ)
                        else if (IsWallDown && IsWallLeft && IsWallRight)
                        {
                            // Start scanning the dead end on this block
                            int DeadEndBlockX = BlockX;
                            int DeadEndBlockY = BlockY;

                            // While we are still in this dead end and there is no wall blocking the way
                            while (IsWallLeft && IsWallRight && !IsWallHere)
                            {
                                // Set the dead end number of the current block : it's the current dead end number
                                m_DeadEnd[DeadEndBlockX][DeadEndBlockY] = CurrentDeadEnd;

                                // Continue scanning (go up)
                                DeadEndBlockY--;

                                // Update the auxiliary variables value.
                                IsWallHere  = m_pArena->IsWall (DeadEndBlockX, DeadEndBlockY);
                                IsWallLeft  = m_pArena->IsWall (DeadEndBlockX - 1, DeadEndBlockY);
                                IsWallRight = m_pArena->IsWall (DeadEndBlockX + 1, DeadEndBlockY);
                            }

                            // If there is a no wall blocking the way and however the dead end was entirely scanned
                            if (!IsWallHere)
                            {
                                // Then this dead end has an exit. Record the block coordinates of this exit.
                                m_DeadEndExit[CurrentDeadEnd].BlockX = DeadEndBlockX;
                                m_DeadEndExit[CurrentDeadEnd].BlockY = DeadEndBlockY;
                            }

                            // Next dead end number
                            CurrentDeadEnd++;
                        }
                        // If this block is the back of NO dead end
                        else
                        {
                            // Set there is no dead end on this block. There may be a dead end
                            // containing this block but we record dead ends by detecting their back.
                            m_DeadEnd[BlockX][BlockY] = -1;
                        }
                    }
                    // If there is a wall on this block
                    else
                    {
                        // There is definitely no dead end here
                        m_DeadEnd[BlockX][BlockY] = -1;
                    }
                } // if
            } // if
        } // for
    } // for

    //*****************
    // SOFT WALL NEAR
    //*****************

// Used when determining the number of soft walls near each block.
// This is the maximum distance (in blocks) of the soft wall from the block.
#define SOFT_WALL_NEAR_MAX_DEPTH    2

    // Auxiliary variables for code readability : is there a soft wall around the current block?
    bool IsSoftWallUp;
    bool IsSoftWallDown;
    bool IsSoftWallLeft;
    bool IsSoftWallRight;
    
    // Current distance of the scanned block from the start block
    int Depth;

    // Scan the blocks of the arena
    for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
    {
        for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
        {
            // If the block is on the edges of the arena grid
            if (BlockX == 0 || BlockX == ARENA_WIDTH - 1 ||
                BlockY == 0 || BlockY == ARENA_HEIGHT - 1)
            {
                // There is definitely no soft wall near here
                m_SoftWallNear[BlockX][BlockY] = -1;
            }
            // If the block is not on the edges of the arena grid
            else
            {
                // Is there a wall on this block?
                IsWallHere = m_pArena->IsWall (BlockX, BlockY);

                // If there is no wall on this block
                if (!IsWallHere)
                {
                    //----------------------
                    // Scan above the block
                    //----------------------
                    
                    // Start scanning (distance 1 from the block)
                    Depth = 1;

                    // Scan until there is a wall or until maximum depth has been reached
                    do
                    {
                        // Is there a wall on the scanned block?
                        IsWallUp = m_pArena->IsWall (BlockX, BlockY - Depth);

                        // Is there a soft wall on the scanned block?
                        IsSoftWallUp = m_pArena->IsSoftWall (BlockX, BlockY - Depth);

                        // Continue scanning
                        Depth++;
                    }
                    while (Depth <= SOFT_WALL_NEAR_MAX_DEPTH && !IsWallUp && !m_pArena->IsItem(BlockX, BlockY - Depth));

                    //----------------------
                    // Scan below the block
                    //----------------------
                    
                    // Start scanning (distance 1 from the block)
                    Depth = 1;

                    // Scan until there is a wall or until maximum depth has been reached
                    do
                    {
                        // Is there a wall on the scanned block?
                        IsWallDown = m_pArena->IsWall (BlockX, BlockY + Depth);

                        // Is there a soft wall on the scanned block?
                        IsSoftWallDown = m_pArena->IsSoftWall (BlockX, BlockY + Depth);

                        // Continue scanning
                        Depth++;
                    }
                    while (Depth <= SOFT_WALL_NEAR_MAX_DEPTH && !IsWallDown && !m_pArena->IsItem(BlockX, BlockY + Depth));

                    //-------------------------------
                    // Scan to the left of the block
                    //-------------------------------
                    
                    // Start scanning (distance 1 from the block)
                    Depth = 1;

                    // Scan until there is a wall or until maximum depth has been reached
                    do
                    {
                        // Is there a wall on the scanned block?
                        IsWallLeft = m_pArena->IsWall (BlockX - Depth, BlockY);
                        
                        // Is there a soft wall on the scanned block?
                        IsSoftWallLeft = m_pArena->IsSoftWall (BlockX - Depth, BlockY);
                        
                        // Continue scanning
                        Depth++;
                    }
                    while (Depth <= SOFT_WALL_NEAR_MAX_DEPTH && !IsWallLeft && !m_pArena->IsItem(BlockX - Depth, BlockY));

                    //--------------------------------
                    // Scan to the right of the block
                    //--------------------------------

                    // Start scanning (distance 1 from the block)                    
                    Depth = 1;

                    // Scan until there is a wall or until maximum depth has been reached
                    do
                    {
                        // Is there a wall on the scanned block?
                        IsWallRight = m_pArena->IsWall (BlockX + Depth, BlockY);
                        
                        // Is there a soft wall on the scanned block?
                        IsSoftWallRight = m_pArena->IsSoftWall (BlockX + Depth, BlockY);
                        
                        // Continue scanning
                        Depth++;
                    }
                    while (Depth <= SOFT_WALL_NEAR_MAX_DEPTH && !IsWallRight && !m_pArena->IsItem(BlockX + Depth, BlockY));

                    //--------------------------------------------------
                    // Count total number of soft walls near this block
                    //--------------------------------------------------

                    // No soft walls near this block yet
                    int NumSoftWallsNear = 0;

                    // Increase this number for each direction if there is a soft wall in this direction
                    if (IsSoftWallUp)         NumSoftWallsNear++;
                    if (IsSoftWallDown)       NumSoftWallsNear++;
                    if (IsSoftWallLeft)       NumSoftWallsNear++;
                    if (IsSoftWallRight)      NumSoftWallsNear++;

                    // Set the number of soft walls near this block
                    m_SoftWallNear[BlockX][BlockY] = NumSoftWallsNear;
                }
                // If there is a wall on this block
                else
                {   
                    // There is definitely no soft wall near here         
                    m_SoftWallNear[BlockX][BlockY] = -1;
                }
            } // if
        } // for
    } // for
    
    // if debug function enabled: draw some squares showing the accesibility
#if defined(DEBUG_DRAW_SOFTWALL_BLOCKS) || defined(DEBUG_DRAW_BURNWALLDANGER_BLOCKS) || defined(DEBUG_DRAW_BOMB_OWNERS)
    // debug display
    BYTE r, g, b;
    BYTE rbase, gbase, bbase;
    int w, h;

    m_pDisplay->RemoveAllDebugRectangles();
#endif
#ifdef DEBUG_DRAW_SOFTWALL_BLOCKS
    rbase = 128; gbase = 128; bbase = 128; 
    
    w = m_pArena->ToPosition(1);
    h = m_pArena->ToPosition(1);
    
    if (m_pDisplay != NULL)
    {
        m_pDisplay->RemoveAllDebugRectangles();
        for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
        {
            for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
            {
                if (m_SoftWallNear[BlockX][BlockY] > 0)
                {
                    r = rbase + m_SoftWallNear[BlockX][BlockY] * 8;
                    g = gbase + m_SoftWallNear[BlockX][BlockY] * 8;
                    b = bbase + m_SoftWallNear[BlockX][BlockY] * 8;
                    
		            m_pDisplay->DrawDebugRectangle (
                        m_pArena->ToPosition(BlockX), 
                        m_pArena->ToPosition(BlockY), 
                        w, h, r, g, b, AIARENADEBUG_SPRITELAYER, PRIORITY_UNUSED);
                }
            }
        }
    }
#endif

    //*************
    // DANGER AND BURNING WALL AND BURNING SOON WALL
    //*************
    
    // Scan each block of the danger array and wallburn array
    for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
    {
        for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
        {
            // Set no danger for the moment
            m_Danger[BlockX][BlockY] = DANGER_NONE;

            m_DangerTimeLeft[BlockX][BlockY] = 999.0f;

            // Set true if there is a burning wall
            m_WallBurn[BlockX][BlockY] = m_pArena->IsBurningWall(BlockX, BlockY);
        }
    }
    
    // create an index array for the bombs
    // each element represents a bomb. its value is the index to the bomb which
    // will ignite this bomb.
    int *BombIndex = new int[m_pArena->MaxBombs()];
    if (BombIndex == NULL) return;
    
    for (int Index = 0; Index < m_pArena->MaxBombs(); Index++)
    {
        BombIndex[Index] = Index; // start with the bomb itself
    }

    // Was there an update?
    bool Updated;
    
    // Scan each block of the arena
    do {
        Updated = false;
        
        for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
        {
            for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
            {
                // If there is a flame or a wall on this block
                if (m_pArena->IsFlame (BlockX, BlockY) || m_pArena->IsWall (BlockX, BlockY))
                {
                    // This block is mortal
                    m_Danger[BlockX][BlockY] = DANGER_MORTAL;
                    m_DangerTimeLeft[BlockX][BlockY] = 0.0f;
                }
                // If there is a bomb on this block
                else if (m_pArena->IsBomb (BlockX, BlockY))
                {
                    // This block will at least soon be mortal (but it can already be mortal)
                    if (m_Danger[BlockX][BlockY] == DANGER_NONE)
                        m_Danger[BlockX][BlockY] = DANGER_SOON;

                    float TimeLeft = -1.0f;
                    int FlameSize = -1;
                    bool IgnoreBomb = false;
                    int ThisBombIndex = -1;
                    
                    for (int Index = 0 ; Index < m_pArena->MaxBombs() ; Index++)
                    {
                        if (m_pArena->GetBomb(Index).GetBlockX() == BlockX &&
                            m_pArena->GetBomb(Index).GetBlockY() == BlockY)
                        {
                            FlameSize = m_pArena->GetBomb(Index).GetFlameSize();
                            // Time left will be propagated to all bombs being ignited by this bomb
                            TimeLeft = m_pArena->GetBomb(BombIndex[Index]).GetTimeLeft();
                            // ignore bomb: when we don't know when a bomb explodes
                            // we can't know when the soft walls around will disappear
                            ThisBombIndex = BombIndex[Index];
                            IgnoreBomb = m_pArena->GetBomb(Index).IsRemote() &&
                                !m_pArena->GetBomber(m_pArena->GetBomb(Index).GetOwnerPlayer()).IsAlive();
                            break;
                        }
                    }

                    ASSERT (TimeLeft != -1.0f);
                    ASSERT (FlameSize != -1);
                    ASSERT (ThisBombIndex != -1);

                    if (FlameSize >= 4)
                    {
                        switch (FlameSize)
                        {
                            case 4  : FlameSize =  5; break;
                            case 5  : FlameSize =  7; break;
                            case 6  : FlameSize =  8; break;
                            default : FlameSize = 99; break;
                        }
                    }

                    int Depth;
                    
                    // Block coordinates used to scan the blocks where the bomb creates danger
                    int DangerBlockX;
                    int DangerBlockY;
                    
                    // Auxiliary variables for updating the timeleft when another bomb
                    // was found which may ignite the bomb we're currently dealing with
                    int UpdateX;
                    int UpdateY;
                    
                    // Auxilary variable for the time left on the current block
                    float TimeLeftHere;
                    
                    // Auxiliary variables for code readability : is there a wall/bomb on the current block?
                    bool IsWall;
                    bool IsBomb;
                    
                    // Start scanning on this block
                    DangerBlockX = BlockX;
                    DangerBlockY = BlockY;
                    Depth = 0;

                    // No wall and no bomb on the current block
                    IsWall = false;
                    IsBomb = false;
                    
                    // While there is no wall or bomb that could stop the explosion flames
                    while (true)
                    {
                        // If there is a bomb where we are scanning or if we scanned deep enough
                        if (IsBomb || Depth > FlameSize)
                        {
                            // Update time left if this bomb might ignite the other
                            for (int Index = 0 ; IsBomb && Index < m_pArena->MaxBombs() ; Index++)
                            {
                                if (m_pArena->GetBomb(Index).GetBlockX() == DangerBlockX &&
                                    m_pArena->GetBomb(Index).GetBlockY() == DangerBlockY)
                                {
                                    TimeLeftHere = m_pArena->GetBomb(BombIndex[Index]).GetTimeLeft();
                                    if (TimeLeft > TimeLeftHere)
                                    {
                                        TimeLeft = TimeLeftHere;
                                        Updated = true;
                                        
                                        // update timeleft on the blocks which have been passed
                                        for (UpdateX = BlockX; UpdateX <= DangerBlockX; UpdateX++)
                                            m_DangerTimeLeft[UpdateX][DangerBlockY] = TimeLeft;
                                        
                                        // update BombIndex array elements
                                        for (int i = 0; i < m_pArena->MaxBombs(); i++)
                                            if (BombIndex[i] == ThisBombIndex)
                                                BombIndex[i] = BombIndex[Index];
                                    }
                                    
                                    break;
                                }
                            }
                            
                            // Stop scanning.
                            break;
                        }
                        // If there is a wall where we are scanning
                        else if (IsWall)
                        {
                            // If this is a soft wall
                            if (m_pArena->IsSoftWall(DangerBlockX,DangerBlockY))
                            {
                                // Then this wall will soon burn (unless we think we can ignore the bomb)
                                // in this case it is uncertain when the wall will be burned
                                if (!IgnoreBomb)
                                    m_WallBurn[DangerBlockX][DangerBlockY] = true;
                            }

                            // Stop scanning.
                            break;
                        }
                        // If there is no bomb and no wall on the block where we are scanning
                        else if (!IgnoreBomb)
                        {
                            // If no danger was recorded on this block
                            if (m_Danger[DangerBlockX][DangerBlockY] == DANGER_NONE)
                            {
                                // This block will soon be mortal
                                m_Danger[DangerBlockX][DangerBlockY] = DANGER_SOON;
                            }

                            if (m_DangerTimeLeft[DangerBlockX][DangerBlockY] > TimeLeft)
                            {
                                m_DangerTimeLeft[DangerBlockX][DangerBlockY] = TimeLeft;
                            }
                        }

                        // Continue scanning (go right)
                        DangerBlockX++;
                        Depth++;            // Go deeper

                        // Update auxiliary variables
                        IsWall = m_pArena->IsWall(DangerBlockX,DangerBlockY);
                        IsBomb = m_pArena->IsBomb(DangerBlockX,DangerBlockY);
                    } // while

                    // Start scanning on this block
                    DangerBlockX = BlockX;
                    DangerBlockY = BlockY;
                    Depth = 0;

                    // No wall and no bomb on the current block
                    IsWall = false;
                    IsBomb = false;

                    // While there is no wall or bomb that could stop the explosion flames
                    while (true)
                    {
                        // If there is a bomb where we are scanning or if we scanned deep enough
                        if (IsBomb || Depth > FlameSize)
                        {
                            // Update time left if this bomb might ignite the other
                            for (int Index = 0 ; IsBomb && Index < m_pArena->MaxBombs() ; Index++)
                            {
                                if (m_pArena->GetBomb(Index).GetBlockX() == DangerBlockX &&
                                    m_pArena->GetBomb(Index).GetBlockY() == DangerBlockY)
                                {
                                    TimeLeftHere = m_pArena->GetBomb(BombIndex[Index]).GetTimeLeft();
                                    if (TimeLeft > TimeLeftHere)
                                    {
                                        TimeLeft = TimeLeftHere;
                                        Updated = true;
                                        
                                        // update timeleft on the blocks which have been passed
                                        for (UpdateX = DangerBlockX; UpdateX <= BlockX; UpdateX++)
                                            m_DangerTimeLeft[UpdateX][DangerBlockY] = TimeLeft;

                                        // update BombIndex array elements
                                        for (int i = 0; i < m_pArena->MaxBombs(); i++)
                                            if (BombIndex[i] == ThisBombIndex)
                                                BombIndex[i] = BombIndex[Index];
                                    }
                                    
                                    break;
                                }
                            }
                            
                            // Stop scanning.
                            break;
                        }
                        // If there is a wall where we are scanning
                        else if (IsWall)
                        {
                            // If this is a soft wall
                            if (m_pArena->IsSoftWall(DangerBlockX,DangerBlockY))
                            {
                                // Then this wall will soon burn (unless we think we can ignore the bomb)
                                if (!IgnoreBomb)
                                    m_WallBurn[DangerBlockX][DangerBlockY] = true;
                            }

                            // Stop scanning.
                            break;
                        }
                        // If there is no bomb and no wall on the block where we are scanning
                        else if (!IgnoreBomb)
                        {
                            // If no danger was recorded on this block
                            if (m_Danger[DangerBlockX][DangerBlockY] == DANGER_NONE)
                            {
                                // This block will soon be mortal
                                m_Danger[DangerBlockX][DangerBlockY] = DANGER_SOON;
                            }

                            if (m_DangerTimeLeft[DangerBlockX][DangerBlockY] > TimeLeft)
                            {
                                m_DangerTimeLeft[DangerBlockX][DangerBlockY] = TimeLeft;
                            }
                        }
                        
                        // Continue scanning (go left)
                        DangerBlockX--;
                        Depth++;            // Go deeper

                        // Update auxiliary variables
                        IsWall = m_pArena->IsWall(DangerBlockX,DangerBlockY);
                        IsBomb = m_pArena->IsBomb(DangerBlockX,DangerBlockY);
                    } // while

                    // Start scanning on this block
                    DangerBlockX = BlockX;
                    DangerBlockY = BlockY;
                    Depth = 0;

                    // No wall and no bomb on the current block
                    IsWall = false;
                    IsBomb = false;

                    // While there is no wall or bomb that could stop the explosion flames
                    while (true)
                    {
                        // If there is a bomb where we are scanning or if we scanned deep enough
                        if (IsBomb || Depth > FlameSize)
                        {
                            // Update time left if this bomb might ignite the other
                            for (int Index = 0 ; IsBomb && Index < m_pArena->MaxBombs() ; Index++)
                            {
                                if (m_pArena->GetBomb(Index).GetBlockX() == DangerBlockX &&
                                    m_pArena->GetBomb(Index).GetBlockY() == DangerBlockY)
                                {
                                    TimeLeftHere = m_pArena->GetBomb(BombIndex[Index]).GetTimeLeft();
                                    if (TimeLeft > TimeLeftHere)
                                    {
                                        TimeLeft = TimeLeftHere;
                                        Updated = true;
                                        
                                        // update timeleft on the blocks which have been passed
                                        for (UpdateY = DangerBlockY; UpdateY <= BlockY; UpdateY++)
                                            m_DangerTimeLeft[DangerBlockX][UpdateY] = TimeLeft;

                                        // update BombIndex array elements
                                        for (int i = 0; i < m_pArena->MaxBombs(); i++)
                                            if (BombIndex[i] == ThisBombIndex)
                                                BombIndex[i] = BombIndex[Index];
                                    }
                                    
                                    break;
                                }
                            }
                            
                            // Stop scanning.
                            break;
                        }
                        // If there is a wall where we are scanning
                        else if (IsWall)
                        {
                            // If this is a soft wall
                            if (m_pArena->IsSoftWall(DangerBlockX,DangerBlockY))
                            {
                                // Then this wall will soon burn (unless we think we can ignore the bomb)
                                // in this case it is uncertain when the wall will be burned
                                if (!IgnoreBomb)
                                    m_WallBurn[DangerBlockX][DangerBlockY] = true;
                            }

                            // Stop scanning.
                            break;
                        }
                        // If there is no bomb and no wall on the block where we are scanning
                        else if (!IgnoreBomb)
                        {
                            // If no danger was recorded on this block
                            if (m_Danger[DangerBlockX][DangerBlockY] == DANGER_NONE)
                            {
                                // This block will soon be mortal
                                m_Danger[DangerBlockX][DangerBlockY] = DANGER_SOON;
                            }

                            if (m_DangerTimeLeft[DangerBlockX][DangerBlockY] > TimeLeft)
                            {
                                m_DangerTimeLeft[DangerBlockX][DangerBlockY] = TimeLeft;
                            }
                        }
                        
                        // Continue scanning (go up)
                        DangerBlockY--;
                        Depth++;            // Go deeper

                        // Update auxiliary variables
                        IsWall = m_pArena->IsWall(DangerBlockX,DangerBlockY);
                        IsBomb = m_pArena->IsBomb(DangerBlockX,DangerBlockY);
                    } // while

                    // Start scanning on this block
                    DangerBlockX = BlockX;
                    DangerBlockY = BlockY;
                    Depth = 0;

                    // No wall and no bomb on the current block
                    IsWall = false;
                    IsBomb = false;

                    // While there is no wall or bomb that could stop the explosion flames
                    while (true)
                    {
                        // If there is a bomb where we are scanning or if we scanned deep enough
                        if (IsBomb || Depth > FlameSize)
                        {
                            // Update time left if this bomb might ignite the other
                            for (int Index = 0 ; IsBomb && Index < m_pArena->MaxBombs() ; Index++)
                            {
                                if (m_pArena->GetBomb(Index).GetBlockX() == DangerBlockX &&
                                    m_pArena->GetBomb(Index).GetBlockY() == DangerBlockY)
                                {
                                    TimeLeftHere = m_pArena->GetBomb(BombIndex[Index]).GetTimeLeft();
                                    if (TimeLeft > TimeLeftHere)
                                    {
                                        TimeLeft = TimeLeftHere;
                                        Updated = true;
                                        
                                        // update timeleft on the blocks which have been passed
                                        for (UpdateY = BlockY; UpdateY <= DangerBlockY; UpdateY++)
                                            m_DangerTimeLeft[DangerBlockX][UpdateY] = TimeLeft;
                                        
                                        // update BombIndex array elements
                                        for (int i = 0; i < m_pArena->MaxBombs(); i++)
                                            if (BombIndex[i] == ThisBombIndex)
                                                BombIndex[i] = BombIndex[Index];
                                    }
                                    
                                    break;
                                }
                            }
                            
                            // Stop scanning.
                            break;
                        }
                        // If there is a wall where we are scanning
                        else if (IsWall)
                        {
                            // If this is a soft wall
                            if (m_pArena->IsSoftWall(DangerBlockX,DangerBlockY))
                            {
                                // Then this wall will soon burn (unless we think we can ignore the bomb)
                                // in this case it is uncertain when the wall will be burned
                                if (!IgnoreBomb)
                                    m_WallBurn[DangerBlockX][DangerBlockY] = true;
                            }

                            // Stop scanning.
                            break;
                        }
                        // If there is no bomb and no wall on the block where we are scanning
                        else if (!IgnoreBomb)
                        {
                            // If no danger was recorded on this block
                            if (m_Danger[DangerBlockX][DangerBlockY] == DANGER_NONE)
                            {
                                // This block will soon be mortal
                                m_Danger[DangerBlockX][DangerBlockY] = DANGER_SOON;
                            }

                            if (m_DangerTimeLeft[DangerBlockX][DangerBlockY] > TimeLeft)
                            {
                                m_DangerTimeLeft[DangerBlockX][DangerBlockY] = TimeLeft;
                            }
                        }
                        
                        // Continue scanning (go down)
                        DangerBlockY++;
                        Depth++;            // Go deeper

                        // Update auxiliary variables
                        IsWall = m_pArena->IsWall(DangerBlockX,DangerBlockY);
                        IsBomb = m_pArena->IsBomb(DangerBlockX,DangerBlockY);
                    } // while
                } // if
            } // for
        } // for
    } // do
    while (Updated);
    
    delete[] BombIndex;
    
    // If the arena is closing right now
    if (m_pArena->GetArenaCloser().IsClosing ())
    {
        // Save in how many seconds the next falling wall will start falling
        float DangerTimeLeft = m_pArena->GetArenaCloser().GetTimeLeftBeforeClosingNextBlock();

        // Scan the next X blocks that will be closed
        for (int Index = 0 ; Index < m_pArena->GetArenaCloser().GetNumberOfBlocksLeft() && Index < 10 ; Index++)
        {
            // Save the block position of the block that will soon be closed
            BlockX = m_pArena->GetArenaCloser().GetNextBlockPositionX (Index);
            BlockY = m_pArena->GetArenaCloser().GetNextBlockPositionY (Index);

            // If there is no danger on this block
            if (m_Danger[BlockX][BlockY] == DANGER_NONE)
            {
                // Now this block will soon be dangerous
                m_Danger[BlockX][BlockY] = DANGER_SOON;
            }

            // If the danger of this falling wall will happen earlier
            // than the current recorded danger on this block
            if (m_DangerTimeLeft[BlockX][BlockY] > DangerTimeLeft)
            {
                // The danger that will happen earlier has a higher priority
                m_DangerTimeLeft[BlockX][BlockY] = DangerTimeLeft;
            }

            // Get the time left in seconds before the next falling wall will start falling
            DangerTimeLeft += m_pArena->GetArenaCloser().GetTimeBetweenTwoBlockClosures();
        }
    }

#if defined(DEBUG_DRAW_BURNWALLDANGER_BLOCKS) || defined(DEBUG_DRAW_BOMB_OWNERS)
    // red: danger, blue: burnwall
    rbase = 128; gbase = 0; bbase = 128; 
    
    w = m_pArena->ToPosition(1);
    h = m_pArena->ToPosition(1);
    
    if (m_pDisplay != NULL)
    {
        for (BlockX = 0 ; BlockX < ARENA_WIDTH ; BlockX++)
        {
            for (BlockY = 0 ; BlockY < ARENA_HEIGHT ; BlockY++)
            {
                if (m_Danger[BlockX][BlockY] != DANGER_NONE &&
                    !m_pArena->IsWall(BlockX,BlockY) &&
                    !m_pArena->IsBomb(BlockX,BlockY))
                {
                    r = rbase;
                    if (m_Danger[BlockX][BlockY] == DANGER_MORTAL)
                        r += 64;
                    
                    r += MIN(64, (int)floor(m_DangerTimeLeft[BlockX][BlockY] * 30.0));
                    
		            m_pDisplay->DrawDebugRectangle (
                        m_pArena->ToPosition(BlockX), 
                        m_pArena->ToPosition(BlockY), 
                        w, h, r, 0, 0, AIARENADEBUG_SPRITELAYER, PRIORITY_UNUSED);
                    
                    m_Font.Draw (m_pArena->ToPosition(BlockX),
                                 m_pArena->ToPosition(BlockY)+h/4, "%.1f",
                                 floor(m_DangerTimeLeft[BlockX][BlockY]*10)/10);

                }
                else if (m_WallBurn[BlockX][BlockY])
                {
                    b = bbase;
                    
		            m_pDisplay->DrawDebugRectangle (
                        m_pArena->ToPosition(BlockX), 
                        m_pArena->ToPosition(BlockY), 
                        w, h, 0, 0, b, AIARENADEBUG_SPRITELAYER, PRIORITY_UNUSED);
                }
                
#ifdef DEBUG_DRAW_BOMB_OWNERS
                if (m_pArena->IsBomb (BlockX, BlockY))
                {
                    for (int Index = 0 ; Index < m_pArena->MaxBombs() ; Index++)
                    {
                        if (m_pArena->GetBomb(Index).GetBlockX() == BlockX &&
                            m_pArena->GetBomb(Index).GetBlockY() == BlockY)
                        {
                            if (!m_pArena->GetBomber(m_pArena->GetBomb(Index).GetOwnerPlayer()).IsAlive())
                            {
                                // bomber is dead
                                r = 0; g = 255; b = 255;
                            }
                            else
                            {
                                switch (m_pArena->GetBomb(Index).GetOwnerPlayer())
                                {
                                    case 0 : r = 255; g = 255; b = 255; break;
                                    case 1 : r = 0;   g = 0;   b = 0;   break;
                                    case 2 : r = 255; g = 0;   b = 0;   break;
                                    case 3 : r = 0;   g = 0;   b = 255; break;
                                    case 4 : r = 0;   g = 255; b = 0;   break;
                                    default: r = g = b = 0;             break;
                                }
                            }
                            
		                    m_pDisplay->DrawDebugRectangle (
                                m_pArena->ToPosition(BlockX), 
                                m_pArena->ToPosition(BlockY), 
                                w, h, r, g, b, AIARENADEBUG_SPRITELAYER, PRIORITY_UNUSED);
                            break;
                        }
                    }
                }  
#endif
            }
        }
    }
#endif
}