#include	"cpyrt.h"			/* DRI copyright message    */
/****************************************************************************/
/*									    */
/*	The  source code contained in this listing is a proprietary trade   */
/*	secret of Digital Research Inc., Pacific Grove, California and is   */
/*	copyrighted  as  an  unpublished  work pursuant to Section 408 of   */
/*	Title  17  of  the  United  States  Code.  Unauthorized  copying,   */
/*	adaptation, distribution, use or display is prohibited by law.	    */
/*									    */
/*	Author:	 xxxxxxxxxxx						    */
/*	PRODUCT: MAZE VidLink Program					    */
/*	Module:  mazefn							    */
/*									    */
/****************************************************************************/

/****************************************************************************/
/*									    */
/*	MAZE Module: MAZEFN, Maze Function				    */
/*	-----------------------------					    */
/*									    */
/*		This is the MAZE function module.  This module		    */
/*	provides the VidLink Maze Program functions.		  	    */
/*									    */
/*	The following routines are present:				    */
/*									    */
/*		maze		MAZE function				    */
/*									    */
/*	The following routines are called:				    */
/*									    */
/*		xxxxxxxxx	xxxxxxxxxxxxxxxx			    */
/*									    */
/*	Revision History:						    */
/*									    */
/*		06/20/84  by  xxxxxxxxxxxx				    */
/*									    */
/****************************************************************************/

/*
 *	Include Files
 */						/****************************/
#include	"portab.h"			/* DRI portable coding conv */
						/****************************/
#include	"ascii.h"			/* ASCII character defines  */
						/****************************/
#include	"color.h"			/* color defines	    */
						/****************************/
#include	"graph.h"			/* graphics chars	    */
						/****************************/

/*#page*/
/*
 *	External Data/Functions:
 */

#include	"vcrt.d"

#include	"mazex.d"			/* maze function extrnl data*/

EXTERN	WORD	vdpiof();

EXTERN	WORD	VIOSTAT();


/*#page*/
/*
 *	Local Data/Functions:
 */
#define	MAX_PLAYERS	6
#define QMAX		4000		/* size of question buffer */
#define AMAX		40		/* size of answer buffer */
#define RETURN		0x0d		/* carriage return */
#define BACKSP		0x09		/* backspace ?? */

struct scene =
    {
    UWORD	start;
    UWORD	finish;
    BYTE	right;
    BYTE	wrong;
    };

struct scene intro [] =
    {
    /* 01 */ 00150, 01482, 02, 00,
    /* 02 */ 01800, 02120, 00, 00
    };

struct scene nightmare_castle [] =
    {
    / * 01 */ 02138, 02202, 02, 01
    };

struct scene blast_off [] =
    {
    /* 01 */  00000, 00000, 00, 00
    };

struct scene first_and_ten [] =
    {
    /* 01 */  00000, 00000, 00, 00
    };

struct scene shoot_out [] =
    {
    /* 01 */  00000, 00000, 00, 00
    };

struct player_state =
    {
    BYTE	score;
    UBYTE	adventure;
    UBYTE	scene;
    UBYTE	group;
    BOOLEAN	bonus;
    };

struct player_state player [MAX_PLAYERS];

BYTE	c_scene;		/* current scene */
BYTE	c_player;		/* current player */
BYTE	last_player;		/* last player number */

UBYTE	row;			/* current row */

UBYTE	q_buffer[QMAX];		/* question buffer */
UBYTE	eoq;			/* TRUE if end of question file */
UWORD	q_size;			/* size of q_buffer (normally QMAX) */
UWORD	q_next;			/* next q_buffer to fill */
UWORD	g_next;			/* next group number */
UWORD	g_count;		/* group count */
UWORD	g_base;			/* group base */
UBYTE	g_max;			/* used to find next question */

UBYTE	ans[AMAX];		/* answer buffer */
UBYTE	a_size;			/* current answer size */

/*#page*/
/****************************************************************************/
/*									    */
/*				xxxxxxxx				    */
/*			        --------				    */
/*									    */
/*		This subroutine performs the xxxxxxxxxxxxxxxxxxxxxxxx.	    */
/*									    */
/****************************************************************************/
GLOBAL	maze(argc,argv)
						/****************************/
