extends Node3D var microban_1 := " #### # .# # ### #*@ # # $ # # ### #### " var states: Array[State] = [State.from_string(microban_1)] const WALL = preload("res://wall.tres") const GOAL = preload("res://goal.tres") const BOX = preload("res://box.tres") @onready var board: Node3D = $Board func _ready() -> void: render() func add_mesh(pos: Vector2i, mesh: Mesh): var offset := -current_state().dims/2.0 var meshinst := MeshInstance3D.new() meshinst.position = Vector3(pos.x + offset.x, 0, pos.y + offset.y) meshinst.mesh = mesh board.add_child(meshinst) func render() -> void: var state := current_state() for child in board.get_children(): child.free() for y in state.dims.y: for x in state.dims.x: var pos := Vector2i(x, y) if state.goal_at(pos): add_mesh(pos, GOAL) if state.box_at(pos): add_mesh(pos, BOX) if state.wall_at(pos) or pos == state.player_pos: add_mesh(pos, WALL) func _input(event: InputEvent) -> void: if event.is_action_pressed("u"): step(Vector2i.UP) elif event.is_action_pressed("d"): step(Vector2i.DOWN) elif event.is_action_pressed("l"): step(Vector2i.LEFT) elif event.is_action_pressed("r"): step(Vector2i.RIGHT) elif event.is_action_pressed("undo"): undo() elif event.is_action_pressed("redo"): pass elif event.is_action_pressed("restart"): restart() func current_state() -> State: return states[-1] func push_state(state: State): states.push_back(state) render() func undo(): if states.size() == 1: return states.pop_back() render() # todo: don't restart multiple times func restart(): push_state(states[0]) func step(move: Vector2i): push_state(current_state().step(move))