Change custom word format and allow different length words
This commit is contained in:
parent
66df0a9b44
commit
cde8565f5d
3 changed files with 53 additions and 51 deletions
|
@ -136,14 +136,14 @@ layout_mode = 2
|
||||||
|
|
||||||
[node name="WordLabel" type="Label" parent="C/V/Help/Options"]
|
[node name="WordLabel" type="Label" parent="C/V/Help/Options"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "A five letter word, e.g. \"APPLE\""
|
text = "A 3-8 letter word, e.g. \"APPLE\""
|
||||||
label_settings = SubResource("LabelSettings_6at68")
|
label_settings = SubResource("LabelSettings_6at68")
|
||||||
horizontal_alignment = 1
|
horizontal_alignment = 1
|
||||||
|
|
||||||
[node name="CodeLabel" type="Label" parent="C/V/Help/Options"]
|
[node name="CodeLabel" type="Label" parent="C/V/Help/Options"]
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "An encoded word beginning with \"5$\",
|
text = "An encoded word beginning with \"$\",
|
||||||
e.g. \"5$BTEo\""
|
e.g. \"$bco92\""
|
||||||
label_settings = SubResource("LabelSettings_6at68")
|
label_settings = SubResource("LabelSettings_6at68")
|
||||||
horizontal_alignment = 1
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ enum GameMode {
|
||||||
CUSTOM,
|
CUSTOM,
|
||||||
}
|
}
|
||||||
|
|
||||||
const MIN_LENGTH := 5
|
const MIN_WORD_LENGTH := 3
|
||||||
const MAX_LENGTH := 5
|
const MAX_WORD_LENGTH := 8
|
||||||
const GENERABLE_WORDS_FILENAME = "res://words/popular-filtered.txt"
|
const GENERABLE_WORDS_FILENAME = "res://words/popular-filtered.txt"
|
||||||
const ALL_WORDS_FILENAME := "res://words/enable1.txt"
|
const ALL_WORDS_FILENAME := "res://words/enable1.txt"
|
||||||
|
|
||||||
|
@ -31,8 +31,8 @@ var allow_future := false
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
randomize()
|
randomize()
|
||||||
generable_words = parse_words(GENERABLE_WORDS_FILENAME, MIN_LENGTH, MAX_LENGTH)
|
generable_words = parse_words(GENERABLE_WORDS_FILENAME, MIN_WORD_LENGTH, MAX_WORD_LENGTH)
|
||||||
all_words = parse_words(ALL_WORDS_FILENAME, MIN_LENGTH, MAX_LENGTH)
|
all_words = parse_words(ALL_WORDS_FILENAME, MIN_WORD_LENGTH, MAX_WORD_LENGTH)
|
||||||
|
|
||||||
detect_params()
|
detect_params()
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func generate_word(length: int, random_seed = null) -> String:
|
||||||
|
|
||||||
func is_valid_word(word: String) -> bool:
|
func is_valid_word(word: String) -> bool:
|
||||||
var length := word.length()
|
var length := word.length()
|
||||||
if length < MIN_LENGTH or length > MAX_LENGTH:
|
if length < MIN_WORD_LENGTH or length > MAX_WORD_LENGTH:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
var words_list := all_words[length] as Array
|
var words_list := all_words[length] as Array
|
||||||
|
@ -117,8 +117,8 @@ func detect_params() -> void:
|
||||||
|
|
||||||
## Checks if the given string is:
|
## Checks if the given string is:
|
||||||
##
|
##
|
||||||
## * A normal five letter word, or
|
|
||||||
## * A valid encoded word, or
|
## * A valid encoded word, or
|
||||||
|
## * A normal alphabetical word, or
|
||||||
## * A valid date in YYYY-MM-DD encoding
|
## * 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
|
## * Will only allow this date to be in the present or past, unless `allow_future` is set to true
|
||||||
##
|
##
|
||||||
|
@ -128,11 +128,18 @@ func parse_custom(value: String) -> bool:
|
||||||
custom_word = ""
|
custom_word = ""
|
||||||
custom_date_str = ""
|
custom_date_str = ""
|
||||||
|
|
||||||
if value.length() == 5:
|
var decoded := decode_word(value)
|
||||||
|
var decoded_len := decoded.length()
|
||||||
|
if decoded_len >= MIN_WORD_LENGTH and decoded_len <= MAX_WORD_LENGTH:
|
||||||
|
custom_word = decoded
|
||||||
|
return true
|
||||||
|
|
||||||
|
var value_len := value.length()
|
||||||
|
if value_len >= MIN_WORD_LENGTH and value_len <= MAX_WORD_LENGTH:
|
||||||
# ...is there an is_alpha function that I missed?
|
# ...is there an is_alpha function that I missed?
|
||||||
var word := value.to_upper()
|
var word := value.to_upper()
|
||||||
var valid := true
|
var valid := true
|
||||||
for i in range(5):
|
for i in range(value_len):
|
||||||
var code := word.unicode_at(i)
|
var code := word.unicode_at(i)
|
||||||
if code < 65 or code > 90: # 65 = ascii "A", 90 = ascii "Z"
|
if code < 65 or code > 90: # 65 = ascii "A", 90 = ascii "Z"
|
||||||
valid = false
|
valid = false
|
||||||
|
@ -141,11 +148,6 @@ func parse_custom(value: String) -> bool:
|
||||||
custom_word = word
|
custom_word = word
|
||||||
return true
|
return true
|
||||||
|
|
||||||
var decoded := decode_word(value)
|
|
||||||
if not decoded.is_empty() and decoded.length() == 5:
|
|
||||||
custom_word = decoded
|
|
||||||
return true
|
|
||||||
|
|
||||||
if date_regex.search(value):
|
if date_regex.search(value):
|
||||||
var parsed_date := Time.get_datetime_dict_from_datetime_string(value, false)
|
var parsed_date := Time.get_datetime_dict_from_datetime_string(value, false)
|
||||||
parsed_date["hour"] = 0
|
parsed_date["hour"] = 0
|
||||||
|
@ -187,49 +189,49 @@ func encode_word(word: String) -> String:
|
||||||
word = word.to_upper()
|
word = word.to_upper()
|
||||||
|
|
||||||
# Encode word in base 26
|
# Encode word in base 26
|
||||||
var num := 0
|
var num := 1 # Start with a single 1 bit
|
||||||
for i in range(word.length()):
|
for i in range(word.length()):
|
||||||
var letter_ind := word[i].unicode_at(0) - 65 # 65 = ascii "A"
|
num *= 26
|
||||||
|
var letter_ind := word.unicode_at(i) - 65 # 65 = ascii "A"
|
||||||
if letter_ind < 0 or letter_ind >= 26:
|
if letter_ind < 0 or letter_ind >= 26:
|
||||||
return ""
|
return ""
|
||||||
num += letter_ind * (26 ** i)
|
num += letter_ind
|
||||||
# Add an offset so that "aaaaa" isn't just zeroes
|
|
||||||
num += 123456
|
|
||||||
|
|
||||||
return str(word.length()) + ENCODING_INDICATOR + large_encode(num)
|
# Bit count for redundancy
|
||||||
|
var count := popcnt(num)
|
||||||
|
num = (num << 6) + count
|
||||||
|
|
||||||
|
return ENCODING_INDICATOR + large_encode(num)
|
||||||
|
|
||||||
|
|
||||||
## Decodes an encoded word. Returns an empty string if invalid
|
## Decodes an encoded word. Returns an empty string if invalid
|
||||||
func decode_word(encoded_word: String) -> String:
|
func decode_word(encoded_word: String) -> String:
|
||||||
var index := encoded_word.find(ENCODING_INDICATOR)
|
if not encoded_word.begins_with(ENCODING_INDICATOR):
|
||||||
if index < 1:
|
|
||||||
return ""
|
|
||||||
var len_str := encoded_word.substr(0, index)
|
|
||||||
if not len_str.is_valid_int():
|
|
||||||
return ""
|
|
||||||
var word_len := len_str.to_int()
|
|
||||||
if word_len < 1:
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
var large_base_str := encoded_word.substr(index + 1)
|
var large_base_str := encoded_word.substr(1)
|
||||||
var num := large_decode(large_base_str)
|
var full_num := large_decode(large_base_str)
|
||||||
if num < 0:
|
|
||||||
|
# Check the bit count
|
||||||
|
var count := full_num & 0x3F # 6 bits
|
||||||
|
var num := full_num >> 6
|
||||||
|
if popcnt(num) != count:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
num -= 123456
|
if num <= 0:
|
||||||
|
|
||||||
if num < 0 or num >= (26 ** word_len): # (26 ** 5) - 1 = "ZZZZZ"
|
|
||||||
# Someone is trying to be sneaky! Or more likely I just messed up.
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# Decode base 26 word
|
# Decode base 26 word
|
||||||
var word := ""
|
var word := ""
|
||||||
for i in range(word_len):
|
while num > 1:
|
||||||
var letter_ind := num % 26
|
var letter_ind := num % 26
|
||||||
word += char(letter_ind + 65) # 65 = ascii "A"
|
word = char(letter_ind + 65) + word # 65 = ascii "A"
|
||||||
@warning_ignore("integer_division")
|
@warning_ignore("integer_division")
|
||||||
num = num / 26
|
num = num / 26
|
||||||
|
|
||||||
|
if num != 1:
|
||||||
|
return ""
|
||||||
|
|
||||||
return word
|
return word
|
||||||
|
|
||||||
|
|
||||||
|
|
24
src/main.gd
24
src/main.gd
|
@ -1,7 +1,6 @@
|
||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
|
|
||||||
const letter_count := 5
|
|
||||||
const guess_count := 6
|
const guess_count := 6
|
||||||
|
|
||||||
const Letter := preload("res://src/letter.tscn")
|
const Letter := preload("res://src/letter.tscn")
|
||||||
|
@ -13,6 +12,7 @@ const Letter := preload("res://src/letter.tscn")
|
||||||
# An array of arrays of the letter nodes
|
# An array of arrays of the letter nodes
|
||||||
var letters := []
|
var letters := []
|
||||||
var keyboard_buttons := {}
|
var keyboard_buttons := {}
|
||||||
|
var letter_count := 5
|
||||||
|
|
||||||
var target_word: String
|
var target_word: String
|
||||||
var current_guess: int
|
var current_guess: int
|
||||||
|
@ -37,16 +37,6 @@ var input_guess: String
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
letter_grid.columns = letter_count
|
|
||||||
for _i in range(guess_count):
|
|
||||||
var letter_array := []
|
|
||||||
for _j in range(letter_count):
|
|
||||||
var letter := Letter.instantiate()
|
|
||||||
letter_array.append(letter)
|
|
||||||
letter_grid.add_child(letter)
|
|
||||||
letters.append(letter_array)
|
|
||||||
|
|
||||||
|
|
||||||
if Global.game_mode != Global.GameMode.CUSTOM:
|
if Global.game_mode != Global.GameMode.CUSTOM:
|
||||||
Global.custom_word = ""
|
Global.custom_word = ""
|
||||||
Global.custom_date_str = ""
|
Global.custom_date_str = ""
|
||||||
|
@ -75,6 +65,16 @@ func _ready() -> void:
|
||||||
if Global.game_mode != Global.GameMode.DAILY:
|
if Global.game_mode != Global.GameMode.DAILY:
|
||||||
subtitle.text = Global.encode_word(target_word)
|
subtitle.text = Global.encode_word(target_word)
|
||||||
|
|
||||||
|
letter_count = target_word.length()
|
||||||
|
letter_grid.columns = letter_count
|
||||||
|
for _i in range(guess_count):
|
||||||
|
var letter_array := []
|
||||||
|
for _j in range(letter_count):
|
||||||
|
var letter := Letter.instantiate()
|
||||||
|
letter_array.append(letter)
|
||||||
|
letter_grid.add_child(letter)
|
||||||
|
letters.append(letter_array)
|
||||||
|
|
||||||
current_guess = 0
|
current_guess = 0
|
||||||
ended = false
|
ended = false
|
||||||
won = false
|
won = false
|
||||||
|
@ -132,7 +132,7 @@ func guess_entered() -> void:
|
||||||
return
|
return
|
||||||
input_guess = input_guess.to_upper()
|
input_guess = input_guess.to_upper()
|
||||||
if input_guess.length() != letter_count:
|
if input_guess.length() != letter_count:
|
||||||
show_error("Word must be five characters.")
|
show_error("Word must be %d characters." % [letter_count])
|
||||||
return
|
return
|
||||||
if not Global.is_valid_word(input_guess) and input_guess != target_word:
|
if not Global.is_valid_word(input_guess) and input_guess != target_word:
|
||||||
show_error("Not a recognized word.")
|
show_error("Not a recognized word.")
|
||||||
|
|
Loading…
Reference in a new issue