Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negation of a state in defining a new command #214

Closed
sultanalnahian opened this issue Feb 17, 2020 · 10 comments
Closed

Negation of a state in defining a new command #214

sultanalnahian opened this issue Feb 17, 2020 · 10 comments

Comments

@sultanalnahian
Copy link

While defining a new command in the logic file, is it possible to mention that certain state cannot be satisfied? For example, I have a game scenario where, you can ask a information to a person. The question can be asked until the person gives the answer. When the person has given the information, you cannot ask the question again. So, I have defined a predicate "asked(pr)", which represents the state when the question has been asked already. And the rule is "ask/pr(pr)" which will be available only when the question was not asked before. So how can I add not "asked(pr)" state in the rule definition?

@MarcCote
Copy link
Contributor

Hi @sultanalnahian, thanks for reaching out. The logic engine powering TextWorld uses the open-world assumption which means that not seeing a particular predicate in the state, does not mean it is false.

In your example, a workaround would be to define both asked(topic, person) and not_asked(topic, person) predicates. Then your ask rules could be something like

ask :: $at(P, r) & $at(person, r) & not_asked(topic, person) -> asked(topic, person);

NB: of course, you'll need to add all the relevant not_asked(...) predicates to the initial state.

@sultanalnahian
Copy link
Author

Hi @sultanalnahian, thanks for reaching out. The logic engine powering TextWorld uses the open-world assumption which means that not seeing a particular predicate in the state, does not mean it is false.

In your example, a workaround would be to define both asked(topic, person) and not_asked(topic, person) predicates. Then your ask rules could be something like

ask :: $at(P, r) & $at(person, r) & not_asked(topic, person) -> asked(topic, person);

NB: of course, you'll need to add all the relevant not_asked(...) predicates to the initial state.

Hi @MarcCote, thanks for the reply. After executing the ask command, will the state not_asked be changed to the asked state? Does it mean that, the not_asked state is no longer true and as a result ask command cannot be executed again?

@MarcCote
Copy link
Contributor

Yes. Your understanding is correct. If I'm not mistaking, that's what you were trying to do, right?

@sultanalnahian
Copy link
Author

Yes, that's right. But It is not working. After giving the ask command, the command should not be shown in the game play as not_asked state is false now. But still the ask command is showing in the game play and it can be executed again. I am posting the person logic file below. Can you please, let me know what I have done wrong?

# person
type pr : t{
    predicates {
        attacked(pr);
        asked(pr);
	not_asked(pr);
    }
    rules {
        attack/pr   :: $at(P, r) & $at(pr, r) -> attacked(pr);
        ask/pr :: $at(P, r) & $at(pr,r) & $in(f, I) & $raw(f) & not_asked(pr) -> asked(pr);
    }
    constraints {
    # Predicate conflicts
    	pr1 :: asked(pr) & not_asked(pr) -> fail();
    }
    inform7 {   
        type {
            kind :: "person";
            definition :: "Person can be attacked. Person can be asked. Person is fixed in place.";
        }

        predicates {
            attacked(pr) :: "The {pr} is attacked";
            asked(pr) :: "The {pr} is asked";
            not_asked(pr) :: "The {pr} is not asked";
        }

        commands {
            attack/pr :: "attack {pr}" :: "_attacking {pr}";
            ask/pr :: "ask the {pr} about the bank robbery" :: "_ask the {pr} about the bank robbery";
        }
	code :: """
            Understand the command "attack" as something new.
            Understand "attack [something]" as _attacking.
            _attacking is an action applying to a thing.

            After _attacking a person:
		say "[the noun] is being attacked.";
            
            Understand the command "ask" as something new.
            Understand "ask [something]" as _asking.
            _asking is an action applying to a thing.

            After _asking a person:
		say "[the noun] has given the information. he said go north.";
           """;
    }
}

@MarcCote
Copy link
Contributor

I think you need _asking instead of _ask in the last section of the Inform7 ask command.

commands {
        ....
            ask/pr :: "ask the {pr} about the bank robbery" :: "_ask the {pr} about the bank robbery";
        }

I just create a PR that will enable you to see what Inform7 events get detected.
#217

You can enable debugging like so:
TEXTWORLD_DEBUG=1 tw-play --hint your_game.ulx

@sultanalnahian
Copy link
Author

I think you need _asking instead of _ask in the last section of the Inform7 ask command.

commands {
        ....
            ask/pr :: "ask the {pr} about the bank robbery" :: "_ask the {pr} about the bank robbery";
        }

I just create a PR that will enable you to see what Inform7 events get detected.
#217

You can enable debugging like so:
TEXTWORLD_DEBUG=1 tw-play --hint your_game.ulx

I have corrected _ask to _asking. But still it is not working.

@MarcCote
Copy link
Contributor

Do you have the list of i7_events detected when you try the ask command? You need to reinstall textworld from the master branch first.
pip install -U https://github.com/microsoft/TextWorld/archive/master.zip

@MarcCote
Copy link
Contributor

I played around with the code snippet you shared. I was able to make the ask action appears only once. Here's my test file and the content of the .twl file.

test_asking.py

import textworld


M = textworld.GameMaker()
R = M.new_room("Room A")
M.set_player(R)

alice = M.new("pr", "Alice")
R.add(alice)

alice.add_property("not_asked")

M.test()

output

-= Room A =-
You arrive in a Room A. A typical kind of place.

There is an Alice on the floor.

> ask the Alice about the bank robbery
[DEBUG] Detected Inform7 events:
['_asking the Alice']

the Alice has given the information. he said go north.

> attack Alice
[DEBUG] Detected Inform7 events:
['_attacking the Alice']

the Alice is being attacked.

> attack Alice
[DEBUG] Detected Inform7 events:
['_attacking the Alice']

the Alice is being attacked.

>

person.twl

# person
type pr : t{
    predicates {
        attacked(pr);
        asked(pr);
	    not_asked(pr);
    }
    rules {
        attack/pr   :: $at(P, r) & $at(pr, r) -> attacked(pr);
        ask/pr :: $at(P, r) & $at(pr,r) & not_asked(pr) -> asked(pr);
    }
    constraints {
    # Predicate conflicts
    	pr1 :: asked(pr) & not_asked(pr) -> fail();
    }
    inform7 {
        type {
            kind :: "person";
            definition :: "Person can be attacked. Person can be asked. Person is fixed in place.";
        }

        predicates {
            attacked(pr) :: "The {pr} is attacked";
            asked(pr) :: "The {pr} is asked";
            not_asked(pr) :: "The {pr} is not asked";
        }

        commands {
            attack/pr :: "attack {pr}" :: "_attacking the {pr}";
            ask/pr :: "ask the {pr} about the bank robbery" :: "_asking the {pr}";
        }
	code :: """
            Understand the command "attack" as something new.
            Understand "attack [someone]" as _attacking.
            _attacking is an action applying to a thing.

            After _attacking a person:
		        say "[the noun] is being attacked.";

            Understand the command "ask" as something new.
            Understand "ask [someone] about [text]" as _asking.
            _asking is an action applying to a thing and one topic.

            After _asking a person:
		        say "[the noun] has given the information. he said go north.";
           """;
    }
}

@sultanalnahian
Copy link
Author

It is working now. So the only change is in the command definition of ask/pr. Changing "_asking the {pr} about the bank robbery" to "_asking the {pr}", makes it working.

Thank you very much for helping me.

@MarcCote
Copy link
Contributor

Do not hesitate if you have other questions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants