183 lines
6.0 KiB
GDScript3
183 lines
6.0 KiB
GDScript3
|
extends ColorRect
|
||
|
|
||
|
export var rows: int = 44
|
||
|
export var cols: int = 63
|
||
|
export var h_margin: int = 2
|
||
|
export var v_margin: int = 2
|
||
|
export var grid_color: Color = Color.black
|
||
|
var READY := false
|
||
|
|
||
|
const ByteArray2D = Common.ByteArray2D
|
||
|
const IntArray2D = Common.IntArray2D
|
||
|
|
||
|
onready var cell_numbers: ByteArray2D
|
||
|
const NUMBER_NONE := 255
|
||
|
onready var cell_colors: ByteArray2D
|
||
|
onready var corner_marks: IntArray2D
|
||
|
enum CornerMark {
|
||
|
L_RIGHT=1, L_DOWN=2, X_RIGHT=4, X_DOWN=8,
|
||
|
DARC_1=16, DARC_2=32, DARC_3=64, DARC_4=128,
|
||
|
SARC_1=256, SARC_2=512, SARC_3=1024, SARC_4=2048
|
||
|
}
|
||
|
func _ready():
|
||
|
# load_puzzle('res://slither_blank.txt')
|
||
|
load_puzzle('res://slither-202005192059.txt')
|
||
|
|
||
|
|
||
|
func draw_string_centered(font, position, string, color := Color.white):
|
||
|
draw_string(font, Vector2(position.x - font.get_string_size(string).x/2.0, position.y + font.get_ascent()), string, color)
|
||
|
|
||
|
const font := preload('res://dynamicfont.tres')
|
||
|
const COLORS = [null, Color.lightgreen, Color.lightyellow, Color.lightblue, Color.lightpink]
|
||
|
|
||
|
var h0 := 0.0
|
||
|
var v0 := 0.0
|
||
|
var h_space := 1.0
|
||
|
var v_space := 1.0
|
||
|
func update_grid_spacing() -> void:
|
||
|
h_space = rect_size.x / (h_margin * 2 + cols)
|
||
|
v_space = rect_size.y / (v_margin * 2 + rows)
|
||
|
if h_space > v_space:
|
||
|
h_space = v_space
|
||
|
else:
|
||
|
v_space = h_space
|
||
|
h0 = h_space * h_margin
|
||
|
v0 = v_space * v_margin
|
||
|
|
||
|
func grid_corner(row, col) -> Vector2:
|
||
|
return Vector2(h0+col*h_space, v0+row*v_space)
|
||
|
|
||
|
func _draw() -> void:
|
||
|
if not READY:
|
||
|
return
|
||
|
update_grid_spacing()
|
||
|
font.set_size(v_space-5)
|
||
|
|
||
|
# Colors
|
||
|
for row in rows:
|
||
|
for col in cols:
|
||
|
var color = COLORS[cell_colors.get_cell(row, col)]
|
||
|
if color != null:
|
||
|
draw_rect(Rect2(Vector2(h0+col*h_space, v0+row*v_space), Vector2(h_space, v_space)), color, true)
|
||
|
|
||
|
# Lines
|
||
|
for row in rows:
|
||
|
for col in cols:
|
||
|
if corner_marks.get_flag(row, col, CornerMark.L_RIGHT):
|
||
|
draw_line(Vector2(h0+col*h_space, v0+row*v_space), Vector2(h0+(col+1)*h_space, v0+row*v_space), Color.blue)
|
||
|
elif corner_marks.get_flag(row, col, CornerMark.X_RIGHT):
|
||
|
draw_line(Vector2(h0+(col+0.4)*h_space, v0+row*v_space), Vector2(h0+(col+0.6)*h_space, v0+row*v_space), Color.red)
|
||
|
else:
|
||
|
draw_line(Vector2(h0+col*h_space, v0+row*v_space), Vector2(h0+(col+1)*h_space, v0+row*v_space), Color.white)
|
||
|
|
||
|
if corner_marks.get_flag(row, col, CornerMark.L_DOWN):
|
||
|
draw_line(Vector2(h0+col*h_space, v0+row*v_space), Vector2(h0+col*h_space, v0+(row+1)*v_space), Color.blue)
|
||
|
elif corner_marks.get_flag(row, col, CornerMark.X_DOWN):
|
||
|
draw_line(Vector2(h0+col*h_space, v0+(row+0.4)*v_space), Vector2(h0+col*h_space, v0+(row+0.6)*v_space), Color.red)
|
||
|
else:
|
||
|
draw_line(Vector2(h0+col*h_space, v0+row*v_space), Vector2(h0+col*h_space, v0+(row+1)*v_space), Color.white)
|
||
|
for col in cols:
|
||
|
if corner_marks.get_flag(rows, col, CornerMark.L_RIGHT):
|
||
|
draw_line(Vector2(h0+col*h_space, v0+rows*v_space), Vector2(h0+(col+1)*h_space, v0+rows*v_space), Color.blue)
|
||
|
elif corner_marks.get_flag(rows, col, CornerMark.X_RIGHT):
|
||
|
draw_line(Vector2(h0+(col+0.4)*h_space, v0+rows*v_space), Vector2(h0+(col+0.6)*h_space, v0+rows*v_space), Color.red)
|
||
|
else:
|
||
|
draw_line(Vector2(h0+col*h_space, v0+rows*v_space), Vector2(h0+(col+1)*h_space, v0+rows*v_space), Color.white)
|
||
|
for row in rows:
|
||
|
if corner_marks.get_flag(row, cols, CornerMark.L_DOWN):
|
||
|
draw_line(Vector2(h0+cols*h_space, v0+row*v_space), Vector2(h0+cols*h_space, v0+(row+1)*v_space), Color.blue)
|
||
|
elif corner_marks.get_flag(row, cols, CornerMark.X_DOWN):
|
||
|
draw_line(Vector2(h0+cols*h_space, v0+(row+0.4)*v_space), Vector2(h0+cols*h_space, v0+(row+0.6)*v_space), Color.red)
|
||
|
else:
|
||
|
draw_line(Vector2(h0+cols*h_space, v0+row*v_space), Vector2(h0+cols*h_space, v0+(row+1)*v_space), Color.white)
|
||
|
|
||
|
# Numbers
|
||
|
for row in rows:
|
||
|
for col in cols:
|
||
|
var num = cell_numbers.get_cell(row, col)
|
||
|
if num < 4:
|
||
|
draw_string_centered(font, Vector2(h0+(col+0.5)*h_space, v0+row*v_space), str(num), Color.black)
|
||
|
|
||
|
# COORDS
|
||
|
for row in rows:
|
||
|
draw_string_centered(font, Vector2(h0/2, v0+row*v_space), '%02d'%row, Color.black)
|
||
|
for col in cols:
|
||
|
draw_string_centered(font, Vector2(h0+(col+0.5)*h_space, v0/4), num2alpha(col), Color.black)
|
||
|
|
||
|
func num2alpha(num: int, uppercase:=false):
|
||
|
var c = ord('A' if uppercase else 'a')
|
||
|
if num >= 26:
|
||
|
return char(c+(num/26)-1) + char(c+(num%26))
|
||
|
else:
|
||
|
return char(c+num)
|
||
|
|
||
|
func _process(delta: float) -> void:
|
||
|
update()
|
||
|
|
||
|
const num_dict := {'.': NUMBER_NONE, '0': 0, '1': 1, '2': 2, '3': 3}
|
||
|
const colornum_dict := {'0': 0, '1': 1, '2': 2}
|
||
|
func load_puzzle(filename: String):
|
||
|
var file := File.new()
|
||
|
var error = file.open(filename, File.READ)
|
||
|
if file.get_line() != 'pzprv3.1':
|
||
|
return
|
||
|
if file.get_line() != 'slither':
|
||
|
return
|
||
|
rows = int(file.get_line())
|
||
|
cols = int(file.get_line())
|
||
|
cell_numbers = ByteArray2D.new(rows, cols)
|
||
|
cell_colors = ByteArray2D.new(rows, cols)
|
||
|
corner_marks = IntArray2D.new(rows+1, cols+1, 0)
|
||
|
|
||
|
var row = 0
|
||
|
var stage = 0
|
||
|
var until = [rows, rows, rows, rows+1, 0]
|
||
|
while not file.eof_reached():
|
||
|
if row >= until[stage]:
|
||
|
stage += 1
|
||
|
row = 0
|
||
|
match stage:
|
||
|
0: # Puzzle definition numbers
|
||
|
var line = file.get_csv_line(' ')
|
||
|
var col = 0
|
||
|
for numstr in line:
|
||
|
if col < cols:
|
||
|
cell_numbers.set_cell(row, col, num_dict.get(numstr, NUMBER_NONE))
|
||
|
col += 1
|
||
|
1: # cell colors
|
||
|
var line = file.get_csv_line(' ')
|
||
|
var col = 0
|
||
|
for numstr in line:
|
||
|
if col < cols:
|
||
|
cell_colors.set_cell(row, col, colornum_dict.get(numstr, 0))
|
||
|
col += 1
|
||
|
2: # vert lines
|
||
|
var line = file.get_csv_line(' ')
|
||
|
var col = 0
|
||
|
for numstr in line:
|
||
|
if col < cols+1:
|
||
|
match int(numstr):
|
||
|
1:
|
||
|
corner_marks.set_flag(row, col, CornerMark.L_DOWN)
|
||
|
-1:
|
||
|
corner_marks.set_flag(row, col, CornerMark.X_DOWN)
|
||
|
col += 1
|
||
|
3: # hor lines
|
||
|
var line = file.get_csv_line(' ')
|
||
|
var col = 0
|
||
|
for numstr in line:
|
||
|
if col < cols+1:
|
||
|
match int(numstr):
|
||
|
1:
|
||
|
corner_marks.set_flag(row, col, CornerMark.L_RIGHT)
|
||
|
-1:
|
||
|
corner_marks.set_flag(row, col, CornerMark.X_RIGHT)
|
||
|
col += 1
|
||
|
4:
|
||
|
break
|
||
|
row += 1
|
||
|
file.close()
|
||
|
READY = true
|
||
|
|
||
|
|