' Memory defragmentation simulator — compact fragmented blocks into contiguous free space
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN() AS LONG
    LOCAL i  AS LONG
    LOCAL j  AS LONG
    LOCAL blockCount  AS LONG
    LOCAL totalSize  AS LONG
    LOCAL freeSpace  AS LONG
    LOCAL maxFree  AS LONG
    LOCAL bestIdx  AS LONG
    LOCAL heapSize  AS LONG
    LOCAL allocated  AS LONG
    LOCAL used  AS LONG
    LOCAL overhead  AS LONG
    LOCAL compacted AS LONG
    LOCAL blocks(400) AS LONG
    LOCAL sizes(400) AS LONG
    LOCAL freeList(400) AS LONG
    LOCAL freeSizes(400) AS LONG
    LOCAL freeCount AS LONG
    LOCAL blockStart  AS LONG
    LOCAL blockEnd  AS LONG
    LOCAL gap  AS LONG
    LOCAL srcIdx  AS LONG
    LOCAL dstIdx  AS LONG
    LOCAL tempSize  AS LONG
    LOCAL tempBlock  AS LONG
    LOCAL compHeap(2000) AS LONG

    heapSize = 2000
    allocated = 0
    blockCount = 20
    totalSize = 0

    PRINT "=== Memory Defragmentation Simulator ==="
    PRINT "Heap size:" & STR$(heapSize) & " units"
    PRINT

    RANDOMIZE TIMER

    FOR i = 0 TO blockCount - 1
        sizes(i) = 10 + (RND * 40)
        IF totalSize + sizes(i) > heapSize - 50 THEN
            sizes(i) = heapSize - totalSize - 50
            IF sizes(i) < 5 THEN EXIT FOR
        END IF
        blocks(i) = totalSize
        totalSize = totalSize + sizes(i)
        allocated = allocated + sizes(i)
    NEXT i
    blockCount = i

    PRINT "Initial allocation (" & STR$(blockCount) & " blocks, " & STR$(allocated) & " units used):"
    FOR i = 0 TO blockCount - 1
        PRINT "  Block " & FORMAT$(i) & ": offset " & FORMAT$(blocks(i)) & ", size " & FORMAT$(sizes(i))
    NEXT i
    PRINT "Free space:" & STR$(heapSize - allocated) & " units"
    PRINT

    FOR i = 0 TO blockCount - 1
        compHeap(blocks(i)) = i + 1
        FOR j = 1 TO sizes(i) - 1
            compHeap(blocks(i) + j) = 255
        NEXT j
    NEXT i

    RANDOMIZE TIMER
    FOR i = 1 TO 7
        j = RND * (blockCount - 1)
        IF sizes(j) > 0 THEN
            sizes(j) = -sizes(j)
        END IF
    NEXT i

    freeCount = 0
    used = 0
    freeSpace = 0
    PRINT "After freeing 7 random blocks:"
    FOR i = 0 TO blockCount - 1
        IF sizes(i) < 0 THEN
            PRINT "  Block " & FORMAT$(i) & ": FREED (was " & FORMAT$(-sizes(i)) & " units)"
            freeList(freeCount) = blocks(i)
            freeSizes(freeCount) = -sizes(i)
            freeCount = freeCount + 1
            freeSpace = freeSpace + (-sizes(i))
        ELSE
            IF sizes(i) > 0 THEN
                PRINT "  Block " & FORMAT$(i) & ": offset " & FORMAT$(blocks(i)) & ", size " & FORMAT$(sizes(i)) & " [LIVE]"
                used = used + sizes(i)
            END IF
        END IF
    NEXT i
    PRINT "Used:" & STR$(used) & ", Free:" & STR$(freeSpace) & ", Overhead:" & STR$(heapSize - used - freeSpace)
    PRINT

    FOR i = 0 TO blockCount - 1
        IF sizes(i) < 0 THEN sizes(i) = 0
    NEXT i

    compacted = 0
    dstIdx = 0

    FOR i = 0 TO blockCount - 1
        IF sizes(i) > 0 THEN
            IF blocks(i) <> dstIdx THEN
                tempSize = sizes(i)
                FOR j = 0 TO tempSize - 1
                    compHeap(dstIdx + j) = compHeap(blocks(i) + j)
                    compHeap(blocks(i) + j) = 0
                NEXT j
                blocks(i) = dstIdx
                compacted = compacted + 1
            END IF
            dstIdx = dstIdx + sizes(i)
        END IF
    NEXT i

    PRINT "After compaction (" & STR$(compacted) & " blocks moved):"
    FOR i = 0 TO blockCount - 1
        IF sizes(i) > 0 THEN
            PRINT "  Block " & FORMAT$(i) & ": offset " & FORMAT$(blocks(i)) & ", size " & FORMAT$(sizes(i)) & " [LIVE]"
        END IF
    NEXT i
    PRINT "Total contiguous free space at end:" & STR$(heapSize - dstIdx) & " units"
    PRINT "Compaction complete."

    FUNCTION = 0
END FUNCTION
