root/ggpa/GameWorld.cpp

Revision 1, 31.8 kB (checked in by pantley2, 4 years ago)

GGPA code from the good old days of SIGART

Line 
1 /*
2  * GameWorld.cpp
3  * Implementation of GameWorld class
4  */
5
6 #include "GameWorld.h"
7 #include "VariableAssignmentIterator.h"
8 #include <string>
9 #include <stdlib.h>
10 #include <math.h>
11 #include <iostream>
12 #include <sstream>
13 using namespace std;
14
15 #define START_KEYWORD "START"
16 #define START_KEYWORD_LENGTH 5
17 #define SPACE_CHARS " \t\n"
18 #define END_CHARS ") \t\n"
19 #define LEADING_CHARS " \t\n"
20 #define TERMINAL_NAME "terminal"
21 #define GOAL_NAME "goal"
22 #define LEGAL_NAME "legal"
23 #define NEXT_NAME "next"
24 #define TRUE_NAME "true"
25 #define DOES_NAME "does"
26 #define NOT_NAME "not"
27 #define OR_NAME "or"
28 #define INIT_TAG "init"
29 #define ROLE_TAG "role"
30 #define DATALOG_RULE_TAG "<="
31 // DISTINCT_NAME defined in Sentence.h
32 #define DEFAULT_REWARD 0
33
34
35 /*
36  * Constructor
37  * Parameters:   rules - string to define rules to create a new GameWorld
38  * No return type
39  * Uses the rules to initialize the GameWorld
40  */
41 GameWorld::GameWorld(const string& rules) : roles(), sentenceStructures(), initialSentences(), initialState(NULL), dependencyGraph(), currentState(NULL), goals(), legalMoveRules(), definitions() {
42     initializeFields();
43     parse(rules);
44 }
45
46
47 /*
48  * Copy Constructor
49  * Initializes this to be a copy of the original GameWorld.
50  */
51 GameWorld::GameWorld(const GameWorld& oldWorld) {
52     // right now we are sharing most of the data.  We may need to
53     // change this later.
54     roles = oldWorld.roles;
55     sentenceStructures = oldWorld.sentenceStructures;
56     initialSentences = oldWorld.initialSentences;
57     initialState = oldWorld.initialState;
58     dependencyGraph = oldWorld.dependencyGraph;
59     goals = oldWorld.goals;
60     legalMoveRules = oldWorld.legalMoveRules;
61     definitions = oldWorld.definitions;
62    
63     // independent copies
64     currentState = new State(*(oldWorld.currentState));
65
66 }
67
68 /*
69  * operator=
70  * Sets this to be a copy of the original GameWorld
71  */
72 GameWorld& GameWorld::operator=(const GameWorld& oldWorld) {
73     if (this == &oldWorld) {
74         delete currentState;
75         currentState = NULL;
76
77         roles = oldWorld.roles;
78         sentenceStructures = oldWorld.sentenceStructures;
79         initialSentences = oldWorld.initialSentences;
80         initialState = oldWorld.initialState;
81         dependencyGraph = oldWorld.dependencyGraph;
82         goals = oldWorld.goals;
83         legalMoveRules = oldWorld.legalMoveRules;
84         definitions = oldWorld.definitions;
85    
86         // independent copies
87         currentState = new State(*(oldWorld.currentState));
88        
89     }
90
91     return *this;
92 }
93
94 /*
95  * Deconstructor
96  * Frees up the memory.
97  */
98 GameWorld::~GameWorld() {
99     delete currentState;
100     currentState = NULL;
101
102 }
103
104 /*
105  * parse
106  * Parameters:   rules - string containing the rules
107  * Return value: none
108  * Parses rules to create a GameWorld that we can use
109  */
110 void GameWorld::parse(const string& rules){
111     // better implementation
112     vector<string> tokens = tokenize(rules);
113     /*
114     for (unsigned int i =0; i<tokens.size(); i++)
115       cout<<tokens[i]<<endl;
116     */
117     if (tokens.size() != 6) {
118         cerr << "Incorrect number of arguments in the rules" << endl;
119         cerr << tokens.size() << " instead of " << 6 << endl;
120         exit(1);
121     }
122
123     matchID = tokens[1];
124     role = tokens[2];
125     parseRules(tokens[3]);
126     startClock = atof(tokens[4].c_str());
127     playClock = atof(tokens[5].c_str());
128    
129     findLegalMoves();
130    
131     return;
132 }
133
134 /*
135  * getMatchID
136  * No parameters
137  * Return type: string
138  * Returns the match id for this game
139  */
140 string GameWorld::getMatchID() {
141     return matchID;
142 }
143
144 /*
145  * getRole
146  * No parameters
147  * Return type: string
148  * Returns the role of this program in the game
149  */
150 string GameWorld::getRole() {
151     return role;
152 }
153
154 /*
155  * getRoles
156  * Parameters: none
157  * Return type: a vector of strings
158  * Returns all roles in this game.
159  */
160 const vector<string>& GameWorld::getRoles() const {
161     return roles;
162 }
163
164 /*
165  * getStartClock
166  * No parameters
167  * Return type: double
168  * Returns the time available for learning before the match starts.
169  *   This time will be in *minutes*
170  */
171 double GameWorld::getStartClock() {
172     return startClock;
173
174 }
175
176 /*
177  * getPlayClock
178  * No parameters
179  * Return type: double
180  * Returns the time available to make each move during the match.  This
181  *    time will be in *seconds*
182  */
183 double GameWorld::getPlayClock() {
184     return playClock;
185 }
186
187 /*
188  * update
189  * Parameters: actions - a string containing a list of the actions
190  *                       taken by the other players
191  * No Return type
192  * Updates the game state for a new turn.
193  */
194 void GameWorld::update(string actions) {
195     vector<string> tokens = tokenize(actions);
196    
197     if (tokens.size() != roles.size()) {
198         cerr << "Wrong number of actions recieved: " << tokens.size()
199              << " instead of " << roles.size() << endl;
200     }
201
202     vector<Action*> currentActions;
203     for (unsigned int player = 0; player < roles.size(); player++) {
204         currentActions.push_back(parseAction(tokenize(tokens[player]),
205                                              roles[player],
206                                              true));
207     }
208
209     update(currentActions);
210 }
211
212 /*
213  * getLegalMoves
214  * Parameters: none
215  * Return type: a vector of Action pointers
216  * Returns a set of legal moves for the default player.
217  */
218 vector<Action*> GameWorld::getLegalMoves() const {
219     return getLegalMoves(role);
220 }
221
222 /*
223  * getLegalMoves
224  * Parameters: player - the player to get the actions for
225  * Return type: a vector of Action pointers
226  * Returns a set of legal moves for the player.  If the player does
227  * not exist in the game, it will return an empty vector
228  */
229 vector<Action*> GameWorld::getLegalMoves(string player) const {
230     vector<Action*> moves;
231     for (unsigned int index = 0; index < legalMoves.size(); index++) {
232         if (legalMoves[index]->getActor() == player) {
233             moves.push_back(legalMoves[index]);
234         }
235     }
236     return moves;
237 }
238
239 /*
240  * parseRules
241  * Parameters:   rules - string containing the rules of the game
242  *               start - place to start parsing the rules
243  * Return value: int - the index of the last letter in the rules
244  * Parses the rules from the string and puts them into the class fields,
245  *   returning the last index used
246  */
247 int GameWorld::parseRules(const string& rules) {
248     //cout << rules << endl;
249   vector<string> ruleTokens = tokenize(rules);
250   unsigned int i;
251   for (i = 0; i < ruleTokens.size(); i++){
252       //cout << ruleTokens[i] << endl;
253     parseRule(ruleTokens[i]);
254   }
255
256   // initialize the state
257   //output();
258   fillInValues();
259   initializeState();
260  
261   return i;
262 }
263
264 /*
265  * parseRule
266  * Parameters:   rule - a string containing a single rule to be parsed
267  * Return value: none
268  * Parses the rule into the GameWorld
269  */
270 void GameWorld::parseRule(const string& rule) {
271     vector<string> tokens = tokenize(rule);
272    
273     //cout << rule << endl;
274     /*
275     for (unsigned int token = 0; token < tokens.size(); token++) {
276         cout << tokens[token] << endl;
277     }
278     */
279     if (tokens.size() == 0) {
280         // empty rule - do nothing
281         return;
282     }
283     string firstWord = tokens[0];
284
285     if (firstWord == "") {
286         // empty rule
287         return;
288     } else if (firstWord == INIT_TAG) {
289         parseInit(rule);
290     } else if (firstWord == ROLE_TAG) {
291         parseRole(rule);
292     } else if (firstWord == DATALOG_RULE_TAG) {
293         parseDatalogRule(rule);
294     } else {
295         cerr << "Invalid rule: " << rule << endl;
296         cerr << "First word is invalid: " << firstWord << endl;
297         exit(1);
298     }
299
300     return;
301 }
302
303
304
305 string GameWorld::getFirstWord(string rule) const {
306     string firstWord;
307     unsigned int stop = rule.find(" ", 0);
308    
309     if (stop == string::npos) {
310         // assume empty rule
311         return "";
312     }
313
314     firstWord = rule.substr(0, stop);
315     return firstWord;
316 }
317
318 vector<string> GameWorld::tokenize(string line) const {
319     vector<string> tokens;
320    
321     // get the start of the first word
322     unsigned int start = line.find_first_not_of(LEADING_CHARS, 0);
323     if (line[start] == '(') {
324         // ignore the first parenthesis, assuming that the closing parenthesis
325         // is at the end of the string
326         start = line.find_first_not_of(LEADING_CHARS, start+1);
327     }
328     unsigned int stop = start;
329     unsigned int length = line.length();
330
331     // find all the words
332     while(start != string::npos) {
333         if (line[start] == '(') {
334             int depth = 1;
335             stop = start;
336             while(depth > 0) {
337                 stop = line.find_first_of("()", stop + 1);
338                 if (stop == string::npos) {
339                     cerr << "Mismatched parenthesis on line " << line << endl;
340                     exit(1);
341                 } else if (line[stop] == '(') {
342                     depth++;
343                 } else { // line[stop] == ')'
344                     depth--;
345                 }
346             }
347             stop = line.find_first_of(SPACE_CHARS, stop);
348         } else {
349             stop = line.find_first_of(END_CHARS, start);
350         }
351        
352         if (stop == string::npos) {
353             tokens.push_back(line.substr(start, length-start));
354             return tokens;
355         } else {
356             tokens.push_back(line.substr(start, stop-start));
357             start = line.find_first_not_of(END_CHARS, stop);
358         }
359
360     }
361
362     return tokens;
363    
364 }
365
366 void GameWorld::parseInit(string rule) {
367     vector<string> tokens = tokenize(rule);
368     if (tokens.size() != 2) {
369         cerr << "Wrong number of values in init rule" << endl;
370     }
371
372     Sentence* sentence = parseSentence(tokenize(tokens[1]));
373     initialSentences.push_back(sentence);
374     return;
375 }
376    
377 void GameWorld::parseRole(string rule) {
378     vector<string> tokens = tokenize(rule);
379     if (tokens.size() != 2) {
380         cerr << "Wrong number of values for role rule" << endl;
381         exit(1);
382     }
383     roles.push_back(tokens[1]);
384     return;
385 }
386
387 void GameWorld::parseDatalogRule(string rule) {
388     vector<string> tokens = tokenize(rule);
389     if (tokens.size() <= 2) {
390         cerr << "There are not enough terms in the datalog rule " << rule
391              << endl;
392         exit(1);
393     }
394    
395     // parse the head of the rule
396     Sentence* head = parseHead(tokens[1]);
397
398     // parse the body of the rule
399     for (unsigned int token = 2; token < tokens.size(); token++) {
400         // parse the token
401         parseBody(tokens[token], head);
402
403        
404     }
405
406     return;
407 }
408
409
410 /*
411  * parseHead
412  * Parameters:  headString - a string containing a text representation of
413  *                           the head for a rule
414  * Return type: Sentence pointer
415  * Returns the Sentence corresponding to the head
416  */
417 Sentence* GameWorld::parseHead(string headString) {
418     vector<string> tokens = tokenize(headString);
419     Sentence* head;
420
421     if (tokens[0] == NEXT_NAME) {
422         head = parseSentence(tokenize(tokens[1]));
423         updateRules.push_back(head);
424     } else if (tokens[0] == LEGAL_NAME) {
425         Action* action = parseAction(tokenize(tokens[2]), tokens[1]);
426         legalMoveRules.push_back(action);
427         head = action;
428         /*
429         head = parseSentence(tokenize(tokens[2]));
430         pair<string, Sentence*> thePair(tokens[1], head);
431         legalMoves.push_back(thePair);
432         */
433     } else if (tokens[0] == TERMINAL_NAME) {
434         if (sentenceStructures[TERMINAL_NAME] == NULL) {
435             cerr << "Terminal sentence structure is NULL!" << endl;
436             exit(1);
437         }
438         head = new Sentence(vector<string>(0),
439                             sentenceStructures[TERMINAL_NAME]);
440     } else if (tokens[0] == GOAL_NAME) {
441         head = parseSentence(tokens);
442         goals.push_back(head);
443         definitions.push_back(head);
444     } else { // a definition
445         head = parseSentence(tokens);
446         definitions.push_back(head);
447     }
448
449     return head;
450 }
451
452 /*
453  *parseSentence
454  *Parameters: tokens - a vector<string> containing in its first index the name of the sentence and the rest of them are the parameters of the sentence
455  * Return type: Sentence pointer
456  * Returns the parsed version of the sentence
457  */
458 Sentence* GameWorld::parseSentence(vector<string> tokens) {
459      SentenceStructure* structure = updateSentenceStructure(tokens, false);
460    
461     // get rid of the name
462     tokens.erase(tokens.begin());
463
464     return new Sentence(tokens, structure);
465 }
466
467 /*
468  * parseAction
469  * Parameters: tokens - a vector<string containing in its first index the
470  *                      name of the action, and the rest are the parameters
471  *                      of the action
472  *             actor - the agent who performs this action
473  * Return type: Action*
474  * Returns the parsed version of the action
475  */
476 Action* GameWorld::parseAction(vector<string> tokens, string actor,
477                                bool inGame) {
478     SentenceStructure* structure;
479     if (!inGame) {
480         structure = updateSentenceStructure(tokens, true);
481     } else {
482         if (checkSentenceStructure(tokens, true) == false) {
483             cerr << "Action did not match expectations" << endl;
484             exit(1);
485         }
486     }
487     //cout << "Action name: " << tokens[0] << endl;
488     // get rid of name
489     tokens.erase(tokens.begin());
490
491     return new Action(tokens, structure, actor, roles);
492 }
493
494  /*
495   *updateSentenceStructure
496   *Parameters: tokens - a vector<string> passed by parseSentence
497   *Return type: a SentenceStructure pointer
498   *Returns the new structure of the sentence after it has been updated
499   */
500 SentenceStructure* GameWorld::updateSentenceStructure(vector<string> tokens, bool isAction)
501  {
502      string name = tokens[0];
503      
504      // get the SentenceStructure
505      SentenceStructure* structure;
506      if (sentenceStructures.find(name) == sentenceStructures.end()) {
507          // create a new SentenceStructure
508          structure = new SentenceStructure(name, tokens.size()-1, isAction);
509          sentenceStructures[name] = structure;
510      } else {
511          structure = sentenceStructures[name];
512      }
513
514      // update each parameter
515      if (structure->getNumParameters() != tokens.size()-1) {
516          cerr << "Wrong number of parameters" << endl;
517          exit(1);
518      }
519
520      for (unsigned int parameter = 0; parameter < tokens.size()-1;
521           parameter++) {
522          if (!isVariable(tokens[parameter+1])) {
523              structure->addValue(parameter, tokens[parameter+1]);
524          }
525      }
526
527      if (structure == NULL) {
528          cerr << "NULL structure?! Structure: " << name << endl;
529      }
530      return structure;
531
532  } 
533
534 /*
535  * parseBody
536  * Parameters:  body - a string containing one component of the body of the
537  *                     rule
538  *              head - a Sentence that is the head of this rule
539  * No return type
540  * Parses this piece of the body, and adds it as a dependency to the head
541  */
542 void GameWorld::parseBody(string body, Sentence* head) {
543    
544     vector<string> tokens = tokenize(body);
545
546     if (tokens[0] == TRUE_NAME) {
547         // second parameter is a sentence
548         Sentence* sentence = parseSentence(tokenize(tokens[1]));
549         head->addAndDependency(sentence, false);
550     } else if (tokens[0] == DOES_NAME) {
551         if (tokens.size() != 3) {
552             cerr << "Inproper use of 'does' - wrong number of arguments" << endl;
553             exit(1);
554         }
555
556         string actor = tokens[1];
557        
558         Action* action = parseAction(tokenize(tokens[2]), actor);
559        
560         head->addAndDependency(action, false);
561        
562     } else if (tokens[0] == NOT_NAME) {
563         if (tokens.size() != 2) {
564             cerr << "Inproper use of 'not' - wrong number of arguments" << endl;
565             exit(1);
566         }
567         vector<string> subTokens = tokenize(tokens[1]);
568         if (subTokens[0] == OR_NAME) {
569             if (subTokens.size() < 2) {
570                 cerr << "Inproper use of 'or' - wrong number of arguments" << endl;
571                 exit(1);
572             }
573             vector<Sentence*> dependency;
574             for (unsigned int token = 1; token < subTokens.size(); token++) {
575                 dependency.push_back(parseSentence(tokenize(subTokens[token])));
576             }
577             head->addOrDependency(dependency, true);
578         } else {
579
580             Sentence* sentence = parseSentence(subTokens);
581             head->addAndDependency(sentence, true);
582         }
583     } else if (tokens[0] == OR_NAME) {
584         if (tokens.size() < 2) {
585             cerr << "Inproper use of 'or' - wrong number of arguments" << endl;
586             exit(1);
587         }
588         vector<Sentence*> dependency;
589         for (unsigned int token = 1; token < tokens.size(); token++) {
590             dependency.push_back(parseSentence(tokenize(tokens[token])));
591         }
592         head->addOrDependency(dependency, true);
593     } else { 
594         // this dependency just does not have "true" in the front
595         Sentence* sentence = parseSentence(tokens);
596         head->addAndDependency(sentence, false);
597     }
598
599
600 }
601
602
603
604 /*
605  * initializeFields
606  * No parameters or return type
607  * Initializes the appropriate fields for this class
608  */
609 void GameWorld::initializeFields() {
610     // create any constant structures
611     SentenceStructure* terminal
612         = new SentenceStructure(TERMINAL_NAME, 0, false);
613     if (terminal == NULL) {
614         cerr << "Terminal state was not created correctly!" << endl;
615     }
616     sentenceStructures[TERMINAL_NAME] = terminal;
617    
618     SentenceStructure* goal = new SentenceStructure(GOAL_NAME, 2, false);
619     sentenceStructures[GOAL_NAME] = goal;
620
621     SentenceStructure* distinct = new SentenceStructure(DISTINCT_NAME, 2, false);
622     sentenceStructures[DISTINCT_NAME] = distinct;
623
624 }
625
626 /*
627  * function that prints out everything, for "testing"
628  */
629 void GameWorld::output() const {
630     map<string, SentenceStructure*>::const_iterator printItr = sentenceStructures.begin();
631     cout << sentenceStructures.size() << " Sentence Structures: " << endl;
632     for (; printItr != sentenceStructures.end(); printItr++) {
633         //cout << "Structure name: " << printItr->first << endl;
634         printItr->second->print();
635         cout << endl;
636     }
637     cout << endl;
638    
639     // print update rules
640     cout << updateRules.size() << " Update rules" << endl;
641     vector<Sentence*>::const_iterator ruleItr = updateRules.begin();
642     for (; ruleItr != updateRules.end(); ruleItr++) {
643         //cout << (*ruleItr)->getName() << endl;
644         (*ruleItr)->print();
645         cout << endl;
646     }
647     cout << endl;
648
649     // print definitions
650     cout << definitions.size() << " definitions" << endl;
651     for (ruleItr = definitions.begin(); ruleItr != definitions.end();
652          ruleItr++) {
653         (*ruleItr)->print();
654         cout << endl;
655     }
656     cout << endl;
657
658     // print goal states
659     cout << goals.size() << " goal" << endl;
660     for (ruleItr = goals.begin(); ruleItr != goals.end();
661          ruleItr++) {
662         (*ruleItr)->print();
663         cout << endl;
664
665     }
666     cout << endl;
667
668     // print initial sentences
669     cout << initialSentences.size() << " initialSentences" << endl;
670     for (ruleItr = initialSentences.begin(); ruleItr != initialSentences.end();
671          ruleItr++) {
672         (*ruleItr)->print();
673         cout << endl;
674
675     }
676     cout << endl;
677
678
679     // print legal move rules
680     vector<Action*>::const_iterator actionItr;
681     cout << legalMoveRules.size() << " legal moves" << endl;
682     for (actionItr = legalMoveRules.begin(); actionItr != legalMoveRules.end();
683          actionItr++) {
684         (*actionItr)->print();
685         cout << endl;
686     }
687     cout << endl;
688 }
689
690 /*
691  * checkSentenceStructure
692  * Parameters: tokens - a vector of strings containing the tokens for
693  *                      this sentence
694  *             isAction - a boolean that is true if the sentence should
695  *                        be an action, and false otherwise
696  * Return type: bool
697  * Returns true if the Sentence is legal in the rules, and false
698  * otherwise
699  */
700 bool GameWorld::checkSentenceStructure(vector<string> tokens,
701                                        bool isAction) {
702     string name = tokens[0];
703    
704     if (sentenceStructures.find(name) == sentenceStructures.end()) {
705         return false;
706     }
707
708     SentenceStructure* structure = sentenceStructures[name];
709
710     if (tokens.size() - 1 != structure->getNumParameters()) {
711         return false;
712     }
713
714     for (unsigned int token = 1; token < tokens.size(); token++) {
715         if (structure->getValueIndex(token - 1, tokens[token]) == -1) {
716             return false;
717         }
718     }
719
720     return true;
721 }
722
723
724 /*
725  * update
726  * Parameters: currentActions - a vector of actions containing the actions
727  *                              taken by players previously.
728  * No return type
729  * Updates the game state based on the actions taken, and the current
730  * state.
731  */
732 void GameWorld::update(vector<Action*> currentActions){
733    
734     State* newState = new State(currentState->getSize());
735    
736     // check the update rules
737     for (unsigned int updateRule = 0; updateRule < updateRules.size();
738          updateRule++) {
739         applyUpdateRule(updateRules[updateRule], newState, currentActions);
740     }
741
742
743     // run through the definitions until we get everything
744     applyDefinitions(currentState);
745    
746     findLegalMoves();
747 }
748
749
750 void GameWorld::applyUpdateRule(Sentence* updateRule, State* state,
751                                 vector<Action*> currentActions) {
752     applyRule(updateRule, state, currentState, currentActions);
753 /*
754     map<string, vector<string> > variables = updateRule->getVariables();
755
756
757     // for each variable assignment
758     VariableAssignmentIterator assignmentItr(variables);
759     for (;!assignmentItr.atEnd(); assignmentItr++) {
760         map<string,string> assignment = assignmentItr.getCurrent();
761         
762         // get the sentence with this assignment
763         Sentence* sentence = updateRule->getAtomicSentence(assignment);
764
765         // check each of the dependencies to see if they are satisfied.
766         vector<vector<Sentence*> > dependencies = sentence->getDependencies();
767         bool allSatisfied = true;
768         for (unsigned int dependencyIndex = 0;
769              dependencyIndex < dependencies.size();
770              dependencyIndex++) {
771             vector<Sentence*> dependency = dependencies[dependencyIndex];
772             bool satisfied = false;
773             for (unsigned int subIndex = 0;
774                  !satisfied && subIndex < dependency.size();
775                  subIndex++) {
776                 if (dependency[subIndex]->getStructure()->isAction()) {
777                     for (unsigned int actionIndex = 0;
778                          actionIndex < currentActions.size(); actionIndex++) {
779                         if (currentActions[actionIndex] == dependency[subIndex]) {
780                             satisfied = true;
781                             break;
782                         }
783                     }
784                 } else {
785                     if (currentState->containsSentence(dependency[subIndex])) {
786                         satisfied = true;
787                     }
788                 }
789             }
790             if (!satisfied) {
791                 allSatisfied = false;
792             }
793         }
794         if (allSatisfied) {
795             state->addSentence(sentence);
796         }
797
798
799
800         // release the sentence
801         delete sentence;
802     }
803 */
804 }
805
806 /**
807  * applyDefinitions
808  * Parameters: state - the state that we are building
809  * No return type
810  * Runs through the definitions and adds any applicable properties
811  * to the state
812  */
813 void GameWorld::applyDefinitions(State* state) {
814     State lastState;
815     do {
816         lastState = *state;
817         for (unsigned int definitionIndex = 0;
818              definitionIndex < definitions.size();
819              definitionIndex++) {
820             applyDefinition(definitions[definitionIndex], state);
821         }
822     }
823     while (!(lastState == *state));
824 }
825
826 /*
827  * applyDefinition
828  * Parameters: definition - the current definition
829  *             state - where to apply the definition
830  * Return type: none
831  * Applies the definition to the current state.
832  */
833 void GameWorld::applyDefinition(Sentence* definition, State* state) {
834     vector<Action*> emptyActions;
835     applyRule(definition, state, state, emptyActions);
836 }
837
838 /**
839  * applyRule
840  * Parameters: rule - the rule to apply: sentence with dependencies
841  *             newState - the state to write the new rule to
842  *             oldState - the state to get information from
843  *             currentActions - a set of the most recent actions
844  * Return type: none
845  * Applies the rule to the newState given the oldState and the
846  * current actions.
847  */
848 void GameWorld::applyRule(Sentence* rule, State* newState, State* oldState,
849                           vector<Action*> currentActions) {
850     map<string, vector<string> > variables = rule->getVariables();
851
852
853     // for each variable assignment
854     VariableAssignmentIterator assignmentItr(variables);
855     for (;!assignmentItr.atEnd(); assignmentItr.next()) {
856         map<string,string> assignment = assignmentItr.getCurrent();
857        
858         // get the sentence with this assignment
859         Sentence* sentence = rule->getAtomicSentence(assignment);
860
861         if (areDependenciesSatisfied(sentence, oldState)) {
862             newState->addSentence(sentence);
863         }
864
865
866
867         // release the sentence
868         delete sentence;
869     }
870 }
871
872 /**
873  * initializeState
874  * No parameters or return type
875  * Using the discovered sentence structures, get the appropriate size
876  * for a state and initialize initialState and currentState appropriately
877  */
878 void GameWorld::initializeState() {
879     int total = 0;
880     // initialize state structure
881     map<string, SentenceStructure*>::iterator structureItr;
882     for (structureItr = sentenceStructures.begin();
883          structureItr != sentenceStructures.end(); structureItr++) {
884         SentenceStructure* structure = structureItr->second;
885         if (!structure->isAction() && structure->getName() != DISTINCT_NAME) {
886             structure->setOffset(total);
887             total += structure->numPossibleSentences();
888         }
889     }
890
891     initialState = new State(total);
892     //cout << "Adding " << initialSentences.size() << " initial sentences"
893     //     << endl;
894     // get all of the sentences in the initial state
895     for (unsigned int initialSentence = 0;
896          initialSentence < initialSentences.size(); initialSentence++) {
897         //cout << "Initial sentence " << initialSentence
898         //     << "/" << initialSentences.size() << endl;
899         vector<Sentence*> sentences
900             = initialSentences[initialSentence]->getAtomicSentences();
901         for (unsigned int index = 0; index < sentences.size(); index++) {
902             //cout << "Adding Sentence" << endl;
903             initialState->addSentence(sentences[index]);
904         }
905        
906     }
907     //initialState->print();
908     // apply the definitions here
909     applyDefinitions(initialState);
910     //initialState->print();
911     //cout << endl;
912     currentState = new State(*initialState);
913     //currentState->print();
914 }
915
916 /**
917  * findLegalMoves
918  * No parameters or return types
919  * Finds all the legal moves for the current state
920  */
921 void GameWorld::findLegalMoves() {
922     vector<Action*> actions;
923     for (unsigned int index = 0; index < legalMoveRules.size(); index++) {
924         applyLegalMoveRule(legalMoveRules[index], actions);
925     }
926    
927     // clear the old legal moves
928     for (unsigned int index = 0; index < legalMoves.size(); index++) {
929         delete legalMoves[index];
930         legalMoves[index] = NULL;
931     }
932    
933     legalMoves = actions;
934 }
935
936 /*
937  * applyLegalMoveRule
938  * Parameters: rule - the rule to apply
939  *             actions - a reference to a vector of actions where any
940  *                       new legal moves should be stored
941  * No return type
942  * Applies the rule and puts any legal moves that are found in the
943  * actions vector.
944  */
945 void GameWorld::applyLegalMoveRule(Action* rule, vector<Action*>& actions) {
946     rule->getDependencies();
947     map<string, vector<string> > variables = rule->getVariables();
948
949
950     // for each variable assignment
951     VariableAssignmentIterator assignmentItr(variables);
952     for (;!assignmentItr.atEnd(); assignmentItr.next()) {
953         map<string,string> assignment = assignmentItr.getCurrent();
954        
955         // get the sentence with this assignment
956         Action* action = rule->getAtomicAction(assignment);
957
958         if (areDependenciesSatisfied(action, currentState)) {
959             actions.push_back(action);
960         }
961
962         // release the sentence
963         delete action;
964     }
965 }
966
967
968 /*
969  * getState
970  * No parameters.
971  * Returns the current state for this GameWorld
972  */
973 State* GameWorld::getState() const {
974     State* state = new State(*currentState);
975     return state;
976 }
977
978 /*
979  * isDone
980  * Parameters: none
981  * Return type: bool
982  * Returns true if the game has reached a terminal state, and false
983  * otherwise.
984  */
985 bool GameWorld::isDone() {
986     vector<string> values;
987     SentenceStructure* structure = sentenceStructures[TERMINAL_NAME];
988     Sentence* terminal
989         = new Sentence(values, structure);
990
991     return currentState->containsSentence(terminal);
992 }
993
994 /*
995  * startGame
996  * No parameters or return type
997  * Initializes the GameWorld for a new game
998  */
999 void GameWorld::startGame() {
1000     delete currentState;
1001     currentState = initialState;
1002     findLegalMoves();
1003 }
1004
1005
1006 /*
1007  * getReward
1008  * Parameters: curRole - the role we are interested in
1009  * Return type: int
1010  * Returns the reward for the current state.  No goal is satisfied,
1011  * it returns the default value.
1012  */
1013 int GameWorld::getReward(string curRole) const {
1014     for (unsigned int goalNum = 0; goalNum < goals.size(); goalNum++) {
1015         Sentence* goal = goals[goalNum];
1016         if ((*goal)[0] == curRole && currentState->containsSentence(goal)) {
1017             istringstream buffer((*goal)[1]);
1018             int reward;
1019             buffer >> reward;
1020             return reward;
1021         }
1022     }
1023
1024     // NOTE: We might want to change how this is handled.
1025     return DEFAULT_REWARD;
1026 }
1027
1028
1029 /*
1030  * areDependenciesSatified
1031  * Parameters: rule - the Sentence* rule to check
1032  *             state - the State to look for dependencies in
1033  * Return type: bool
1034  * Returns true if all of the dependencies for the rule are satisfied,
1035  * and false otherwise.
1036  */
1037 bool GameWorld::areDependenciesSatisfied(Sentence* rule, State* state) {
1038     // check each of the dependencies to see if they are satisfied.
1039     /* can't do this for an action
1040     if (state->containsSentence(rule)) {
1041         // it does not need to be added again, so return false
1042         // NOTE: is this the best action?
1043         return false;
1044     }
1045     */
1046     vector<vector<Sentence*> > dependencies = rule->getDependencies();
1047     bool allSatisfied = true;
1048     for (unsigned int dependencyIndex = 0;
1049          dependencyIndex < dependencies.size();
1050          dependencyIndex++) {
1051         vector<Sentence*> dependency = dependencies[dependencyIndex];
1052         bool satisfied = false;
1053         for (unsigned int subIndex = 0;
1054              !satisfied && subIndex < dependency.size();
1055              subIndex++) {
1056             if (isDependencySatisfied(dependency[subIndex], state)) {
1057                 satisfied = true;
1058             }
1059                
1060         }
1061         bool negated = rule->isDependencyNegated(dependencyIndex);
1062         if ((!satisfied && !negated) || (satisfied && negated)) {
1063             allSatisfied = false;
1064         }
1065     }
1066    
1067     return allSatisfied;
1068 }
1069
1070 /*
1071  * isDependencySatisfied
1072  * Parameters: dependency - the Sentence* to check
1073  *             state - the state in which to check if the dependency is
1074  *                     satisfied
1075  * Return type: bool
1076  * Returns true if the dependency is satisfied in this state, and false
1077  * otherwise
1078  */
1079 bool GameWorld::isDependencySatisfied(Sentence* dependency, State* state) {
1080     if (dependency->getName() == DISTINCT_NAME) {
1081         if ((*dependency)[0] != (*dependency)[1]) {
1082             return true;
1083         } else {
1084             return false;
1085         }
1086     }
1087     if (state->containsSentence(dependency)) {
1088         return true;
1089     }
1090
1091     return false;
1092 }
1093
1094
1095 /*
1096  * fillInValues
1097  * No parameters or return type
1098  * fills in missing values in the sentence structures
1099  */
1100 void GameWorld::fillInValues() {
1101     for (unsigned int index = 0; index < updateRules.size(); index++) {
1102         updateRules[index]->mergeValues();
1103     }
1104    
1105     for (unsigned int index = 0; index < legalMoveRules.size(); index++) {
1106         legalMoveRules[index]->mergeValues();
1107     }
1108    
1109     for (unsigned int index = 0; index < definitions.size(); index++) {
1110         definitions[index]->mergeValues();
1111     }
1112    
1113 }
Note: See TracBrowser for help on using the browser.