// File: miklhh[P]tetris/src/game.cpp
// Function: test_movable(block_t*, int)
collision_t test_movable(block_t* block, direction_t direction)
{
	/* Make a copy of the block and move it. */
	block_t block_copy = *block;
	block_move(&block_copy, direction);

	/* Test if the block interfears with any other placed box, or wall. */
	collision_t collision = NO_COLLISION;

	/* Test collision with other boxes. */
	for (int y = 0; y < MAX_BLOCK_WIDTH; y++)
	{
		for (int x = 0; x < MAX_BLOCK_HEIGHT; x++)
		{
			if (block_copy.structure.tile[y][x] == FILLED   &&
				field[y + block_copy.position.y][x + block_copy.position.x].tile == TAKEN)
			{
				collision = COLLISION_BLOCK;
			}
		}
	}

	/* Test collision with wall. */
	switch (direction)
	{
	case DIRECTION_LEFT:
		/* Test for collision with left side wall. */
		for (int y = 0; y < MAX_BLOCK_HEIGHT; y++)
		{
			for (int x = 0; x < MAX_BLOCK_WIDTH; x++)
			{
				if (block_copy.structure.tile[y][x] == FILLED   &&
					x + block_copy.position.x < 0)
				{
					collision = COLLISION_WALL_R;
				}
			}
		}
		break;

	case DIRECTION_RIGHT:
		/* Test for collision with the right side wall. */
		for (int y = 0; y < MAX_BLOCK_HEIGHT; y++)
		{
			for (int x = 0; x < MAX_BLOCK_WIDTH; x++)
			{
				if (block_copy.structure.tile[y][x] == FILLED   &&
					x + block_copy.position.x > GRID_WIDTH - 1)
				{
					collision = COLLISION_WALL_R;
				}
			}
		}
		break;
		
	case DIRECTION_UP:
		/* Test for collision with the upper side wall. */
		for (int y = 0; y < MAX_BLOCK_HEIGHT; y++)
		{
			for (int x = 0; x < MAX_BLOCK_WIDTH; x++)
			{
				if (block_copy.structure.tile[y][x] == FILLED   &&
					y + block_copy.position.y < 0)
				{
					collision = COLLISION_WALL_U;
				}
			}
		}
		break;

	case DIRECTION_DOWN:
		/* Test for collision the the lower side wall. */
		for (int y = 0; y < MAX_BLOCK_HEIGHT; y++)
		{
			for (int x = 0; x < MAX_BLOCK_WIDTH; x++)
			{
				if (block_copy.structure.tile[y][x] == FILLED   &&
					y + block_copy.position.y > GRID_HEIGHT - 1)
				{
					collision = COLLISION_WALL_D;
				}
			}
		}
		break;

	default:
		break;
	}
	return collision;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x5c(%rbp), %rdi
movl $0x50, %edx
callq 0x2130
movl -0xc(%rbp), %esi
leaq -0x5c(%rbp), %rdi
callq 0x2b80
movl $0x0, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
cmpl $0x4, -0x64(%rbp)
jge 0x30cc
movl $0x0, -0x68(%rbp)
cmpl $0x4, -0x68(%rbp)
jge 0x30bf
leaq -0x5c(%rbp), %rax
addq $0x10, %rax
movslq -0x64(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movslq -0x68(%rbp), %rcx
cmpl $0x1, (%rax,%rcx,4)
jne 0x30b2
movl -0x64(%rbp), %eax
addl -0x50(%rbp), %eax
movslq %eax, %rcx
leaq 0x50e2(%rip), %rax      # 0x8170
imulq $0x78, %rcx, %rcx
addq %rcx, %rax
movl -0x68(%rbp), %ecx
addl -0x54(%rbp), %ecx
movslq %ecx, %rcx
imulq $0xc, %rcx, %rcx
addq %rcx, %rax
cmpl $0x1, 0x8(%rax)
jne 0x30b2
movl $0x5, -0x60(%rbp)
jmp 0x30b4
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x305b
jmp 0x30c1
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x304e
movl -0xc(%rbp), %eax
movq %rax, -0x90(%rbp)
subq $0x3, %rax
ja 0x32b5
movq -0x90(%rbp), %rax
leaq 0x1fa6(%rip), %rcx      # 0x5094
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x0, -0x6c(%rbp)
cmpl $0x4, -0x6c(%rbp)
jge 0x315a
movl $0x0, -0x70(%rbp)
cmpl $0x4, -0x70(%rbp)
jge 0x314d
leaq -0x5c(%rbp), %rax
addq $0x10, %rax
movslq -0x6c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movslq -0x70(%rbp), %rcx
cmpl $0x1, (%rax,%rcx,4)
jne 0x3140
movl -0x70(%rbp), %eax
addl -0x54(%rbp), %eax
cmpl $0x0, %eax
jge 0x3140
movl $0x2, -0x60(%rbp)
jmp 0x3142
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x310b
jmp 0x314f
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
jmp 0x30fe
jmp 0x32b7
movl $0x0, -0x74(%rbp)
cmpl $0x4, -0x74(%rbp)
jge 0x31c2
movl $0x0, -0x78(%rbp)
cmpl $0x4, -0x78(%rbp)
jge 0x31b5
leaq -0x5c(%rbp), %rax
addq $0x10, %rax
movslq -0x74(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movslq -0x78(%rbp), %rcx
cmpl $0x1, (%rax,%rcx,4)
jne 0x31a8
movl -0x78(%rbp), %eax
addl -0x54(%rbp), %eax
cmpl $0x9, %eax
jle 0x31a8
movl $0x2, -0x60(%rbp)
jmp 0x31aa
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x3173
jmp 0x31b7
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x3166
jmp 0x32b7
movl $0x0, -0x7c(%rbp)
cmpl $0x4, -0x7c(%rbp)
jge 0x322a
movl $0x0, -0x80(%rbp)
cmpl $0x4, -0x80(%rbp)
jge 0x321d
leaq -0x5c(%rbp), %rax
addq $0x10, %rax
movslq -0x7c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movslq -0x80(%rbp), %rcx
cmpl $0x1, (%rax,%rcx,4)
jne 0x3210
movl -0x7c(%rbp), %eax
addl -0x50(%rbp), %eax
cmpl $0x0, %eax
jge 0x3210
movl $0x3, -0x60(%rbp)
jmp 0x3212
movl -0x80(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x80(%rbp)
jmp 0x31db
jmp 0x321f
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x31ce
jmp 0x32b7
movl $0x0, -0x84(%rbp)
cmpl $0x4, -0x84(%rbp)
jge 0x32b3
movl $0x0, -0x88(%rbp)
cmpl $0x4, -0x88(%rbp)
jge 0x32a0
leaq -0x5c(%rbp), %rax
addq $0x10, %rax
movslq -0x84(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movslq -0x88(%rbp), %rcx
cmpl $0x1, (%rax,%rcx,4)
jne 0x328d
movl -0x84(%rbp), %eax
addl -0x50(%rbp), %eax
cmpl $0x13, %eax
jle 0x328d
movl $0x4, -0x60(%rbp)
jmp 0x328f
movl -0x88(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x88(%rbp)
jmp 0x324c
jmp 0x32a2
movl -0x84(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x84(%rbp)
jmp 0x3239
jmp 0x32b7
jmp 0x32b7
movl -0x60(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)