#include <stdio.h>

void NL(){
    putchar('\n');
}
void Say(const char * msg){
    puts(msg);
    //NL();
}
char Input(){
    puts("Choose ");
    char cmd = getchar();
    return cmd;
}


typedef const char * String;
typedef unsigned int Index;
typedef unsigned char Bool;

#define Range(var,count) var=0; var < count; var++
#define Len(array) (int)( sizeof(array) == 0 ? 0 : sizeof(array) / sizeof(array[0]) )
#define Function(T,RT,PT...) RT (*T)(PT)
#define Table(T,Columns) struct T { Columns }
#define False 0

typedef Table(Kv,
              const char * Key; 
              int Val;
              const struct Kv * Next;
             )Kv;
int Get(Kv * kv,
        const char * key){
    if (kv){
        if (kv->Key == key){
            return kv->Val;
        }
        return Get(kv->Next,key);
    }
    return False;
}
int Set(Kv * kv,
         const char * key,
         int val){
    if (kv){
        if (kv->Key == key){
            kv->Val = val;
            return val;
        }
        return Set(kv->Next,key,val);
    }

    return False;
}

/********************************* coroutine ***********************************/
//duffman machine is not simple enough
//define your coroutine with :
// Co coroutineName (Co current){... return (Co){ptr}}
// return (Co){0}; to exit
// reutrn current; to loop
// use CoRun((Co){coroutineName})
#define Quit (Co){0}
typedef Table(Coroutine,
              Function(Run,
                       struct Coroutine,
                       struct Coroutine);
              ) Co;
void CoRun(Co current){
    while(current.Run){
        current = current.Run(current);
    }
}

void CoRunLst(Co coLst[],const int size){
    while(coLst[0].Run){
        int index;
        for (index=size-1; index>-1; index--){
            coLst[index] = coLst[index].Run(coLst[index]);
        }
    }
}

/*
 * actor are distinguished from place
 * but they are state machine like place
 * but actor have a 1:n relation ship with place
 * many actor can share the same place.
 * and actor may be findable byt place
 *
 * entity is not a state machine
 * they have a relation 1:n with actor
 * they are findable by actor
 */
/******************************** ymcface *************************************/

Co Caught(Co current) {
    Say("Hey You, Who are you ? "
        "It is My house "
        "Hear gunshot and your eye close themself");
    return Quit;
}

Co UnderTheBed(Co current) {
    return Quit;
}

Co OutTheCloset(Co current) {
    Say("now in the room with your wet pant, "
        "the rooms [d]oor is half open, "
        "the [c]loset is behind, "
        "at the [w]indow you see the sun, its noon ,"
        "there is lot of dust [u]nder the bed");
    switch(Input()){
        case 'd':
            Say("you open the door and walk away," 
                "every step remind you that you peed in your pant"
                "the man of the house is right out the door");
            return (Co){Caught};
        case 'c':
            Say("you return in the closet and a bowling ball fall on your head");
            return Quit;
        case 'w':
            Say("you open the window and jump "
                "it was not a bungalow but a condomium "
                "falling 3 stage directly on the concrete "
                "the legist stated that you peed in your pant before commiting suicide");
            return Quit;
        case 'u':
            Say("you crawl under the bed"
                "just in time before he came back with deodorant");
            return (Co){UnderTheBed};
    }
    return current;
}

Co InTheCloset(Co current){
    puts("you are in the closet, its dark, you [w]ait as you were told to "
        "you cant see anything around you except the [c]rack of the [d]oor,"
        "you hear a loud voice, you have an urge to [p]ee");
    switch(Input()){
        case 'd':
            puts("open the door and see the fear itself in a human form");
            return (Co){Caught};
        case 'p':
            puts("peeing in your pant"
                "hear yelling : DAMN IT ! IT SMELL BAD !" 
                "That damn cat peed under my bed again"
                "you hear foot step, he seam to have walked away"
                "open the door");
            return (Co){OutTheCloset};
    }
    return current;
}

int clock = 0;
Co Tac(Co);
Co Tic(Co current){
    puts("Tic");
    clock++;
    return (Co){Tac};
}
Co Tac(Co current){
    puts("Tac");
    clock++;
    return (Co){Tic};
}
//main

int main(void){
    //CoRun((Co){InTheCloset});
    Co lst[] = {
        (Co){InTheCloset},
        (Co){Tic}
    };
    CoRunLst(lst,2);
    return 0;
}