WORD	argc;					/* cmd tail argument count  */
CHAR	*argv[];				/* cmd tail string pointers */
    {						/*****	begin maze	*****/
    CHAR c;


#ifdef	CPU_65
    d_ouchar(14);				/* switch to lower case	    */
#endif
    clear();
    sign_on();
    vdpiof("VC");
    p_inchar();

    clear();
    set_row(5);
    l_outstr("     Do you want to see");
    set_row(6);
    l_outstr("     the Introduction (y/n)? ");
    c = p_inchar();
    if ((c == 'Y') || (c == 'y'))
	{
	clear();
	set_row(5);
	l_outstr("     Insert Maze Mania Side #1 ");
	set_row(6);
	l_outstr("     Strike any key to continue ");
	c = p_inchar();
	vdpiof("FR1SE");
	if (VIOSTAT())
	    {		/* not in play mode */
	    while (!VIOSTAT())
		;
	    while (vdpiof("PL"))
		{
		set_row(8);
		l_outstr("     Please insert disc.");
		}
	    set_row(9);
	    l_outstr("     Thank-you.");
	    while (!VIOSTAT())
		;
	    vdpiof("PA");
	    }
	else
	    while (!VIOSTAT())
		;
	clear();
	set_row(5);
	l_outstr("     Introduction Part #1 ");
	vdpiof("VOVP");

	if (!sequence((UWORD)150,(UWORD)1482))
	    {
	    vdpiof("VC");
	    p_move(6,0);
	    l_outstr("     Introduction Part #2 ");
	    vdpiof("VP");
	    sequence((UWORD)1800,(UWORD)2120);
	    }
	vdpiof("VC");
	}

    init_players();
    c_scene = 1;
    c_player = 0;
    g_next   = 0;
    g_count = 0;
    q_size   = QMAX;
    while (select_player())
	ask_question();

    /* saved for reference
    p_clear();
    p_move(9,0);
    l_outstr("     Sequence test.");
    p_move(10,0);
    l_outstr("     Strike any key to abort.");
    vdpiof("VP");
    while (!sequence((UWORD)12450,(UWORD)12500))
	;
    */

#ifdef	CPU_65
    d_ouchar(142);				/* switch to upper case	    */
#endif
    }						/*****	end maze	*****/

/*#page*/
/****************************************************************************/
/*									    */
/*				xxxxxxxx				    */
/*			        --------				    */
/*									    */
/*		This subroutine performs the xxxxxxxxxxxxxxxxxxxxxxxx.	    */
/*									    */
/****************************************************************************/
MLOCAL sign_on()
    {
    UBYTE	i;
    UBYTE	j;
    UBYTE	k;

    p_color(BLUE);
    i = 0;
    j = (p_crt.rows - h_so_maze) >> 1;
    k = (p_crt.cols - w_so_maze) >> 1;

    while (so_maze[i])
	{
	p_move(i+j,k);
	l_outstr(so_maze[i++]);
	}
    }

GLOBAL	l_outstr(s)

CHAR	*s;
    {
#ifdef	CPU_65
    CHAR	c;

    while (c = *s++)
	{
	if ((c >= 'a') && (c <= 'z'))		/* if lower case	    */
	    c = c & 0xdf;			/*	then to upper	    */
	else
	if ((c >= 'A') && (c <= 'Z'))		/* if upper case	    */
	    c = c | 0x20;			/*	then to lower	    */
	d_ouchar(c);
	}
#else
	p_outstr(s);
#endif
    }

newline()
    {
    set_row(row+1);
    }

set_row(r)

UBYTE	r;
    {
    p_move(row = r, 0);
    }

clear()
    {
    row = 0;
    p_clear();
    }

stop_display()
    {
    UWORD i;
    for (i = 0; i < 30000; i++);
    }

BOOLEAN	read_group()
    {
    UWORD q, k, k_loc;
    UBYTE n, n1, n2;
    if (eoq || (eoq = !(n = gn_num())))
	return;
    q_next = g_next;
    put_q(n);
    while (n--)
	{
	n1 = gn_num();
	n2 = gn_num();
	k_loc = q_next;
	put_q(0);
	put_q(0);
	k = 0;
	while (n1--)
	    k += gn_nstr();
	put_q('\0');
	while (n2--)
	    k += gn_nstr();
	put_q('\0');
	k += 2;
	put_nq(k_loc, k & 0xff);
	put_nq(k_loc+1, k >> 16);
	if (q_next >= q_size - 2)
	    return (FALSE);
	g_next = q_next;
	g_count++;
	return (TRUE);
	}
    }

UBYTE gn_num()
    {
    UBYTE x, d;
    x = 0;
    while ((d = gnc()) == ' ' || d == ',')
	;
    while (d = d - '0') <= 9)
	x = x * 10 + d;
    return (x);
    }

UWORD gn_nstr()
    {
    UWORD d;
    UBYTE c;
    d = 1;
    while (gnc() != '"')
	;
    while ((c = gnc()) != '"')
	{
	put_q(c);
	d++;
	}
    put_q('\n');
    return (d);
    }

UBYTE gnc()
    {
    if (eoq)
        return ('"');
    /* note: read next character */
    return ('#');
    }

put_q(x)

UBYTE	x;
    {
    put_nq(q_next,x);
    }

put_nq(loc,x)

UWORD	loc;
UBYTE	x;
    {
    if (loc >= q_size)
	return;
    q_buffer[loc] = x;
    if (loc >= q_next)
	q_next = loc + 1;
    }
    
UBYTE rand_q(g)

UBYTE	g;
    {
    /* return random number between 1 and g */
    return (1);
    }

next_question()
    {
    UWORD q;
    q = rand_q(g_max = get_q(g_base));
    q_next = 1;
    while (q--)
	gn_qpos();
    for (q = 1; q < g_max; q++)
	{
	if (!(get_q(q_base+1) & 0x80))
	    break;
	gn_qpos();
	}
    if (q >= g_max)
	{
	for (q = 1; q < g_count; q++)
	    {
	    put_q(q_base+1,get_q(q_base+1) | 0x80);
	    gn_qpos();
	    }
	}
    }

gn_qpos()
    {
    q_base +=
	gnq(q_base) | ((gnq(q_base+1) & 0x7f) << 8);
    if (++q_next > g_max)
	{
	q_base = g_base + 1;
	q_next = 1;
	}
    }

display_question()
    {
    set_row(4);
    l_outstr("    Here's the question:");
    newline();
    write_q(&q_buffer[q_base]);
    }

write_q(q)

UBYTE	*q;
    {
    while (*q)
	{
	if (*q == '\n')
	    {
	    newline();
	    l_outstr("    ");
	    }
	else
	    d_outchar(*q);
	q++;
	}
    }

BOOLEAN get_answer()
    {
    UBYTE c;
    newline();
    newline();
    l_outstr("    What's your answer?");
    a_size = 0;
    while ((c = p_inchar()) != RETURN)
    if (c == BACKSP)
	{
	if (a_size > 0)
	    {
	    d_outchar(BACKSP);
	    d_outchar(' ');
	    d_outchar(BACKSP);
	    }
	}
    else
    if (a_size < AMAX)
	d_outchar(ans[a_size++] = c);
    while (get_q(q_base))
	{
	if match_q()
	    return (TRUE);
	while (get_q(q_base++) != '\n')
	    ;
	}
    return (FALSE);
    }

BOOLEAN match_q()
    {
    UBYTE a;
    for (a = 0; a < a_size; a++)
    if (toupper(get_q(q_base)) != toupper(ans[a]))
    if (get_q(q_base) == '\n')
	return (FALSE);
    return (get_q(q_base) == '\n');
    }

ask_question()
    {
    UBYTE p, g, r, w;
    BOOLEAN a;
    UWORD s;
    if (player.bonus[c_player])
	vdpiof("ST");
    else
	vdpiof("AL");
    clear();
    set_row(3);
    l_outstr("    Player ");
    outBYTE(c_player);
    l_outstr(" has ");
    outBYTE(p = player.score[c_player]);
    l_outstr(" points");
    g = player.group[c_player];
    a = TRUE;
    while (a)
    	{
	/* select next question from group */
	if (g > g_count)
	if (!read_group())
	    g = 1;
	/* note: make g_base absolute q_buffer address from group g */
	next_question();
	display_question();
	if (a = get_answer())
	    {
	    g += 1;
	    if ((p += 5) > 100)
		p = 100;
	    s = nightmare.right[scene];
	    }
	else
	    {
	    if ((p -= 3) < 0)
		p = 0;
	    s = nightmare.wrong[scene];
	    }
 	/* set frame display for bonus questions later */
	play_scene(scene);
	clear();
	set_row(3);
	if ((r = nightmare.right[scene]) + (w = nightmare.wrong[scene]) == 0)
	    {
	    l_outstr("    Congratulations!  You made");
	    newline();
	    l_outstr("    it through the maze");
	    s = 0;
	    a = FALSE;
	    }
	else
	if (r == 0)
	    {
	    l_outstr("    Sorry, DEAD END");
	    s = w;
	    }
	if (a)
	    {
	    l_outstr("    Correct!");
	    /* display bonus question info later */
	    s = r;
	    }
	else
	    {
	    l_outstr("    Oops!  You got the");
	    newline();
	    l_outstr("    question wrong");
	    }
	stop_display();
	}
    player.score[c_player] = p;
    player.scene[c_player] = s;
    player.group[c_player] = g;
    }



play_scene(s)

UBYTE	s;
    {
    /* should test for abort from sequence */
    while (TRUE)
	{
	sequence(nightmare.start[s],nightmare.finish[s]);
	if (nightmare.wrong[s] != 0)
	    return;
	if ((s = nightmare.right[s]) == 0)
	    return;
	}
    }


GLOBAL	BOOLEAN	sequence(start,stop)

UWORD	start;
UWORD	stop;
    {
    UBYTE	str[10];
    UBYTE	stp[10];
    BOOLEAN	key;

    sprintf(str,"%d",start);
    sprintf(stp,"%d",stop-1);

    vdpiof("VO");
    vdpiof("FR");
    vdpiof(str);
    vdpiof("SE");
    while (!VIOSTAT())
	;
    vdpiof("MF");
    vdpiof(stp);
    vdpiof("SE");
/*
    if (VIOSTAT())
	while (VIOSTAT())
	    ;
*/
    while (!VIOSTAT())
	;
    vdpiof("VNPL");
/*
    if (VIOSTAT())
	while (VIOSTAT())
	    ;
*/
    while (!VIOSTAT())
	;
    key = FALSE;
/*
    while (VIOSTAT())
	if (key = p_instat())
	    {
	    p_inchar();
	    break;
	    }
*/
    while (1)
	{
	if (!VIOSTAT())
	    if (!VIOSTAT())
		if (!VIOSTAT())
		    if (!VIOSTAT())
			break;
	if (key = p_instat())
	    {
	    p_inchar();
	    break;
	    }
	}
    vdpiof("PA");
    return(key);
    }
