Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- extends Node2D
- var ticks = 0
- var groups = []
- var crafters = []
- var crafter_recipies = []
- var crafter_rects = []
- const directions = {
- [false, false]:Vector2(1,0),
- [true, true]:Vector2(0,1),
- [true, false]:Vector2(-1,0),
- [false, true]:Vector2(0,-1)
- }
- const block_types = {
- "fist":0,
- "otherfist":3,
- "joiner":1,
- "block":4,
- "spawner":2,
- "arm":5,
- "crafter":6,
- "bin":8
- }
- const recipies = {
- [[-2, 4, -2],
- [4, 4, 4],
- [-2, 4, -2],]:[[-2,-1,-2],
- [-1,7,-1],
- [-2,-1,-2]],
- [[4, 4, 4],
- [4, -2, 4],
- [4, 4, 4],]:[[-1,-1,-1],
- [-1,-2,-1],
- [-1,7,-1]],
- [[4, 4, 4],
- [4, 4, 4],
- [4, 4, 4],]:[[-1,-1,-1],
- [-1,7,-1],
- [-1,-1,-1]]
- }
- func flood_fill(pos, cells, list):
- var index = cells.find(pos)
- if index != -1:
- list.append(pos)
- cells.remove(index)
- flood_fill(pos + Vector2(1,0), cells, list)
- flood_fill(pos + Vector2(-1,0), cells, list)
- flood_fill(pos + Vector2(0,1), cells, list)
- flood_fill(pos + Vector2(0,-1), cells, list)
- func find_crafters():
- var crafter_cells = $machine.get_used_cells_by_id(block_types["crafter"])
- while not crafter_cells.empty():
- var crafter = []
- flood_fill(crafter_cells[0], crafter_cells, crafter)
- crafters.append(crafter)
- crafter_recipies.append(null)
- func min_vec(list):
- var min_vec = Vector2(9999,9999)
- for vec in list:
- min_vec.x = min(min_vec.x, vec.x)
- min_vec.y = min(min_vec.y, vec.y)
- return min_vec
- func max_vec(list):
- var max_vec = Vector2(-9999,-9999)
- for vec in list:
- max_vec.x = max(max_vec.x, vec.x)
- max_vec.y = max(max_vec.y, vec.y)
- return max_vec
- func find_recipies():
- for index in crafters.size():
- var crafter = crafters[index]
- var start = min_vec(crafter)
- var rect = Rect2(start, max_vec(crafter)-start+Vector2(1,1))
- crafter_rects.append(rect)
- for recipie in recipies:
- var broken = false
- if recipie.size() == rect.size.y and recipie[0].size() == rect.size.x:
- for x in rect.size.x:
- for y in rect.size.y:
- var in_crafter = recipie[y][x] != -2
- if (Vector2(x,y)+rect.position in crafter) != in_crafter:
- broken = true
- break
- if broken:
- break
- if not broken:
- crafter_recipies[index] = recipie#they store copy of recipie insted of index
- break
- func scan_colours():
- for index in range(64):
- var group = $colours.get_used_cells_by_id(index)
- if !group.empty():
- groups.append(group)
- for pos in group:
- $blocks.set_cellv(pos, block_types["block"])
- $visible_blocks.set_cellv(pos, block_types["block"])
- func do_debug():
- $colours.clear()
- for index in groups.size():
- for pos in groups[index]:
- $colours.set_cellv(pos, index%64)
- func _ready():
- scan_colours()
- find_crafters()
- find_recipies()
- func _process(_delta):
- if Input.is_action_just_pressed("ui_right"):
- tick()
- #print(Engine.get_frames_per_second())
- func tick():
- ticks+=1
- for pos in $machine.get_used_cells():
- var state = $machine.get_cellv(pos)
- var direction = get_direction(pos)
- if ticks % 2 == 0:
- if state == block_types["fist"]:
- var cell = $blocks.get_cellv(pos+direction)
- if cell != -1:
- move(pos+direction, direction)
- else:
- if state == block_types["spawner"] and $blocks.get_cellv(pos) == -1:
- $blocks.set_cellv(pos, block_types["block"])
- elif state == block_types["otherfist"]:
- var cell = $blocks.get_cellv(pos+direction)
- if cell != -1:
- move(pos+direction, direction)
- for pos in $machine.get_used_cells():
- var state = $machine.get_cellv(pos)
- var direction = get_direction(pos)
- if state == block_types["joiner"] and $machine.is_cell_x_flipped(pos.x, pos.y):
- join(pos, direction)
- for pos in $machine.get_used_cells():
- var state = $machine.get_cellv(pos)
- var direction = get_direction(pos)
- if ticks % 2 == 0:
- pass
- else:
- if state == block_types["arm"]:
- do_arm(pos, direction)
- for pos in $machine.get_used_cells():
- var state = $machine.get_cellv(pos)
- var direction = get_direction(pos)
- if state == block_types["joiner"] and $machine.is_cell_x_flipped(pos.x, pos.y):
- join(pos, direction)
- elif state == block_types["bin"]:
- var index = find_nested_index(pos, groups)
- if index != -1:
- for group_pos in groups[index]:
- $blocks.set_cellv(group_pos, -1)
- groups.remove(index)
- else:
- $blocks.set_cellv(pos, -1)
- for crafter_index in crafters.size():
- var crafter = crafters[crafter_index]
- var index = find_nested_index(crafter[0], groups)
- if index != -1:
- var recipie = crafter_recipies[crafter_index]
- if recipie!=null:
- var broken = false
- for pos in crafter:
- var recipie_pos = pos-crafter_rects[crafter_index].position
- if not recipie[recipie_pos.y][recipie_pos.x] == $blocks.get_cellv(pos):
- broken = true
- break
- if not pos in groups[index]:
- broken = true
- break
- if broken:
- continue
- groups.remove(index)
- for pos in crafter:
- var recipie_pos = pos-crafter_rects[crafter_index].position
- var item = recipies[recipie][recipie_pos.y][recipie_pos.x]
- if item != -2:
- $blocks.set_cellv(pos, item)#can do without dict if i store index of recipe:output pair
- do_debug()
- func do_arm(arm_pos, direction):
- var start_index = find_nested_index(arm_pos-direction, groups)
- var end_index = find_nested_index(arm_pos+direction, groups)
- var start_group = []
- if start_index!=-1:
- start_group = groups[start_index].duplicate(true)
- var end_group = []
- if end_index!=-1:
- end_group = groups[end_index].duplicate(true)
- var moves = []
- for index in start_group.size():
- var pos = start_group[index]
- var startpos = pos
- pos-=arm_pos
- pos=-pos
- pos+=arm_pos
- if $blocks.get_cellv(pos)!=-1:
- return false
- start_group[index]=pos
- moves.append([startpos, pos])
- for index in end_group.size():
- var pos = end_group[index]
- var startpos = pos
- pos-=arm_pos
- pos=-pos
- pos+=arm_pos
- if $blocks.get_cellv(pos)!=-1:
- return false
- end_group[index]=pos
- moves.append([startpos, pos])
- if start_index==-1 and end_index==-1:#individual blocks
- if $blocks.get_cellv(arm_pos-direction)!=-1:
- moves.append([arm_pos-direction, arm_pos+direction])
- elif $blocks.get_cellv(arm_pos+direction)!=-1:
- moves.append([arm_pos+direction, arm_pos-direction])
- for move in moves:
- if start_index!=-1:
- groups[start_index]=start_group
- if end_index!=-1:
- groups[end_index]=end_group
- var cell = $blocks.get_cellv(move[0])
- $blocks.set_cellv(move[0], -1)
- $blocks.set_cellv(move[1], cell)
- func join(pos, direction):
- var other_pos = pos+direction
- if $blocks.get_cellv(pos) != -1 and $blocks.get_cellv(other_pos) != -1:#ugly solution to adding to existing group
- var found = [find_nested(pos, groups), find_nested(other_pos, groups)]
- if not (found[0].empty() and found[1].empty()):
- if found[0].empty():
- if not pos in found[1]:
- found[1].append(pos)
- elif found[1].empty():
- if not other_pos in found[0]:
- found[0].append(other_pos)
- elif found[0]!=found[1]:
- groups.erase(found[0])
- var index = find_nested_index(other_pos, groups)#index of one i didnt remove
- groups[index]+=found[0]
- else:
- groups.append([pos,other_pos])
- func get_direction(pos):
- return directions[[$machine.is_cell_x_flipped(pos.x, pos.y), $machine.is_cell_transposed(pos.x, pos.y)]]
- func move(pos, direction):
- var done_groups = []
- var tiles = []
- if push_wrapper(pos, direction, tiles, done_groups):
- var states = []
- for tile in tiles:
- states.append($blocks.get_cellv(tile))
- $blocks.set_cellv(tile, -1)
- for index in tiles.size():
- $blocks.set_cellv(tiles[index]+direction, states[index])
- func push_wrapper(pos, direction, tiles, done_groups):
- var group = find_nested(pos, groups)
- if !group.empty() and not group in done_groups:
- done_groups.append(group)
- for pos in group:
- if not pos+direction in group:
- if not push(pos, direction, tiles, done_groups):
- return false
- for pos in group:#lazy fix for all the tiles that arent on the outward face(right face to move right etc)
- if pos+direction in group:
- tiles.append(pos)
- for index in group.size():
- group[index]+=direction
- return true
- else:
- return push(pos, direction, tiles, done_groups)
- func push(pos, direction, tiles, done_groups):
- var newpos = pos+direction
- var check = $blocks.get_cellv(newpos)
- if check==1:#if its check is in a wall
- return false
- else:
- if not pos in tiles:
- tiles.append(pos)
- if check==-1:#if its check is air
- return true
- else:#otherwise move the checked tile
- return push_wrapper(newpos, direction, tiles, done_groups)
- func find_nested(item, list):
- for sublist in list:
- if item in sublist:
- return sublist
- return []
- func find_nested_index(item, list):
- for index in list.size():
- if item in list[index]:
- return index
- return -1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement