// This may look like C code, but it is really -*- C++ -*-
//
//  Copyright (c) University of Aizu 1994
//


// Wrappers protect against including this file more than once

#ifndef Base_h
#define Base_h 1

//  This is the base class from which all objects in Monopoly 
//  are derived from. It defines the "read" and "write" operations,
//  and enforces the presense of "readContents", "writeContents" and
//  "className"

//  "classname" is used for 2 purposes:
//  1) It is necessary to know the classname in order to detect errors in
//     the input stream. Often, these "errors" are voluntary, since we want
//     to be able to read any objects. If we have a choice of objects to read,
//     we simply try reading the first type, if that fails try the next one
//     and so on... That way, we can read many more things than if did it
//     conventionally (e.g. by overloading >> and <<).

//  2) Since we want to avoid using templates, we have to do our own run-time
//     type checking for container classes. 

//  Classes are written out in the following format:
//
//      <className> <contents> <terminator>
//
//  <className> is an alphanumeric string followed by whitespaces.
//  <contents> depends on the derived classes. The virtual member function
// "readContents" is responsible for reading this part.
//  The whole thing is terminated by a terminator, currently set to "end".

//  The "read" operation is to be the inverse of the "write" operation.
//  The "read" operation will return "wrongObject" if the name in the 
//  input stream is not the one expected, and reposition the read pointer 
//  so that another "read" operation from a different object may be attempted.

//  In case of unexpected end of file or missing terminator, wrongData 
//  will be returned.

//  endOfFile is only returned when attempting to read a new object, and 
//  if the end of file is detected before having read any non-whitespace
//  characters.
//

#include <bool.h>

// We do a forward declaration of our global class "Game" here, because
// so many other classes use it. See "Game.h" for the full definition.
class Game;

enum IOstatus {
  ok,           // We have read in a well-formed object.
  endOfFile,    // We reached the end of file.
  wrongObject,  // We found something unexpected and unread it. Try again.
  wrongData     // The data cannot possibly be an object. Something's wrong.
};

IOstatus write(IOstatus s);  // All "enum" types should have a write function.

//  Rudimentary error handling:
void die(char *errorlocation);  // die a terrible death when 
                                // weird things happen...
void expected(char *something); // die a different death when 
                                // reading weird data...

//  Boolean type (the typedef is just for consistancy...)
typedef bool Bool;
IOstatus read(Bool &b);
IOstatus write(Bool const b);

typedef int Attempts; //  Special type for jail escape attempts
typedef int Price;    //  Special type for prices
typedef int Steps;    //  Special type for steps on the board
typedef int Remaining;//  Special type for remaining houses

IOstatus read(int &i);
IOstatus write(int const i);

//  further text IO utilities.
IOstatus read(char * &word);      // WARNING: this allocates space for text dynamically!
char *newString(char const *word); // creates a copy of word in a newly allocated space
IOstatus write(char const *word);
IOstatus writeln(char const *word = 0);
IOstatus writeEnd(void);

//  Number of houses on a property
enum Houses {none, oneHouse, twoHouses, threeHouses, fourHouses, hotel};
IOstatus read(Houses &h);
IOstatus write(Houses const h);

//  Size of monopolies, i.e. properties owned by the same player
enum GroupSize {all, one, two, three};
IOstatus read(GroupSize &g);
IOstatus write(GroupSize const g);

// Account states
enum AccountStatus {creditor, debitor};
IOstatus write(AccountStatus const s);

// Types of event cards
enum Deck {chance, community};
IOstatus read(Deck &t);
IOstatus write(Deck const t);

//  The "expect" function reads a word from the inputstream, compares it to
//  the argument, and if equal, returns "ok", otherwise "unreads" the word
//  and returns "wrongObject".

IOstatus expect(char const *something);
IOstatus expectEnd(void);

class Base {
public:
  Base(void) {}
  Base(Game* game);
  virtual ~Base(void) {}

  IOstatus read(void);
  IOstatus write(void) const;

  virtual IOstatus readContents(void) = 0;
  virtual IOstatus writeContents(void) const = 0;
  virtual char *classname(void) const = 0;

  Bool is(const char* name) const;
  void typeCheck(const Base& aBase) const;

  // Most objects will want to reference other objects in the game.
  // Therefore, all objects will know where to look. Note that we will
  // only allow member functions to access this.
protected:
  static Game* theGame;
};

// End of wrapper
#endif
// End of file
