/************************************************************************
       -= SEER - C-Scripting engine v 0.93a =-
State      : under implementation
Author     : Przemyslaw Podsiadly
             email: ppodsiad@elka.pw.edu.pl
             WWW:   http://home.elka.pw.edu.pl/~ppodsiad
File:excpp.cpp
Desc:script with C++ example: interaction between C++ and Script
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <seer.h>

#define MAN     0
#define WOMAN   1

#define NAMES_NUM       4
struct{
        char *name;
        int sex;
} names[NAMES_NUM]=
{{"Ian",MAN},
{"Iola",WOMAN},
{"Turlin",MAN},
{"Yenefer",WOMAN}};

//Our class, that the scripts access
class NPC{
        char name[64];
        int sex;
        int strength, wisdom, hp;
public:
        NPC(){
         srand(time(NULL));
         int n=rand()%NAMES_NUM;
         strcpy(name,names[n].name);
         sex=names[n].sex;
         //other (un)important stuff follows...
        }
        static void export();
        char *get_name() {return name;}
        int get_sex()   {return sex;}
};

//This exports _important_ member functions
void NPC::export()
{//NOTE: you use NPC.member_name as a function name,
 //not NPC::member_name;
 scAdd_Member_Symbol("NPC.get_name",get_name);
 scAdd_Member_Symbol("NPC.get_sex",get_sex);
}

char *header=
"//This is the internal header.                                         \n"
"//Something like 'stdio' internal header in seerc, but smaller         \n"
"#ifndef HEADER_INCLUDED                                                \n"
"#include stdlib							\n"
"import int printf(char *,...);                                         \n"
"import int scanf(char *,...);                                          \n"

"#define MAN    0                                                       \n"
"#define WOMAN  1                                                       \n"
//Now some more things : the NPC class (the almost-exact copy)
//SeeR knows the class as struct (no public/private/protected
//keywords allowed in SeeR so far). No constructor/destructor
//allowed also. Not this time, baby ;-)
"struct NPC{                                                            \n"
"       char name[64];                                                  \n"
"       int sex;                                                        \n"
"       int strength, wisdom, hp;                                       \n"
"       import char *get_name();                                        \n"
"       import int get_sex();                                           \n"
"};                                                                     \n"

//let's force the script to export these,
//they should be implemented further in script:
"export On_Talk;                                                        \n"
"void On_Talk(NPC *with);                                               \n"
"export Init;                                                           \n"
"void Init(char *name);                                                 \n"
"#define HEADER_INCLUDED                                                \n"
"#endif                                                                 \n"
;

/*
This function tells SeeR addresses of functions and variables it can
use (import). If script imports symbol you don't tell the address SeeR
will complain : unresolved reference.Here we use only printf, but we
can add also scanf. In this way you also add variables.
We add also the header files and export class NPC.
*/
void Init_Externals()
{
 scAdd_External_Symbol("printf",printf);
 scAdd_External_Symbol("scanf",scanf);
//let's export the class
 NPC::export();

 scAdd_Internal_Header("theHeader",header);
}

/*** THE MAIN ***************************************/
int main()
{
//scrpt will contain the compiled script
 scScript scrpt;
//and this is the instance of script, which we can call
//it contains all the data from script.
 scInstance *prog;

//let's give the script some functions of ours
 Init_Externals();

//when in SeeR in debug mode, here it will store all debugging data
 scOpen_Debug("excpp.dbg");//start debugging

//compile example script : "excpp.sc"
 scrpt=scCompile_File("excpp.sc");

//Error?
 if (scErrorNo)
   {
      printf("%s\n> %s\n",scErrorMsg,scErrorLine);exit(scErrorNo);
   }

//create instance of the script - you can run only instance of script,
//not script
 prog=scCreate_Instance(scrpt,"");
//Error?
 if (!prog)
  {
   printf("Error creating instance!\n%s\n",scErrorMsg);
   return 1;
  }

//now, let's execute the function (here 'main' has no arguments)
 scCall_Instance(prog,scGet_Symbol(prog,"Init"),"Igor the Shopkeeper");
//Error?
 if (scErrorNo)
      printf("%s\n",scErrorMsg);

 NPC npc;
 scCall_Instance(prog,scGet_Symbol(prog,"On_Talk"),&npc);
 if (scErrorNo)
      printf("%s\n",scErrorMsg);
//let's delete instance and script
 scFree_Instance(prog);
 free(scrpt);

//close debugging - close the debug file also
 scClose_Debug();

 return 0;
}

