Inform 7 error using If player consents - inform7

I'm trying to write a piece of interactive fiction using inform 7, I want to put a choice in there for the player and I want a simple yes or no I used the following code:
if the player consents say "You get a better view of the stranger."
Otherwise:
say "You can't make out what's happening clearly, however, you notice the stranger walking out of the pub"
I then get this useless error message:
You wrote 'if the player consents say "You get a better view of the stranger."' : but I can't find a verb that I know how to deal with. This looks like an 'if' phrase which has slipped its moorings, so I am ignoring it. ('If' phrases, like all other such instructions, belong inside definitions of rules or phrases - not as sentences which have no context. Maybe a full stop or a skipped line was accidentally used instead of semicolon, so that you inadvertently ended the last rule early?)
Any help would be greatly appreciated.

The punctuation is off. Phrases should end with a semicolon, and if phrases should use either begin..end blocks, or the "colon-and-indentation" style. So either:
if the player consents begin;
say "You get a better view of the stranger.";
otherwise;
say "You can't make out what's happening clearly, however, you notice the stranger walking out of the pub";
end if;
or
if the player consents:
say "You get a better view of the stranger.";
otherwise:
say "You can't make out what's happening clearly, however, you notice the stranger walking out of the pub";
Note the colons and semicolons and tabs in the second example.
Also, as the error message says, you need to specify when that question should be asked. If phrases must be inside rules or phrases. For example, if the question should be asked as a result of an action:
After examining the stranger for the first time:
say "Move closer?";
if the player consents begin;
say "You get a better view of the stranger.";
otherwise;
say "You can't make out what's happening clearly, however, you notice the stranger walking out of the pub";
end if;

Related

Prevent automatically entering the room on startup

I want to give the player a chance to select a few options on game startup, such as their name.
The only problem is that the game insists on putting the player into the first room immediately and print the room name and description. That's not interesting for the player yet, though.
How can I prevent Inform 7 from automatically putting the player into the first room, or at least suppress the room name and description printing at startup?
The solution I found:
The initial room is a room.
The first rule for printing the name of a room:
if the player is in the initial room:
do nothing;
otherwise:
continue the action.

Find out in what line Espresso fails exactly

I am running Espresso tests on my Android app. If one fails I the view tree is printed. Unfortunately I don't know in what line this failure occurs exactly.
Is there a way to tell Espresso to print the stack trace when an Exception is thrown (e.g. NoMatchingViewException) so I can see in what line my tests fails?
Thanks
Thomas
EDIT:
Output I get looks like (removed part in the middle):
android.support.test.espresso.AmbiguousViewMatcherException: 'with id: com.wombatl.mobility.charge.test:id/stopChargingButton' matches multiple views in the hierarchy.
Problem views are marked with '****MATCHES****' below.
View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1080, height=2160, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=WM.LayoutParams{(0,0)(fillxfill) ty=1 fl=#81810100 pfl=0x20000 wanim=0x10302f6 needsMenuKey=2 colorMode=0}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}
|
+->LinearLayout{id=-1, visibility=VISIBLE, width=1080, height=2034, has-focus=true, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.FrameLayout$LayoutParams#48dbdb, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=2}
|
(...)
|
+--------------->AppCompatTextView{id=2131361990, res-name=hoursTextView, visibility=VISIBLE, width=68, height=53, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params=android.widget.Rela
No, the line number will not be shown in the failure message. You will have to deduce it yourself.
It is clearly stated that you have multiple matches for the view with id stopChargingButton. That's it.
android.support.test.espresso.AmbiguousViewMatcherException: 'with id: com.wombatl.mobility.charge.test:id/stopChargingButton' matches multiple views in the hierarchy.
View matchers should match only one element otherwise Espresso doesn't know what view to operate on and throws the exception. Add additional matching criteria to identify specific view on the screen. You may use allOf() hamcrest matcher for this purpose.
If the view you wanna operate on is the part of the ListView - use onData(). If it is inside RecyclerView look in the documentation how to operate on the item which is the part of the RecyclerView.

Waiting for elements to update in an asp.net site

I am using excel vba to create an API of sorts for a third party .aspx site.
For testing I have set it up to search for a person by their ID and the print their name as displayed on the webpage.
The problem is that the function will print the name of the last person searched not the current one, even though the page displays the correct name.
So,
search John Cleese's ID
Print "Cleese, John"
search Michael Palin's ID
Print "Cleese, John"
search Eric Idle's ID
Print "Palin, Michael"
search Terry Jones' ID
Print "Idle, Eric"
I believe the cause is that the function is getting the name before the specific html element with the persons name on it has updated. .Busy or .ReadyState seem ineffective because the site is ASP.NET
Code
Public Function search(ID as string)
With IE
.Navigate idSearch_URL
Do While .ReadyState <> 4 Or .Busy: DoEvents: Loop ' wait
With .Document
.getElementByID(idSearchTxt_ID).Vlaue = ID ' enter id
.getEleentById(idFindBtn_ID).Click ' search it
End With
Do While .ReadyState <> 4 Or .Busy: DoEvents: Loop ' wait
Debug.Print .Document.getElementByID(nameLabelID).innerText ' Prints prev. name
End With
End Function
I know the issue is that the wait loops aren't waiting for existing elements to update because, if I set through with the debugger or just insert a Sleep call before the Debug.Print, then the correct name is printed. What methods can I use to wait until the nameLabelID has updated or all of the webpage has updated.
I don't want to use a Sleep call because it's a waste of time and I can't shorten it to like 10 ms because I don't know if that would be long enough.
I don't think I should share much of the source code for the website. However, I could drop some of the javascript functions, if a solution involves them.
PS. I know nothing about ASP.NET. The behavior of the site indicates like there are some local variables set when navigating the site. Are they client side? Is there a way to grab those directly and bypass reading the webpage?
PPS, This may be just for comments, but would another language like perl or ruby be more appropriate for this than VBA?

Prolog: Recursion and splitting lists

I'm trying to write a game in which the program reads through a database, grabs attributes and asks the player if the Movie that the player is thinking of will have that attribute. The user will answer either yes or no and if yes, the game will ask about the next attribute until either the user has said yes to every attribute, at that point the program will output the name of the movie. Or if the user says no, the game will then move along to the next movie in the database and start asking about those attributes.
The game ends when either it finds a movie with all the attributes or there are no more movies in the database in which the program could ask about.
Here is the database file.
object_properties(crocodile_dundee,[comedy,australian,paul_hogan_movie]).
object_properties(flipper,[action_movie,australian, paul_hogan_movie,
-comedy]).
object_properties(jackass,[comedy,-australian]).
object_properties(the_godfather,[drama,crime,-character_batman]).
object_properties(the_dark_knight,[drama,crime,character_batman]).
object_properties(the_living_planet, [documentary,director_attenborough]).
object_properties(the_code, [documentary,nerds_love_it]).
object_properties(the_russian_revolution, [documentary,about_history]).
Here is my game file.
go():-
guess_object(0,[]).
guess_object(Obj,[A|As]) :-
object_categories(Obj,A).
guess_object(1).
guess_object(2).
guess_object(3).
guess_object(4).
guess_object(5). %how do i do this specifically for the current Obj attributes?
guess(X) :- guess_object(_, X),
writeln('Does your object have the attribute '(X)'?'),
read(Input), Input=('yes') -> assert(object(X)) ; retractall(X), guess(X).
writeln('I guess that the film is: 'guess_object(Obj,_).
The main questions I have:
How do I split the object attributes in to a list like I'm trying to do on guess_object(1) through to guess_object(5) depending on whether the object has 2 attributes or 4 attributes, etc.
How do I make my guess(A) predicate recursive so once the user says no it will then go to the next object in the database file?
I'm not too great at prolog but any advice or pointers would be greatly appreciated, even if it's just pointing out a stupid mistake I may have made. I will also answer any questions anyone has to the best of my ability.

What is the most efficient way of filling in details on a web form?

Take a standard web page with lots of text fields, drop downs etc.
What is the most efficient way in webdriver to fill out the values and then verify if the values have been entered correctly.
You only have to test that the values are entered correctly if you have some javascript validation or other magic happening at your input fields. You don't want to test that webdriver/selenium works correctly.
There are various ways, depending if you want to use webdriver or selenium. Here is a potpourri of the stuff I'm using.
Assert.assertEquals("input field must be empty", "", selenium.getValue("name=model.query"));
driver.findElement(By.name("model.query")).sendKeys("Testinput");
//here you have to wait for javascript to finish. E.g wait for a css Class or id to appear
Assert.assertEquals("Testinput", selenium.getValue("name=model.query"));
With webdriver only:
WebElement inputElement = driver.findElement(By.id("input_field_1"));
inputElement.clear();
inputElement.sendKeys("12");
//here you have to wait for javascript to finish. E.g wait for a css Class or id to appear
Assert.assertEquals("12", inputElement.getAttribute("value"));
Hopefully, the results of filling out your form are visible to the user in some manner. So you could think along these BDD-esque lines:
When I create a new movie
Then I should see my movie page
That is, your "new movie" steps would do the field entry & submit. And your "Then" would assert that the movie shows up with your entered data.
element = driver.find_element(:id, "movie_title")
element.send_keys 'The Good, the Bad, the Ugly'
# etc.
driver.find_element(:id, "submit").click
I'm just dabbling in this now, but this is what I came up with so far. It certainly seems more verbose than something like Capybara:
fill_in 'movie_title', :with => 'The Good, the Bad, the Ugly'
Hope this helps.

Resources