Skip to content

Instantly share code, notes, and snippets.

@itarato
Created September 19, 2015 03:41
Show Gist options
  • Select an option

  • Save itarato/01a7f02300e2b9fd9374 to your computer and use it in GitHub Desktop.

Select an option

Save itarato/01a7f02300e2b9fd9374 to your computer and use it in GitHub Desktop.
Unblock Me iOS game level 605 solver
package main
import (
"log"
"math/rand"
)
const MOVE_VERTICALLY = true
const MOVE_HORIZONTALLY = !MOVE_VERTICALLY
const MOVE_UPLEFT = -1
const MOVE_DOWNRIGHT = 1
const m_size_w = 6
const m_size_h = 6
var matrix [][]uint = [][]uint{
[]uint{1, 2, 3, 3, 3, 0},
[]uint{1, 2, 0, 4, 5, 0},
[]uint{1, 6, 6, 4, 5, 0},
[]uint{7, 7, 8, 0, 5, 0},
[]uint{0, 0, 8, 9, 9, 0},
[]uint{0, 10, 10, 11, 11, 0},
}
type Point struct {
X uint
Y uint
}
var point_map_h = &Point{Y: 0, X: MOVE_DOWNRIGHT}
var point_map_v = &Point{Y: MOVE_DOWNRIGHT, X: 0}
var point_map map[bool]*Point = map[bool]*Point{
MOVE_VERTICALLY: point_map_v,
MOVE_HORIZONTALLY: point_map_h,
}
type BlockProperty struct {
dir bool
length uint
pos Point
}
type MovableMemory struct {
left bool
right bool
id uint
}
var blocks map[uint]*BlockProperty = make(map[uint]*BlockProperty)
func main() {
register_blocks()
for step := 0; ; step++ {
make_move()
if is_solution() {
pretty_print_blocks()
log.Println("Solution found after step", step)
break
}
}
}
func pretty_print_blocks() {
out := "\n"
for _, row := range matrix {
for _, cell := range row {
if cell == 0 {
out += " "
} else if blocks[cell].dir == MOVE_HORIZONTALLY {
out += "-"
} else {
out += "|"
}
}
out += "\n"
}
log.Println(out)
}
func register_blocks() {
var i, j uint
for i = 0; i < m_size_h; i++ {
for j = 0; j < m_size_w; j++ {
block_id := matrix[i][j]
// Empty field.
if block_id == 0 {
continue
}
// Already registered block.
if _, ok := blocks[block_id]; ok {
continue
}
prop := &BlockProperty{}
var block_dir_map Point
if i < m_size_h-1 && matrix[i+1][j] == block_id {
prop.dir = MOVE_VERTICALLY
block_dir_map = Point{X: 0, Y: 1}
} else {
prop.dir = MOVE_HORIZONTALLY
block_dir_map = Point{X: 1, Y: 0}
}
prop.pos = Point{X: j, Y: i}
var length uint = 0
for matrix[i+length*block_dir_map.Y][j+length*block_dir_map.X] == block_id {
length++
}
prop.length = length
blocks[block_id] = prop
}
}
}
func make_move() {
selected, move_selected := select_for_move()
// log.Println("Move", selected.id, "to", move_selected)
mask_block(selected.id, 0)
props := blocks[selected.id]
move_map := point_map[props.dir]
props.pos.Y = uint(int(props.pos.Y) + int(move_map.Y)*move_selected)
props.pos.X = uint(int(props.pos.X) + int(move_map.X)*move_selected)
mask_block(selected.id, selected.id)
}
func get_movables() []MovableMemory {
var movable []MovableMemory
for block_id, _ := range blocks {
if left, right := is_movable(block_id); left || right {
movable = append(movable, MovableMemory{left: left, right: right, id: block_id})
}
}
return movable
}
func select_for_move() (MovableMemory, int) {
movable := get_movables()
selected := movable[rand.Intn(len(movable))]
var move_options []int
if selected.left {
move_options = append(move_options, MOVE_UPLEFT)
}
if selected.right {
move_options = append(move_options, MOVE_DOWNRIGHT)
}
move_selected := move_options[rand.Intn(len(move_options))]
return selected, move_selected
}
// Return: upleft, downright
func is_movable(block_id uint) (bool, bool) {
prop := blocks[block_id]
move_map := point_map[prop.dir]
move_left_y := prop.pos.Y - move_map.Y
move_left_x := prop.pos.X - move_map.X
move_right_y := prop.pos.Y + move_map.Y*(prop.length)
move_right_x := prop.pos.X + move_map.X*(prop.length)
var left, right bool
left = in_range(move_left_x, m_size_w) && in_range(move_left_y, m_size_h) && matrix[move_left_y][move_left_x] == 0
right = in_range(move_right_x, m_size_w) && in_range(move_right_y, m_size_h) && matrix[move_right_y][move_right_x] == 0
return left, right
}
func in_range(n, limit uint) bool {
return n >= 0 && n < limit
}
func mask_block(block_id uint, mask uint) {
props := blocks[block_id]
move_map := point_map[props.dir]
var i uint
for i = 0; i < props.length; i++ {
matrix[props.pos.Y+(move_map.Y*i)][props.pos.X+(move_map.X*i)] = mask
}
}
func is_solution() bool {
return matrix[2][5] == 6
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment