📄 readefg.cc
字号:
//// $Source: /home/gambit/CVS/gambit/sources/game/readefg.cc,v $// $Date: 2002/08/26 05:50:10 $// $Revision: 1.4 $//// DESCRIPTION:// Parser for reading extensive form savefiles//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//#include <stdlib.h>#include <ctype.h>#include "base/base.h"#include "efg.h"//=========================================================================// Temporary representation classes//=========================================================================//// The following classes temporarily contain and organize the data// read in from a file:// class InfosetData// class OutcomeData// class NodeData// class PlayerData// class TreeData//class InfosetData {public: int m_number; gText m_name; gBlock<gText> m_actions; gBlock<gNumber> m_probs; InfosetData(void) : m_number(0), m_name("") { } void AddAction(const gText &p_action) { m_actions.Append(p_action); } void AddProb(const gNumber &p_prob) { m_probs.Append(p_prob); }};class OutcomeData {public: gText m_name; gBlock<gNumber> m_payoffs; OutcomeData(const gText &p_name) : m_name(p_name) { }};class NodeData {public: gText m_name; int m_player, m_infoset, m_outcome; InfosetData *m_infosetData; OutcomeData *m_outcomeData; NodeData *m_next; NodeData(void) : m_name(""), m_player(-1), m_infoset(-1), m_outcome(-1), m_infosetData(0), m_outcomeData(0), m_next(0) { } ~NodeData(); InfosetData *AddInfosetData(const gText &);};NodeData::~NodeData(){ if (m_infosetData) delete m_infosetData; if (m_outcomeData) delete m_outcomeData;} InfosetData *NodeData::AddInfosetData(const gText &m_infosetName){ m_infosetData = new InfosetData; m_infosetData->m_name = m_infosetName; return m_infosetData;}class DefinedInfosetData {public: int m_fileID; Infoset *m_infoset; DefinedInfosetData *m_next; DefinedInfosetData(void) : m_fileID(-1), m_infoset(0), m_next(0) { }};class PlayerData {public: gText m_name; DefinedInfosetData *m_firstInfoset, *m_lastInfoset; PlayerData *m_next; PlayerData(void); ~PlayerData(); void AddInfoset(int p_number, Infoset *p_infoset); Infoset *GetInfoset(int p_number);};PlayerData::PlayerData(void) : m_name(""), m_firstInfoset(0), m_lastInfoset(0), m_next(0){ }PlayerData::~PlayerData(){ DefinedInfosetData *infoset = m_firstInfoset; while (infoset) { DefinedInfosetData *nextInfoset = infoset->m_next; delete infoset; infoset = nextInfoset; }}void PlayerData::AddInfoset(int p_number, Infoset *p_infoset){ DefinedInfosetData *infoset = new DefinedInfosetData; infoset->m_fileID = p_number; infoset->m_infoset = p_infoset; if (m_firstInfoset) { m_lastInfoset->m_next = infoset; m_lastInfoset = infoset; } else { m_firstInfoset = infoset; m_lastInfoset = infoset; }}//// If information set p_number (as numbered in the savefile) has// been created, returns the pointer to the Infoset structure; otherwise,// returns null.//Infoset *PlayerData::GetInfoset(int p_number){ for (DefinedInfosetData *infoset = m_firstInfoset; infoset; infoset = infoset->m_next) { if (infoset->m_fileID == p_number) { return infoset->m_infoset; } } return 0;}class DefinedOutcomeData {public: int m_fileID; efgOutcome *m_outcome; DefinedOutcomeData(int p_number, efgOutcome *p_outcome) : m_fileID(p_number), m_outcome(p_outcome) { }};class TreeData {public: gText m_title; gText m_comment; PlayerData *m_firstPlayer, *m_lastPlayer, m_chancePlayer; NodeData *m_firstNode, *m_lastNode; gBlock<DefinedOutcomeData *> m_outcomes; TreeData(void); ~TreeData(); void AddPlayer(const gText &); NodeData *AddNode(const gText &, int, int); efgOutcome *GetOutcome(int p_number) const;};TreeData::TreeData(void) : m_title(""), m_comment(""), m_firstPlayer(0), m_lastPlayer(0), m_firstNode(0), m_lastNode(0){ }TreeData::~TreeData(){ if (m_firstPlayer) { PlayerData *player = m_firstPlayer; while (player) { PlayerData *nextPlayer = player->m_next; delete player; player = nextPlayer; } } if (m_firstNode) { NodeData *node = m_firstNode; while (node) { NodeData *nextNode = node->m_next; delete node; node = nextNode; } } for (int outc = 1; outc <= m_outcomes.Length(); outc++) { delete m_outcomes[outc]; }}void TreeData::AddPlayer(const gText &p_player){ PlayerData *player = new PlayerData; player->m_name = p_player; if (m_firstPlayer) { m_lastPlayer->m_next = player; m_lastPlayer = player; } else { m_firstPlayer = player; m_lastPlayer = player; }}NodeData *TreeData::AddNode(const gText &p_name, int p_player, int p_infoset){ NodeData *node = new NodeData; node->m_name = p_name; node->m_player = p_player; node->m_infoset = p_infoset; if (m_firstNode) { m_lastNode->m_next = node; m_lastNode = node; } else { m_firstNode = node; m_lastNode = node; } return node;}//// If outcome number p_number (as numbered in the savefile) has// been created, returns a pointer to the outcome;// otherwise, returns a null outcome//efgOutcome *TreeData::GetOutcome(int p_number) const{ for (int outc = 1; outc <= m_outcomes.Length(); outc++) { if (m_outcomes[outc]->m_fileID == p_number) { return m_outcomes[outc]->m_outcome; } } return 0;}//=========================================================================// Parser classes and static functions //=========================================================================//// These classes and functions are responsible for parsing the// savefile and building the temporary data structures//typedef enum { symINTEGER = 0, symDOUBLE = 1, symRATIONAL = 2, symTEXT = 3, symEFG = 4, symD = 5, symR = 6, symC = 7, symP = 8, symT = 9, symLBRACE = 10, symRBRACE = 11, symCOMMA = 12, symEOF = 13} SymbolSet;class ParserState {private: gInput &m_file; SymbolSet m_lastSymbol; double m_lastDouble; gInteger m_lastInteger; gRational m_lastRational; gText m_lastText;public: ParserState(gInput &p_file) : m_file(p_file) { } SymbolSet GetNextSymbol(void); SymbolSet GetCurrentSymbol(void) const { return m_lastSymbol; } const gInteger &GetLastInteger(void) const { return m_lastInteger; } const gRational &GetLastRational(void) const { return m_lastRational; } double GetLastDouble(void) const { return m_lastDouble; } gText GetLastText(void) const { return m_lastText; }}; class ParserError { };SymbolSet ParserState::GetNextSymbol(void){ char c = ' '; if (m_file.eof()) { return (m_lastSymbol = symEOF); } while (isspace(c)) { m_file.get(c); if (m_file.eof()) { return (m_lastSymbol = symEOF); } } if (c == 'c') { return (m_lastSymbol = symC); } if (c == 'D') { return (m_lastSymbol = symD); } if (c == 'E') { m_file.get(c); if (c == 'F') { m_file.get(c); if (c == 'G') { m_file.get(c); if (!isspace(c)) { throw ParserError(); } else { return (m_lastSymbol = symEFG); } } } throw ParserError(); } else if (c == 'p') { return (m_lastSymbol = symP); } else if (c == 'R') { return (m_lastSymbol = symR); } else if (c == 't') { return (m_lastSymbol = symT); } else if (c == '{') { return (m_lastSymbol = symLBRACE); } else if (c == '}') { return (m_lastSymbol = symRBRACE); } else if (c == ',') { return (m_lastSymbol = symCOMMA); } else if (isdigit(c) || c == '-') { gText buf; buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } if (c == '.') { buf += c; m_file.get(c); while (isdigit(c)) { buf += c; m_file.get(c); } m_file.unget(c); m_lastDouble = strtod((char *) buf, 0); return (m_lastSymbol = symDOUBLE); } else if (c == '/') {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -