GLK: COMPREHEND: Fix answering rhetorical questions

This commit is contained in:
Paul Gilbert 2020-10-31 11:00:48 -07:00
parent 0b93a68a0d
commit a5b9eeb7ab
5 changed files with 40 additions and 15 deletions

View File

@ -75,6 +75,7 @@ DebuggerDumper::DebuggerDumper() : _game(nullptr) {
_opcodes[OPCODE_INVENTORY] = "inventory";
_opcodes[OPCODE_MOVE_OBJECT_TO_ROOM] = "move_object_to_room";
_opcodes[OPCODE_SAVE_ACTION] = "save_action";
_opcodes[OPCODE_CLEAR_LINE] = "clear_line";
_opcodes[OPCODE_MOVE_TO_ROOM] = "move_to_room";
_opcodes[OPCODE_VAR_ADD] = "var_add";
_opcodes[OPCODE_SET_ROOM_DESCRIPTION] = "set_room_description";

View File

@ -42,6 +42,11 @@ void Sentence::clear() {
_specialOpcodeVal2 = 0;
}
void Sentence::copyFrom(const Sentence &src, bool copyNoun) {
for (uint idx = (copyNoun ? 0 : 1); idx < 6; ++idx)
_formattedWords[idx] = src._formattedWords[idx];
}
void Sentence::format() {
for (uint idx = 0; idx < 6; ++idx)
_formattedWords[idx] = 0;
@ -110,7 +115,8 @@ void Sentence::format() {
/*-------------------------------------------------------*/
ComprehendGame::ComprehendGame() : _gameStrings(nullptr), _ended(false) {
ComprehendGame::ComprehendGame() : _gameStrings(nullptr), _ended(false),
_nounState(NOUNSTATE_INITIAL) {
}
ComprehendGame::~ComprehendGame() {
@ -798,7 +804,7 @@ void ComprehendGame::doAfterTurn() {
}
void ComprehendGame::read_input() {
Sentence sentence;
Sentence tempSentence;
char *line = NULL, buffer[1024];
bool handled;
@ -835,8 +841,13 @@ void ComprehendGame::read_input() {
line = &buffer[0];
while (1) {
read_sentence(&line, &sentence);
handled = handle_sentence(&sentence);
NounState prevNounState = _nounState;
_nounState = NOUNSTATE_STANDARD;
read_sentence(&line, &tempSentence);
_sentence.copyFrom(tempSentence, tempSentence._formattedWords[0] || prevNounState != NOUNSTATE_QUERY);
handled = handle_sentence(&_sentence);
if (handled)
doAfterTurn();

View File

@ -34,6 +34,8 @@ namespace Comprehend {
#define ROOM_IS_DARK 1
#define ROOM_IS_TOO_BRIGHT 2
enum NounState { NOUNSTATE_STANDARD = 0, NOUNSTATE_QUERY = 1, NOUNSTATE_INITIAL = 2 };
struct GameStrings;
struct Sentence;
@ -48,11 +50,19 @@ struct Sentence {
}
bool empty() const {
return _nr_words == 0;
return !_formattedWords[0];
}
/**
* Clears the sentence
*/
void clear();
/**
* Copies from another sentence to this one
*/
void copyFrom(const Sentence &src, bool copyNoun = true);
/**
* Splits up the array of _words into a _formattedWords
* array, placing the words in appropriate noun, verb, etc.
@ -64,6 +74,8 @@ struct Sentence {
class ComprehendGame : public GameData {
protected:
bool _ended;
NounState _nounState;
Sentence _sentence;
public:
const GameStrings *_gameStrings;

View File

@ -89,6 +89,7 @@ enum ScriptOpcode {
OPCODE_TAKE_OBJECT,
OPCODE_MOVE_OBJECT_TO_ROOM,
OPCODE_SAVE_ACTION,
OPCODE_CLEAR_LINE,
OPCODE_MOVE_TO_ROOM,
OPCODE_VAR_ADD,
OPCODE_SET_ROOM_DESCRIPTION,

View File

@ -188,16 +188,14 @@ void ComprehendGameOpcodes::execute_opcode(const Instruction *instr, const Sente
break;
case OPCODE_SAVE_ACTION:
/*
* FIXME - This saves the current verb and allows the next
* command to use just the noun. This is used to allow
* responses to ask the player what they meant, e.g:
*
* > drop
* I don't understand what you want to drop.
* > gun
* Okay.
*/
// Causes the next sentence inputed to re-use the first word of the current one.
// As far as I'm aware, this is only used for handling responses to rhethorical questions
_nounState = NOUNSTATE_QUERY;
// fall-through
case OPCODE_CLEAR_LINE:
// Resets the input line, removing any pending further actions that were specified
// TODO: Make input line a class field, and reset it here
break;
case OPCODE_SET_CAN_TAKE:
@ -394,6 +392,7 @@ ComprehendGameV1::ComprehendGameV1() {
_opcodeMap[0x85] = OPCODE_MOVE_TO_ROOM;
_opcodeMap[0x86] = OPCODE_VAR_ADD;
_opcodeMap[0x87] = OPCODE_SET_ROOM_DESCRIPTION;
_opcodeMap[0x88] = OPCODE_CLEAR_LINE;
_opcodeMap[0x89] = OPCODE_MOVE_OBJECT_TO_CURRENT_ROOM;
_opcodeMap[0x8a] = OPCODE_VAR_SUB;
_opcodeMap[0x8b] = OPCODE_SET_OBJECT_DESCRIPTION;
@ -696,6 +695,7 @@ ComprehendGameV2::ComprehendGameV2() {
_opcodeMap[0x85] = OPCODE_MOVE_TO_ROOM;
_opcodeMap[0x86] = OPCODE_VAR_ADD;
_opcodeMap[0x87] = OPCODE_SET_ROOM_DESCRIPTION;
_opcodeMap[0x88] = OPCODE_CLEAR_LINE;
_opcodeMap[0x89] = OPCODE_SPECIAL;
_opcodeMap[0x8a] = OPCODE_VAR_SUB;
_opcodeMap[0x8c] = OPCODE_MOVE_DEFAULT;