Add support for custom dates and words

This commit is contained in:
Terry Hearst 2024-03-07 21:59:31 -05:00
parent a7e83622d2
commit 0a34af5d0d
3 changed files with 130 additions and 20 deletions

View file

@ -1,24 +1,34 @@
extends Node
enum GameMode {
DAILY,
RANDOM,
CUSTOM,
}
const MIN_LENGTH := 5
const MAX_LENGTH := 5
const GENERABLE_WORDS_FILENAME = "res://words/popular-filtered.txt"
const ALL_WORDS_FILENAME := "res://words/enable1.txt"
var daily_mode := true
var game_mode := GameMode.DAILY
var custom_word := ""
var custom_date_str := ""
var generable_words: Dictionary
var all_words: Dictionary
var allow_future := false
func _ready() -> void:
randomize()
generable_words = parse_words(GENERABLE_WORDS_FILENAME, MIN_LENGTH, MAX_LENGTH)
all_words = parse_words(ALL_WORDS_FILENAME, MIN_LENGTH, MAX_LENGTH)
detect_params()
func parse_words(filename: String, min_len: int, max_len: int) -> Dictionary:
var dict := {}
@ -62,6 +72,94 @@ func is_valid_word(word: String) -> bool:
return word.to_upper() in words_list
## Checks for command line/URL parameters and configures the game accordingly
func detect_params() -> void:
var daily := false
var custom := ""
if OS.has_feature("web"):
var paramsStr = JavaScriptBridge.eval("window.location.search")
var paramsObj = JavaScriptBridge.create_object("URLSearchParams", paramsStr)
if paramsObj.has("daily") and paramsObj.get("daily") not in ["false", "0"]:
daily = true
if paramsObj.has("custom"):
custom = paramsObj.get("custom")
if paramsObj.has("allowfuture") and paramsObj.get("allowfuture") not in ["false", "0"]:
allow_future = true
else:
var args := OS.get_cmdline_user_args()
if "--daily" in args:
daily = true
var custom_index := args.find("--custom")
if custom_index != -1 and custom_index < (args.size() - 1):
custom = args[custom_index + 1]
if "--allowfuture" in args:
allow_future = true
print("daily: ", daily)
print("custom: ", custom)
print("allowfuture: ", allow_future)
if daily:
game_mode = GameMode.DAILY
get_tree().change_scene_to_file.call_deferred("res://src/main.tscn")
return
if custom:
if parse_custom(custom):
game_mode = GameMode.CUSTOM
get_tree().change_scene_to_file.call_deferred("res://src/main.tscn")
return
## Checks if the given string is:
##
## * A normal five letter word, or
## * A valid encoded word, or
## * A valid date in YYYY-MM-DD encoding
## * Will only allow this date to be in the present or past, unless `allow_future` is set to true
##
## Returns true if successful, and will set `custom_word` and possibly `custom_date_str` values accordingly. Returns
## false if unsuccessful and will erase `custom_word` and `custom_date_str`.
func parse_custom(value: String) -> bool:
if value.length() == 5:
# ...is there an is_alpha function that I missed?
var word := value.to_upper()
var valid := true
for i in range(5):
var code := word.unicode_at(i)
if code < 65 or code > 90: # 65 = ascii "A", 90 = ascii "Z"
valid = false
break
if valid:
custom_word = word
return true
if value.is_valid_hex_number():
var decoded := decode_word(value.hex_to_int())
if not decoded.is_empty():
custom_word = decoded
return true
var parsed_date := Time.get_datetime_dict_from_datetime_string(value, false)
if parsed_date.has("year"):
parsed_date["hour"] = 0
parsed_date["minute"] = 0
parsed_date["second"] = 0
var new_time := Time.get_unix_time_from_datetime_dict(parsed_date)
var valid := true
if not allow_future:
var current_time := Time.get_unix_time_from_datetime_string(Time.get_date_string_from_system(true))
if new_time > current_time:
valid = false
if valid:
custom_word = generate_word(5, new_time)
custom_date_str = Time.get_date_string_from_unix_time(new_time)
return true
return false
func _notification(what: int) -> void:
if what == NOTIFICATION_WM_CLOSE_REQUEST:
get_tree().quit()
@ -119,7 +217,7 @@ func decode_word(encoded_word: int) -> String:
num -= 123456
if num < 0 or num >= (26 ** 5): # (26 ** 5) - 1 = "zzzzz"
if num < 0 or num >= (26 ** 5): # (26 ** 5) - 1 = "ZZZZZ"
# Someone is trying to be sneaky! Or more likely I just messed up.
return ""

View file

@ -46,27 +46,39 @@ func _ready() -> void:
letter_grid.add_child(letter)
letters.append(letter_array)
var random_seed = null
if Global.daily_mode:
var current_time := Time.get_datetime_dict_from_system(true)
current_time["hour"] = 0
current_time["minute"] = 0
current_time["second"] = 0
random_seed = Time.get_unix_time_from_datetime_dict(current_time)
title.text = "Daily " + title.text
subtitle.text = "%d-%02d-%02d" % [current_time["year"], current_time["month"], current_time["day"]]
if Global.game_mode != Global.GameMode.CUSTOM:
Global.custom_word = ""
Global.custom_date_str = ""
if not Global.custom_word.is_empty():
target_word = Global.custom_word
title.text = "Custom " + title.text
if Global.custom_date_str:
subtitle.text = Global.custom_date_str
else:
subtitle.text = String.num_int64(Global.encode_word(target_word), 16)
else:
title.text = "Random " + title.text
var random_seed = null
if Global.game_mode == Global.GameMode.DAILY:
var current_time := Time.get_date_string_from_system(true)
random_seed = Time.get_unix_time_from_datetime_string(current_time)
title.text = "Daily " + title.text
subtitle.text = current_time
elif Global.game_mode == Global.GameMode.RANDOM:
title.text = "Random " + title.text
target_word = Global.generate_word(letter_count, random_seed)
if Global.game_mode != Global.GameMode.DAILY:
subtitle.text = String.num_int64(Global.encode_word(target_word), 16)
target_word = Global.generate_word(letter_count, random_seed)
current_guess = 0
ended = false
won = false
if not Global.daily_mode:
subtitle.text = String.num_int64(Global.encode_word(target_word), 16)
for i in range(0, 26):
var letter := char("A".unicode_at(0) + i)
var keyboard_button: Button = keyboard_vbox.find_child("Button" + letter)

View file

@ -11,13 +11,13 @@ func _ready() -> void:
func _on_DailyButton_pressed() -> void:
Global.daily_mode = true
Global.game_mode = Global.GameMode.DAILY
var error := get_tree().change_scene_to_file("res://src/main.tscn")
assert(not error)
func _on_RandomButton_pressed() -> void:
Global.daily_mode = false
Global.game_mode = Global.GameMode.RANDOM
var error := get_tree().change_scene_to_file("res://src/main.tscn")
assert(not error)