Script to accept random keycode?

OurJud
29 Nov 2016, 18:42I have an idea for a sci-fi themed game which will start out with 'you' trapped in lab. The only way out is via a seven-number combination lock. Initially, any number sequence they enter will return a fail, but when the player finds an experimental serum in one of the cabinets which makes anyone who takes it the luckiest person alive, they can return to the keypad and effectively guess the code.
For this to happen I need a script which 'locks' the keypad, in as much as any combination of numbers will fail, but then when the player has the 'serum' flag set to them, any combination of numbers will be accepted and open the door.
How would I make sure that anything BUT a seven-number code would be rejected (in others 6 or 8 numbers, or any letters wouldn't work), once they have the serum, but also that ANY seven-number code will work, so long as it's only 7 numbers?
There's a keypad on the wall.
> use keypad
Please enter your seven-number code.
> 2394572
Fail.
> 98u3209
Fail - Please enter numbers only.
> 2304
The keypad requires seven numbers.
> cancel (takes player out of keypad loop)
(player find and takes serum then returns to the keypad)
> 8349028 (or any other seven number code)
Green light. Door opens

Father
29 Nov 2016, 19:05Why don't you make the combination a password. We are encouraged to add letters, numbers and even punctuation to passwords, so a password could be anything.
XanMag
29 Nov 2016, 19:21I was thinking the same thing. You could make two separate keypads and swap them out when the serum is consumed. Then run a script that accounts for any input generating an error response for using keypad1 and run a script that accounts for any input generating a correct response for keypad2?

OurJud
29 Nov 2016, 19:35That is one way round, but I can't imagine a keypad on a door that allows for any characters.
I wanted to be quite strict about it being a seven-digit number.
A script to allow any input is easy enough, but I don't know what that script would be to allow any seven-digit number to unlock the door, but only a seven-digit number.
The Pixie
29 Nov 2016, 20:09I thought about doing exactly that just a few days ago, inspired by your user image.
I would use IsRegexMatch
to compare the input. This will check the string is just seven digits:
if (IsRegexMatch("^\d\d\d\d\d\d\d$", result) {
If it does match, but the player has not taken the serum, put the result in a stringlist (attribute of game maybe), so when the player does take it you can test if it is the same as one tried previously (no matter how lucky you are, a code that failed before should still fail).
if (ListContains(game.badguesses, result) {
Is that enough for you to get going?
hegemonkhan
29 Nov 2016, 20:19you can of course change/split/nest/expand my code for what you want*, but here's how it'd be done in simplicity:
http://docs.textadventures.co.uk/quest/functions/isint.html
http://docs.textadventures.co.uk/quest/functions/string/lengthof.html
// HK edited:
get input {
if (NAME_OF_OBJECT.NAME_OF_BOOLEAN_ATTRIBUTE and IsInt (result) and LengthOf (result) = 7) {
// door is unlocked/opened/etc
} else {
// fail
}
}
// the 'player.serum' check is the first check operation, and if that succeeds/passes, next it does the 'IsInt' check, and if that succeeds/passes, then lastly, it does the 'LengthOf' (7 character) check, and if that succeeds/passes, the door is unlocked. If any of the checks fail, then you fail to unlock the door.
.* (if you need help on how to adjust it to what you want, such as prompting about each of the different checks fails, or whatever, let me know and I'll provide the code/help you need for doing it)

OurJud
29 Nov 2016, 23:02Thank you both.
TP, I was hoping there were no other Dwarfers on here ;-)
As for the code, I'm afraid it's a bit beyond me to take it alone from there. Is the RegexMatch checking that the input is numbers so that I can return a 'Numbers only' message if they used letters? The narrative will explain they need to enter numbers, so I'm probably allowing for something that 90% of players aren't going to do, but if it wasn't too difficult...
hege, I'm guessing yours only checks for characters too, as opposed to numbers only, although I can at least see how yours is working (I don't mean that in a negative manner, TP)
I'll have a few test runs with hege's script (at least for now, as I understand it)

OurJud
29 Nov 2016, 23:26Your script gets this, hege:
Error running script: Error compiling expression 'player.serum and IsInt (result) and LengthOf (result) = 7': AndOrElement: Operation 'And' is not defined for types 'Object' and 'Boolean'

OurJud
29 Nov 2016, 23:48I have a horrible feeling this is going to be too difficult and just frustrate me, so I think I'll keep it simple, go with this and just leave it down to the player to enter a seven digit number when instructed.
msg ("You step up to the keypad. Please enter the seven-digit code.")
get input {
if (GetBoolean(player, "gotserum")) {
msg ("The door slides open")
}
else {
msg ("Incorrect keycode")
}
}
Deckrect
30 Nov 2016, 00:24I am not a programmer, so i find the simple solution, always the best one.
Create two Objects: False Keypad and Real Keypad. The Real, always return errors and never unlocks. The False, always return the "unlock" result, no matter what was typed. Make them visible and invisible, depending on the "Serum" flag. Once in place, you may add a little complexity to check if the player typed numbers and not letters using the "Is Int" and "To Int" resources.
hegemonkhan
30 Nov 2016, 02:54I think my syntax is fine (it could be wrong though, but I don't think so... lol), which means that the error is merely that you've used 'serum' as your Boolean Attribute's name from my code, but in your game, you've got no 'serum' Boolean Attribute on your 'player' Player Object, and thus the error, as instead, you've got a 'gotserum' Boolean Attribute on your 'player' Player Object:
if your (Boolean) Attribute is named 'gotserum', then you need to change it as so within my code:
if (player.gotserum and IsInt (result) and LengthOf (result) = 7) {
alternatively, this is the same scripting (technically it has a bit more overhead/extra-coding-underneath, but this probably isn't going to be an issue, lol):
if (GetBoolean (player, "gotserum") and IsInt (result) and LengthOf (result) = 7) {
(also, if the Object's 'name' is not 'player', you need to change it in my code to your Object's 'name', as well)
the 'IsInt' checks for if your input (which is stored/saved/set into the built-in 'result' Variable) is an integer number
result = abc
if (IsInt (result)) ---> FALSE (fail)
result = abc123
if (IsInt (result)) ---> FALSE (fail)
result = 1.0023
if (IsInt (result)) ---> FALSE (fail)
result = 123
if (IsInt (result)) ---> TRUE (succeeds/passes)
result = 1.0023
if (IsDouble (result)) ---> TRUE (succeeds/passes)
result = 123
if (IsDouble (result)) ---> FALSE (fail)
result = abc
if (IsDouble (result)) ---> FALSE (fail)
result = abc123
if (IsDouble (result)) ---> FALSE (fail)
(if I understand)
result = 1.0023
if (IsNumeric (result)) ---> TRUE (succeeds/passes)
result = 123
if (IsNumeric (result)) ---> TRUE (succeeds/passes)
result = abc
if (IsNumeric (result)) ---> FALSE (fail)
result = abc123
if (IsNumeric (result)) ---> FALSE (fail)

OurJud
30 Nov 2016, 03:19I initially had the boolean as serum, but was still getting the error.
Thank you for the revision.
hegemonkhan
30 Nov 2016, 04:07unfortunately when the ERROR is, '... for types Object and ....', this can be a specific error (non-matching Attribute/Data Types: 'object' vs ' int' or 'double' vs 'int' or 'string' vs 'int' or etc etc etc), or it's a generalized/default error in that you used something that doesn't exist in the game (you typo'ed somewhere in your code). When the Error mentions an 'Object', you've no idea what the error is talking about, unfortunately, as it's totally amibigious... argh. It's the least informative error... not good to get it, lol.
hegemonkhan
30 Nov 2016, 04:20here's what my code is doing:
Boolean Logic / Truth Tables:
'AND' Boolean Logic / Truth Table:
true and true ---> TRUE
true and false ---> FALSE
false and true ---> FALSE
false and false ---> FALSE
how does more than two factors work?, see below:
--
the grouping priorities: brackets, braces, curly brackets/braces, are the same as they're in math: more inner = higher priority
--
math:
5 * 2 + 3
// the multiplication has higher priority than the addition:
// effectively: (5 * 2) + 3 = (10) + 3 = 13
but, if we put in grouping symbols (parenthesis), they have higher priority than the multiplication:
5 * (2 + 3)
5 * (5) = 25
--
coding example:
string_variable = StringDictionaryItem (game.mydict, StringListItem (game.mylist, GetRandomInt (0,9)))
the '(0,9)' is put-into/used-for the 'GetRandomInt', the 'GetRandomInt' returns an integer value, the '(game.mylist, integer value)' is put-into/used-for the 'StringListItem', the 'StringListItem' returns a string value, the '(game.mydict, string value)' is put-into/used-for the 'StringDictionaryItem', the 'StringDictionaryItem' returns a string value, the string value is stored/saved/set-into the 'string_variable'
--
'[ false and false and false ]' example:
// if read from left:
[ ( false and false) and false ] ---> FALSE
[ (false) and false ] ---> FALSE
[ false and false ] ---> FALSE
// or, if read from right:
[ false and (false and false) ] ---> FALSE
[ false and (false) ] ---> FALSE
[ false and false ] ---> FALSE
player.gotserum = true ---> true
or
player.gotserum ---> true
or
not player.gotserum = false ---> true
or
player.gotserum <> false ---> true
// or
player.gotserum = false ---> false
or
not player.gotserum ---> false
or
player.gotserum <> true ---> false
IsInt (result) ---> true
or
IsInt (result) = true ---> true
or
not IsInt (result) = false ---> true
or
IsInt (result) <> false ---> true
// or
IsInt (result) ---> false
or
not IsInt (result) ---> false
or
IsInt (result) <> true ---> false
or
IsInt (result) = false ---> false
LengthOf (result) = 7 ---> true
or
LengthOf (result) = 7 ---> false
// etc etc etc (see player.gotserum or IsInt examples, I got lazy)
if (player.gotserum and IsInt (result) and LengthOf (result) = 7)
if (true and true and true) ---> TRUE, do its nested 'then' scripting/action
if (true and true and false) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (true and false and true) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (true and false and false) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (false and true and true) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (false and true and false) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (false and false and true) ---> FALSE, skip/don't-do its nested 'then' scripting/action
if (false and false and false) ---> FALSE, skip/don't-do its nested 'then' scripting/action
The Pixie
30 Nov 2016, 08:11Try this:
msg ("You step up to the keypad. Please enter the seven-digit code.")
get input {
if (not IsRegexMatch("^\\d\\d\\d\\d\\d\\d\\d$", result)) {
msg ("I said seven-digit... That means seven digits. Sorry for the confusion.")
}
else if (ListContains(game.badguesses, result)) {
msg ("You tried that before and it did not work.")
}
else if (not GetBoolean(player, "gotserum")) {
msg ("Incorrect keycode")
list add (game.badguesses, result)
}
else {
msg ("The door slides open")
}
}
You will need to add a string list attribute called badguesses
to the game object.

OurJud
30 Nov 2016, 13:01Thank you, TP. This works up to a point, but then I get this error which I suspect is my fault becuase I don't know anything about string list attributes.
I went to the attribute tab of my keypad object (which is where I have your script in the Use/Give tab) and just clicked 'Add' on attributes and typed badguesses, but I don't know what to put in the value for it.
I get the error if I type seven digits before or after takingthe serum.
Error running script: Error evaluating expression 'ListContains(game.badguesses, result)': ListContains function expected list parameter but was passed 'null'
The Pixie
30 Nov 2016, 14:06Put the attribute on the game
object. Set it to be a string list in the drop down list, but leave it empty.

OurJud
30 Nov 2016, 15:09Okay, did that, and now I get:
Error running script: Error evaluating expression 'ListContains(game.badguesses, result)': ListContains function expected list parameter but was passed ''
It's okay, I've got a working system now. This is what I'm using:
msg ("You step up to the keypad. Please enter the seven-digit code.")
get input {
if (GetBoolean(player, "gotserum")) {
msg ("The door slides open")
MoveObject (player, corridor)
}
else if (result="Cancel" or result="cancel") {
ShowRoomDescription
}
else {
msg ("Incorrect keycode")
do (keypadCommand, "script")
}
}
The Pixie
30 Nov 2016, 15:36I am guessing you still had badguesses
as a string, rather than a string list.

OurJud
30 Nov 2016, 15:49Yes, I did. Sorry.
I wish my brain functioned better than it does, but it doesn't. I seriously suspect it's diseased.
DarkLizerd
01 Dec 2016, 04:57Another approach...
"You drink the serum, and suddenly realize that 7341025 is the obvious answer!!!
You return to the keypad you enter the number and the door opens"
But the player never enters the key code, you just tell the player that he did...
No need to enter any numbers...
No need to check and verify the entered digits...

OurJud
01 Dec 2016, 06:02That's an idea, DarkLizerd, but the system I've got now is good enough I think. I tell them they have to enter a seven-digit number code, so if they want to go 'testing' my system by entering random characters, good luck to them.