bad board attempt

This commit is contained in:
mehbark 2025-05-01 15:09:57 -04:00
parent 1d0a7f7bef
commit 3653f2a18d
9 changed files with 106 additions and 149 deletions

57
board.gd Normal file
View file

@ -0,0 +1,57 @@
class_name Board
extends Node3D
@export var dims: Vector2i
var pieces: Dictionary[Vector2i, Array] = {}
func pieces_at(pos: Vector2i) -> Array[Piece]:
return pieces.get(pos, [])
func remove_piece(piece: Piece, from: Vector2i):
pieces[from] = pieces_at(from).filter(func (p): return p != piece)
func add_piece(piece: Piece, to: Vector2i):
pieces.get_or_add(to, []).push_back(piece)
piece.position = Vector3(to.x, 0, to.y)
add_child(piece)
func add_pieces(piece: Array[Piece], to: Vector2i):
for p in piece:
add_piece(p, to)
func do_move(piece: Piece, from: Vector2i, to: Vector2i) -> Callable:
return func():
remove_piece(piece, from)
add_piece(piece, to)
func undo_move(piece: Piece, from: Vector2i, to: Vector2i) -> Callable:
return func():
remove_piece(piece, to)
add_piece(piece, from)
static func from_string(src: String) -> Board:
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 board := Board.new()
board.dims = dims
for y in range(lines.size()):
var line := lines[y]
for x in range(line.length()):
var c := line[x]
var pos := Vector2i(x, y)
match c:
".": board.add_piece(Piece.goal(), pos)
"*": board.add_pieces([Piece.goal(), Piece.box()], pos)
"+": board.add_pieces([Piece.goal(), Piece.player()], pos)
"$": board.add_piece(Piece.box(), pos)
"@": board.add_piece(Piece.player(), pos)
"#": board.add_piece(Piece.wall(), pos)
return board

1
board.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://c8ywa33v3jq7t

58
main.gd
View file

@ -10,37 +10,12 @@ var microban_1 := "
####
"
var states: Array[State] = [State.from_string(microban_1)]
var hist := UndoRedo.new()
const WALL = preload("res://wall.tres")
const GOAL = preload("res://goal.tres")
const BOX = preload("res://box.tres")
const PLAYER = preload("res://player.tres")
@onready var board: Node3D = $Board
@onready var board := Board.from_string(microban_1)
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): add_mesh(pos, WALL)
if pos == state.player_pos: add_mesh(pos, PLAYER)
add_child(board)
func _input(event: InputEvent) -> void:
if event.is_action_pressed("u"):
@ -52,29 +27,18 @@ func _input(event: InputEvent) -> void:
elif event.is_action_pressed("r"):
step(Vector2i.RIGHT)
elif event.is_action_pressed("undo"):
undo()
hist.undo()
elif event.is_action_pressed("redo"):
pass
print('hi')
hist.redo()
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
# TODO:
func restart():
push_state(states[0])
pass
func step(move: Vector2i):
push_state(current_state().step(move))
hist.create_action("move")
hist.commit_action()

View file

@ -16,10 +16,8 @@ sky = SubResource("Sky_0xm2m")
script = ExtResource("1_ig7tw")
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 0.258819, 0.965926, 0, -0.965926, 0.258819, 0, 3.48438, 1.16423)
transform = Transform3D(1, 0, 0, 0, 0.258819, 0.965926, 0, -0.965926, 0.258819, 0.035, 3.615, 3)
fov = 90.0
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_ig7tw")
[node name="Board" type="Node3D" parent="."]

34
piece.gd Normal file
View file

@ -0,0 +1,34 @@
class_name Piece
extends MeshInstance3D
const WALL = preload("res://wall.tres")
const GOAL = preload("res://goal.tres")
const BOX = preload("res://box.tres")
const PLAYER = preload("res://player.tres")
enum Type {
Wall,
Goal,
Box,
Player,
}
@export var type: Piece.Type
static func make(type: Piece.Type, mesh: Mesh) -> Piece:
var piece := Piece.new()
piece.mesh = mesh
piece.type = type
return piece
static func wall() -> Piece:
return make(Piece.Type.Wall, WALL)
static func goal() -> Piece:
return make(Piece.Type.Goal, GOAL)
static func box() -> Piece:
return make(Piece.Type.Box, BOX)
static func player() -> Piece:
return make(Piece.Type.Player, PLAYER)

1
piece.gd.uid Normal file
View file

@ -0,0 +1 @@
uid://bq3a5hhccxndn

View file

@ -74,6 +74,7 @@ redo={
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":true,"pressed":false,"keycode":0,"physical_keycode":89,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":85,"key_label":0,"unicode":85,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":true,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":90,"key_label":0,"unicode":90,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":80,"key_label":0,"unicode":112,"location":0,"echo":false,"script":null)
]
}

View file

@ -1,98 +0,0 @@
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 wall_at(pos) or box_at(pos)
func wall_at(pos: Vector2i) -> bool:
return walls.get_bitv(pos)
func goal_at(pos: Vector2i) -> bool:
return goals.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 := "#<<state:{0}>, {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

View file

@ -1 +0,0 @@
uid://bav3tjhu6anx