Rock the UI Away - Removes VueUI and adds TGUI (#16509)

* tgui the beginning

* binaries and the like

* Bring in the last of it

* Example radio UI

* delete example

* NTOS Main Menu, start on manifest, tgui states

* tasks.json

* gunnery ui pt 1

* okay

* fix everything

* scss update

* oops

* manifest gigablast

* downloader part 1

* download prt 2

* NTOSDownloader final

* mfw committing to_worlds

* gunnery console pt2

* i cooked

* targeting (finished)

* one vueui down

* voting ui almost done

* MY MIND FEELS LIKE AN ARCH ENEMYYYY

* voting ui down

* photocopier

* ntos config + download fixes

* photocopier 2

* refactor define

* NTOS client manager + fixes

* fax machine final (it also uses toner now)

* marching forwards... left behind...

* ntnrc part 1

* canister

* add quotes

* portable pumps pt1 + more backgrounds

* oops

* finish the portable pump

* freezers

so I'll keep on pushing forward... you haven't seen the last of me... oooooooh...

* doors ui pt1

* finish doors UI (forgive me wildkins it's a bit of shitcode)

* vitals monitor, make things use labeled lists, new backgrounds

* mais j'envoyé aucun mayday...

* maglock pt1

* pour ça je me suis perdu...

* infrared

* fix that

* prox sensor pt1

* prox sensor

* signaler (this was actually pretty hard)

* atmos control pt1

* atmos control pt1.1

* atmos pt 2

* fuel injector

* multitool UI

* jammer

* list viewer

* APC

* portgen

* targeting console updates + SMES ui

* new themes, shield generator

* supermatter

* Add ore detector and (shitty) NTNet Relay

* orderterminal pt1

* orderterminal pt2

* smartfridge

* Add (air-)tank GUI update ore detector size

* Adds Transfer Valves

* Add AtmoScrubber

* analyzer pt1

* weapons analyzer pt2

* bodyscanner pt1

* bodyscanner pt2

* fix this shitcode

* seed storage

* appearance changer

* appearance changer final

* sleeper pt1

* sleeper

* gps

* vehicles

* chem dispenser

* lily request

* holopad

* tgui modules pt1

* ppanel

* damage menu

* fixes

* im here too now

* follow menu, search bars

* quikpay

* quikpay fixes

* circuit printer

* ppanel

* ppanel updates

* pai

* turret controls (i want to kill myself)

* tweak

* remove the boardgame

* guntracker

* implant tracker

* penal mechs

come close to me, come close to me

* chem codex

* pai radio

* doorjack

* pai directives

* signaler removal, sensors

* ghost spawner

* spawnpoint

* fixes

* teleporter

* one more to the chopping block

* account database

* remove divider

* scanner, atmos

* latejoin ui pt1

* latejoin

* records pt1

* RECORDS UI DONE

* delete interpreter & records

* CHAT FUCKING CLIENT

* data updates

* fix some things

* final UI, log

* basic nanoui fix

* antag panel

* remove vueui

* atm update

* vending update

* warrants, cameras

* ntmonitor

* time comes for all

* preserve this legacy

* bring that back (oops)

* rcon, ui auto update for computer UIs, remove rcon computers

* alarm monitoring (a bit broke and also todo: add custom alarm monitoring programs to a few consoles)

* A LIKE SUPREME

* a

* power monitor

* lights on

* fuck this code, fuck nanoui modules, and fuck nanoui

* LEAVE IT OH SO FAR BEHIND

* fix alarm monitoring for synths

* I SAW IN YOU WHAT LIFE WAS MISSING

* comms console

* idcard and record updates

* turn the light on

* arcade

* pt2

* news browser

* static

* crusher

* f

* COULD I JUST SLEIGH THE GOLD FROM THE BALLS? I'M SO FRUSTRATED OH COULD YOU TELL? IF I HEAR ONE MORE VUEUI OR ONE NANOUI I'M GONNA LOSE IT SO LET ME GOOOOOOOOOOOOOOOOO

* codeowners & suit sensors

* html ui style removal

* make lint happy

* resist and disorder

* i slowly get up and turn off the noise, already fed up...

* pleaseeeeeeeeeeeeeee

* THE CREDIT LARP IS NECESSARY

* i hold the keys

* RISE UP

* fix that?

* harry's suggestions xoxo

* runtime fix pt2

* You are the only thing that I still care about

* adds build workflow

* Update update_tgui.yml

* adds some needed steps

* ATM

* misc fixes and tweaks

* fixes 2

* make newscasters usable and fix use power on freezers

* turret control is clearer

---------

Co-authored-by: John Wildkins <john.wildkins@gmail.com>
Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: harryob <55142896+harryob@users.noreply.github.com>
Co-authored-by: Werner <Arrow768@users.noreply.github.com>
Co-authored-by: Geeves <ggrobler447@gmail.com>
Co-authored-by: harryob <me@harryob.live>
This commit is contained in:
Matt Atlas
2023-06-25 19:03:33 +02:00
committed by GitHub
co-authored by John Wildkins Matt Atlas harryob Werner Geeves harryob
parent 4ce7ba118b
commit 31956c7eb0
1117 changed files with 80951 additions and 44002 deletions
@@ -1,7 +1,3 @@
// This file is used as a reference for Modular Computers Development guide on the wiki. It contains a lot of excess comments, as it is intended as explanation
// for someone who may not be as experienced in coding. When making changes, please try to keep it this way.
// An actual program definition.
/datum/computer_file/program/game/arcade
filename = "arcadec" // File name, as shown in the file browser program.
filedesc = "Unknown Game" // User-Friendly name. In this case, we will generate a random name in constructor.
@@ -11,10 +7,17 @@
size = 2 // Size in GQ. Integers only. Smaller sizes should be used for utility/low use programs (like this one), while large sizes are for important programs.
requires_ntnet = FALSE // This particular program does not require NTNet network conectivity...
available_on_ntnet = TRUE // ... but we want it to be available for download.
nanomodule_path = /datum/nano_module/arcade_classic // Path of relevant nano module. The nano module is defined further in the file.
var/picked_enemy_name
color = LIGHT_COLOR_BLUE
usage_flags = PROGRAM_ALL_REGULAR
tgui_id = "NTOSArcade"
var/picked_enemy_name
var/player_mana
var/player_health
var/enemy_mana
var/enemy_health
var/enemy_name = "Greytide Horde"
var/gameover
var/information
// Blatantly stolen and shortened version from arcade machines. Generates a random enemy name
/datum/computer_file/program/game/arcade/proc/random_enemy_name()
@@ -27,6 +30,7 @@
..()
picked_enemy_name = random_enemy_name()
filedesc = "[pick("Defeat", "Destroy", "Decimate", "Decapitate")] [picked_enemy_name]"
new_game()
// Important in order to ensure that copied versions will have the same enemy name.
/datum/computer_file/program/game/arcade/clone()
@@ -34,35 +38,8 @@
G.picked_enemy_name = picked_enemy_name
return G
// When running the program, we also want to pass our enemy name to the nano module.
/datum/computer_file/program/game/arcade/run_program()
. = ..()
if(. && NM)
var/datum/nano_module/arcade_classic/NMC = NM
NMC.enemy_name = picked_enemy_name
// Nano module the program uses.
// This can be either /datum/nano_module/ or /datum/nano_module/program. The latter is intended for nano modules that are suposed to be exclusively used with modular computers,
// and should generally not be used, as such nano modules are hard to use on other places.
/datum/nano_module/arcade_classic
name = "Classic Arcade"
var/player_mana // Various variables specific to the nano module. In this case, the nano module is a simple arcade game, so the variables store health and other stats.
var/player_health
var/enemy_mana
var/enemy_health
var/enemy_name = "Greytide Horde"
var/gameover
var/information
/datum/nano_module/arcade_classic/New()
..()
new_game()
// ui_interact handles transfer of data to NanoUI. Keep in mind that data you pass from here is actually sent to the client. In other words, don't send anything you don't want a client
// to see, and don't send unnecessarily large amounts of data (due to laginess).
/datum/nano_module/arcade_classic/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
/datum/computer_file/program/game/arcade/ui_data(mob/user)
var/list/data = initial_data()
data["player_health"] = player_health
data["player_mana"] = player_mana
@@ -72,32 +49,25 @@
data["gameover"] = gameover
data["information"] = information
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "arcade_classic.tmpl", "Defeat [enemy_name]", 500, 350, state = state)
if(host.update_layout())
ui.auto_update_layout = TRUE
ui.set_initial_data(data)
ui.open()
return data
// Three helper procs i've created. These are unique to this particular nano module. If you are creating your own nano module, you'll most likely create similar procs too.
/datum/nano_module/arcade_classic/proc/enemy_play()
/datum/computer_file/program/game/arcade/proc/enemy_play()
if((enemy_mana < 5) && prob(60))
var/steal = rand(2, 3)
player_mana -= steal
enemy_mana += steal
information += "[enemy_name] steals [steal] of your power!"
information += " [enemy_name] steals [steal] of your power!"
else if((enemy_health < 15) && (enemy_mana > 3) && prob(80))
var/healamt = min(rand(3, 5), enemy_mana)
enemy_mana -= healamt
enemy_health += healamt
information += "[enemy_name] heals for [healamt] health!"
information += " [enemy_name] heals for [healamt] health!"
else
var/dam = rand(3, 6)
player_health -= dam
information += "[enemy_name] attacks for [dam] damage!"
information += " [enemy_name] attacks for [dam] damage!"
/datum/nano_module/arcade_classic/proc/check_gameover()
/datum/computer_file/program/game/arcade/proc/check_gameover()
if((player_health <= 0) || player_mana <= 0)
if(enemy_health <= 0)
information += "You have defeated [enemy_name], but you have died in the fight!"
@@ -111,7 +81,7 @@
return TRUE
return FALSE
/datum/nano_module/arcade_classic/proc/new_game()
/datum/computer_file/program/game/arcade/proc/new_game()
player_mana = 10
player_health = 30
enemy_mana = 20
@@ -119,34 +89,35 @@
gameover = FALSE
information = "A new game has started!"
/datum/nano_module/arcade_classic/Topic(href, href_list)
if(..()) // Always begin your Topic() calls with a parent call!
return TRUE
if(href_list["new_game"])
/datum/computer_file/program/game/arcade/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
if(..())
return
if(action == "new_game")
new_game()
return TRUE // Returning 1 (TRUE) in Topic automatically handles UI updates.
if(gameover) // If the game has already ended, we don't want the following three topic calls to be processed at all.
return TRUE // Instead of adding checks into each of those three, we can easily add this one check here to reduce on code copy-paste.
if(href_list["attack"])
var/damage = rand(2, 6)
information = "You attack for [damage] damage."
enemy_health -= damage
enemy_play()
check_gameover()
return TRUE
if(href_list["heal"])
var/healfor = rand(6, 8)
var/cost = rand(1, 3)
information = "You heal yourself for [healfor] damage, using [cost] energy in the process."
player_health += healfor
player_mana -= cost
enemy_play()
check_gameover()
return TRUE
if(href_list["regain_mana"])
var/regen = rand(4, 7)
information = "You rest for a while, regaining [regen] energy."
player_mana += regen
enemy_play()
check_gameover()
return TRUE
return
if(gameover)
return
switch(action)
if("attack")
var/damage = rand(2, 6)
information = "You attack for [damage] damage."
enemy_health -= damage
enemy_play()
check_gameover()
return TRUE
if("heal")
var/healfor = rand(6, 8)
var/cost = rand(1, 3)
information = "You heal yourself for [healfor] damage, using [cost] energy in the process."
player_health += healfor
player_mana -= cost
enemy_play()
check_gameover()
return TRUE
if("regain_mana")
var/regen = rand(4, 7)
information = "You rest for a while, regaining [regen] energy."
player_mana += regen
enemy_play()
check_gameover()
return TRUE
@@ -1,245 +0,0 @@
//This proc checks the validity of the current boardstate
//It will analyse all the tiles in sequence, and halt if it finds an invalid one.
//Tiles will be checked for conflicts along the row, border and 3x3 box
/datum/nano_module/program/sudoku/proc/check_validity()
//This result will be returned at the end
. = 0
//Return var of 0 is normal, that means the game is unfinished and the boardstate is valid
//Any return var > zero indicates invalid, with that number being the index of the first invalid tile
//Return var of -1 indicates all tiles filled and boardstate valid. IE: Game over, you win!
var/empty = 0
var/conflict = 0
for (var/t in grid)
var/list/tile = t
if (tile["static"])
continue
var/v = tile["value"]
var/i = tile["index"]
if (!v)
empty++
continue
var/list/group
group = get_row(i)
for (var/n in group)
if(n == v)//CONFLICT
conflict = i
break
group = get_column(i)
for (var/n in group)
if(n == v)//CONFLICT
conflict = i
break
group = get_box(i)
for (var/n in group)
if(n == v)//CONFLICT
conflict = i
break
if (conflict)
break
if (conflict)
message = "Error: Invalid tile found! The problem is highlighted"
highlight(list(conflict))
.=conflict
else if (empty > 0)
message = "Everything looks fine so far! You have [empty] tiles left to fill"
highlight()
//If we havent found any conflict and all tiles are filled, then the user has won the game.
else if (empty == 0)
message = "Congratulations! You win the game!"
if (!won_game)
playsound(get_turf(program.computer), 'sound/magic/light.ogg', 50, 1)
won_game = 1
.=-1
//Attempts to solve the board using simple single-tile logic. This will solvve most easier boards
//May implement split timelines for solving boards where the answer isnt simple
//Number of steps indicates how many tiles to solve. Passing 1 can serve as a hint function
/datum/nano_module/program/sudoku/proc/solver(var/steps = 81)
if (check_validity() != 0) //Can't build on quicksand. The boardstate must be valid before we attempt to progress
return
var/done = 0
var/list/emptytiles = list()
for (var/t in grid)
var/list/tile = t
var/v = tile["value"]
if (v)//Already has a valid value, next tile
continue
emptytiles += text2num(tile["index"])
if(emptytiles.len)
while (steps > 0 && !done)
if (emptytiles.len <= 0 )
done = 1//If we get here then the solver has won the game.
var/i = pick_n_take(emptytiles)
var/list/tile = grid[i]
tile["value"] = solution[i]//Solution is the pre-saved correct solution for the puzzle
tile["static"] = 1
steps--
cheated++//Cheated var indicates the user had help
message = "A tile has been revealed for you. You've now had [cheated] hints"
highlight(list(i))
//Returns all possible values for a tile
//If this ever returns nothing then the game is in an unwinnable state, a mistake has been made
/datum/nano_module/program/sudoku/proc/get_options(var/index)
. = list(1,2,3,4,5,6,7,8,9)
. -= get_row(index)
. -= get_column(index)
. -= get_box(index)
//Returns all tiles in the same row as index, excluding index
/datum/nano_module/program/sudoku/proc/get_row(var/index)
var/list/tile = grid[index]
//We get the row number from this
var/rowstart = (((tile["row"]-1)*9) + 1)//Index of the first tile on the row we want
var/i
var/list/indices = list()
for (i = 0, i <= 8, i++)
indices += rowstart+i
indices -= index
return get_tile_values(indices)
//Returns all tiles in the same row as index, excluding index
/datum/nano_module/program/sudoku/proc/get_column(var/index)
var/list/tile = grid[index]
//We get the row number from this
var/columnstart = tile["column"]//Index of the first tile on the row we want
var/i
var/list/indices = list()
for (i = 0, i <= 8, i++)
indices += columnstart+(i*9)
indices -= index
return get_tile_values(indices)
/datum/nano_module/program/sudoku/proc/get_box(var/index)
var/list/tile = grid[index]
var/list/temp = boxes[tile["box"]]
var/list/boxind = temp.Copy()
boxind -= index
return get_tile_values(boxind)
//Takes a list of indexes, returns the grid tiles with those indexes.
/datum/nano_module/program/sudoku/proc/get_tiles(var/list/indexes)
. = list()
for (var/i in indexes)
. += list(grid[i])
/datum/nano_module/program/sudoku/proc/get_tile_values(var/list/indexes)
. = list()
for (var/i in indexes)
var/list/tile = grid[i]
. += tile["value"]
//A not so simple grid builder which uses a backtracking algorithm.
//Attempts to build the grid linearly with random numbers, backtracking and trying again whenever a
//collision is found
/datum/nano_module/program/sudoku/proc/advanced_populate_grid(var/clues = 36)
set background = 1
if (building)
return
building = 1
clear_grid(1)
var/iterations = 0
var/i = 1
for (i = 1, i <= 81, i++)
var/list/tile = grid[i]
iterations++
var/list/tried = tile["tried"]
var/list/options = get_options(i)
options.Remove(tried)//The list of tried numbers is used when we backtrack
//So long as we have any options left, we'll pick a random one and keep going
if (options.len > 0)
tile["value"] = pick(options)
tile["static"] = 1
else
//If there are no valid, non-colliding numbers for this tile, then things get interesting.
var/list/prev = grid[i-1]//Get the previous tile
var/list/t = prev["tried"]
t += prev["value"]//The value for the previous tile is now blacklisted
prev["value"] = ""
//grid[i-1] = prev
//Now we wipe our own tried list since we're stepping back. How we've branched forward
//from this point is no longer relevant
tile["tried"] = list()
//And finally we set i back two decrements, so in the next cycle of the loop
//it will look at the previous cell
i -= 2
if (iterations == 100)
iterations = 0
sleep(1)
//Now we copy over the solution
solution = list()
for (var/t in grid)
var/list/tile = t
solution += tile["value"]
//And finally we start removing stuff until we have only the clues left
var/toremove = 81 - clues
var/list/filledtiles = list()
for (i = 1, i <= 81, i++)
filledtiles += i
while (toremove > 0)
i = pick_n_take(filledtiles)
toremove--
var/list/tile = grid[i]
tile["value"] = ""
tile["static"] = 0
tile["tried"] = list()//to prevent any cheating
building = 0
//Highlights all indices in the list. Unhighlights every other cell
/datum/nano_module/program/sudoku/proc/highlight(var/list/indices)
if (!indices)
indices = list()
for (var/i = 1, i <= 81, i++)
var/list/tile = grid[i]
if (indices.len && (i in indices))
tile["highlight"] = 1
else
tile["highlight"] = 0
@@ -1,211 +0,0 @@
/datum/computer_file/program/game/sudoku
filename = "sudoku" // File name, as shown in the file browser program.
filedesc = "Sudoku" // User-Friendly name. In this case, we will generate a random name in constructor.
program_icon_state = "sudoku" // Icon state of this program's screen.
program_key_icon_state = "black_key"
extended_desc = "A game of numbers, logic, and deduction. Popular for centuries to keep the mind sharp." // A nice description.
size = 2 // Size in GQ. Integers only. Smaller sizes should be used for utility/low use programs (like this one), while large sizes are for important programs.
requires_ntnet = FALSE // This particular program does not require NTNet network conectivity...
available_on_ntnet = TRUE // ... but we want it to be available for download.
nanomodule_path = /datum/nano_module/program/sudoku // Path of relevant nano module. The nano module is defined further in the file.
usage_flags = PROGRAM_ALL_REGULAR
/datum/nano_module/program/sudoku
var/list/grid = null
var/building = FALSE
var/list/solution = list()
var/cheated = FALSE
var/list/boxes = list(//Most efficient way i could think to do this
"11" = list(1,2,3,10,11,12,19,20,21),
"12" = list(4,5,6,13,14,15,22,23,24),
"13" = list(7,8,9,16,17,18,25,26,27),
"21" = list(28,29,30,37,38,39,46,47,48),
"22" = list(31,32,33,40,41,42,49,50,51),
"23" = list(34,35,36,43,44,45,52,53,54),
"31" = list(55,56,57,64,65,66,73,74,75),
"32" = list(58,59,60,67,68,69,76,77,78),
"33" = list(61,62,63,70,71,72,79,80,81)
)
var/message = ""//Error or informational message shown on screen.
var/last_message = ""
var/message_sent = FALSE
var/list/clues = list("Easy" = 36, "Medium" = 31,"Hard" = 26,"Robust" = 17)
var/last_user
var/won_game = FALSE
var/datum/computer_file/program/game/sudoku
var/new_difficulty = "Easy" //The selected difficulty mode for generating the next grid
var/collapse = FALSE
var/width = 900
/datum/nano_module/program/sudoku/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = FALSE, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
if (!grid)
create_grid()
data["grid"] = grid
data["src"] = "\ref[src]"
data["collapse"] = collapse
data["message"] = message
data["difficulty"] = new_difficulty
if (message != last_message)
last_message = message
message_sent = world.time
else if ((world.time - message_sent) > 100)//Make sure that messages show onscreen for at least 10 seconds
message = ""//Displays for one refresh only
last_user = user
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "sudoku.tmpl", "Sudoku", width, 557, state = state)
//if(host.update_layout()) // This is necessary to ensure the status bar remains updated along with rest of the UI.
ui.auto_update_layout = TRUE
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(FALSE)
/datum/nano_module/program/sudoku/Topic(var/href, var/list/href_list)
..()
if(href_list["save"])//This is called with every keypress
save_grid(href_list)
return//No refreshing for every input
else if(href_list["check"])
save_grid(href_list)
check_validity()
else if(href_list["hint"])//Reveals one tile
var/response = alert(usr, "Are you sure you want a hint? This will reveal the correct number for one tile. But you'll lose the pride of having figured it out yourself...", "Ask for a hint", "Help me.", "I can do it myself.")
if(response == "Help me.")
solver(1)
else
return
else if(href_list["solve"])
solver(81)
else if(href_list["clear"])
var/response = alert(usr, "Are you sure you want to clear the grid? This will remove all the numbers you've typed in. The starting clues will remain.", "Clear board", "Clear it.", "Wait no!")
if(response == "Clear it.")
clear_grid(FALSE)
else
return
else if(href_list["purge"])
clear_grid(TRUE)
else if(href_list["difficulty"])
new_difficulty = href_list["difficulty"]
else if(href_list["newgame"])
var/response = alert(usr, "Are you sure you want to start a new game? All progress on this one will be lost. Be sure to pick your desired difficulty first.", "New Puzzle", "Start Anew.", "Wait no!")
if(response == "Start Anew.")
advanced_populate_grid(clues[new_difficulty])
else
return
else if(href_list["collapse"])
collapse = !collapse
set_width(usr)
return
if(usr)
ui_interact(usr)
/datum/nano_module/program/sudoku/proc/set_width(var/mob/user)
if(collapse)
width = 400
else
width = 900
var/datum/nanoui/ui = SSnanoui.get_open_ui(user, src, "main")
if(ui)
ui.close()
ui_interact(user, force_open = TRUE)
/datum/nano_module/program/sudoku/proc/save_grid(var/list/inputdata)
var/i = 1
for(i = 1, i <= 81, i++)
var/list/cell = grid[i]
var/v = text2num(inputdata["[i]"])
if(inputdata["[i]"] == "" || (v > 0 && v < 10))
cell["value"] = inputdata["[i]"]
/datum/nano_module/program/sudoku/proc/create_grid()
if(grid)
grid.Cut()
grid = list()
var/n = 81
var/list/numbers = list()
while (n)
n--
numbers += rand(1,9)
var/row = 1
var/column = 0
n = 1//reuse this
for (var/a in numbers)
var/list/number = list()
number["value"] = ""
//if (prob(20))
//number["static"] = 1
column++
if (column > 9)
row++
column = 1
number["id"] = "[row][column]"
number["row"] = row
number["column"] = column
number["index"] = n
number["tried"] = list()//used in grid generation
n++
grid.Add(list(number))
var/box = ""
switch (row)
if (1 to 3)
box += "1"
if (4 to 6)
box += "2"
if (7 to 9)
box += "3"
switch (column)
if (1 to 3)
box += "1"
if (4 to 6)
box += "2"
if (7 to 9)
box += "3"
number["box"] = box
advanced_populate_grid()
/datum/nano_module/program/sudoku/proc/id_num(var/index)
var/row = 1
var/column = 1
if(index <= 9)
column = index
else
while(index > 9)
index -= 9
row++
column = index
return "[row][column]"
//Clears the grid:
//With an input of 0, clears all user input and restores the grid to just the generated clues
//With input of 1, clears every cell, grid becomes empty
/datum/nano_module/program/sudoku/proc/clear_grid(var/full = 0)
for (var/t in grid)
var/list/tile = t
if (full || !tile["static"])
tile["value"] = ""
tile["static"] = 0
tile["highlight"] = 0
if(full)
cheated = FALSE
won_game = FALSE