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