class_name State extends Resource @export var dims: Vector2i @export var player_pos: Vector2i @export var walls := BitMap.new() @export var goals := BitMap.new() @export var boxes := BitMap.new() static func from_string(src: String) -> State: var lines := src.lstrip("\n").rstrip("\n").split("\n") var width := 0 for line in lines: width = max(width, line.length()) var dims := Vector2i(width, lines.size()) var state := State.new() state.dims = dims state.walls.create(dims) state.goals.create(dims) state.boxes.create(dims) for y in range(lines.size()): var line := lines[y] for x in range(line.length()): var pos := Vector2i(x, y) match line[x]: "#": state.walls.set_bitv(pos, true) ".": state.goals.set_bitv(pos, true) "@": assert(not state.player_pos) state.player_pos = pos "+": assert(not state.player_pos) state.goals.set_bitv(pos, true) state.player_pos = pos "$": state.boxes.set_bitv(pos, true) "*": state.goals.set_bitv(pos, true) state.boxes.set_bitv(pos, true) assert(state.player_pos) return state func solid_at(pos: Vector2i) -> bool: return walls.get_bitv(pos) or boxes.get_bitv(pos) func box_at(pos: Vector2i) -> bool: return boxes.get_bitv(pos) func passable_at(pos: Vector2i) -> bool: return not solid_at(pos) # todo: keep shared structure (e.g. walls are always the same) func step(move: Vector2i) -> State: var new: State = duplicate(true) var p0 := new.player_pos var p1 := p0 + move var p2 := p1 + move if passable_at(p1): new.player_pos = p1 elif box_at(p1) and passable_at(p2): new.boxes.set_bitv(p1, false) new.boxes.set_bitv(p2, true) new.player_pos = p1 return new func _to_string() -> String: var out := "#<, {1}@{2}\n".format([get_instance_id(), dims, player_pos]) for y in range(dims.y): out += " " for x in range(dims.x): if player_pos == Vector2i(x, y): out += "+" if goals.get_bit(x, y) else "@" continue if walls.get_bit(x, y): out += "#" continue match [goals.get_bit(x, y), boxes.get_bit(x, y)]: [true, true ]: out += "*" [true, false]: out += "." [false, true ]: out += "$" [false, false]: out += " " out += "\n" out += ">" return out