From: karttu@mits.mdata.fi (Antti Karttunen)
Subject: JINTORI (was Re: Some far-out ideas)
Organization: MITS, Helsinki, Finland
Date: Sun, 16 Aug 1992 21:31:20 GMT

(I apologize the rambling nature of this article, but I'm almost sleeping
when I write this.)

There has been some queries about that Jintori game I mentioned in my last
message. So here are some answers:

The ftp site is ftp.waseda.ac.jp (133.9.1.32) (user-id: anonymous)
and executable with some sample patterns can be found from
/pub/archive/fj.binaries.msdos/jintori.lzh
and the sources can be found from /pub/fj/fj.sources/games/jintori
If I remember right, they are all packed in Jintori.2.01.tar
so you don't need to download all the small files.
Except the sample bug programs in the sample subdirectory, there was
also bug programs KUNI91, PAT, YOU, and 1 in the directory superior to it
(which are not included in executable package, however).

However, there's only one problem. The sources and executable are for
the Japanese NEC PC-9800 series compatible micros. Although these
machines also use (somewhat Nihongo-zied) MS-DOS, they are _not_
"western" IBM-PC compatible. Although most programs work ok, as long as
they don't try to do anything fanciful with the screen, the graphics, etc.

But this Jintori (= "Battle field") game of course need graphics, so
the graphics portion of the code has to be rewritten. And that's
exactly what I have done. But there are still some bugs in the code
I have written (Uh, don't know Turbo-C graphics routines so well,
as I have wasted my time with the ancient Aztec-C), and now the
development for my part is frozen as one genius here happily formated
the hard disk containing the Borland C compiler... ;-(

So! If there is some kind soul there with the Turbo C compiler and some
spare time, then I suggest downloading the sources from the above mentioned
site, replacing the visualmo.c file in them with the file I give below.
Also, the sound effect portions of the code in the other source files
(jintori.c, etc.) should be commented out. Preferably with #ifdef PC98
and #endif instead of /* */, so the code can later be compiled for
PC-9800's also.

Of course, the sources can be compiled for other machines also (like
Amiga, X-windows, etc.), just replace the graphics functions in
visualmo.c file.

And still one surprise. All documents coming with packages seem to
be in Japanese! (some written with JIS and some with Shift-JIS)
I'm trying to "translate" jintori.man to English, but it's somewhat
slow as I don't actually know Japanese even myself.
(I just have good kanji-dictionary ;-)

Actually, here's also my version of soundeff.h file, effectually
defining all the sound functions as null macros, when compiled
for the western PC's:

===================== CUT HERE ======================================

/*
 *      "Jintori" Version 2.01  Mar 27, 1991
 *      SoundEffector.h  Version 2.01
 *      Last modified: Mar 15, 1991
 */

#ifdef PC98

extern void  OpenSoundEffector(/* */);
extern void  CloseSoundEffector(/* */);

extern void  SoundBorn(/* */);
extern void  SoundDead(/* */);
extern void  SoundBasisi(/* */);
extern void  SoundPaint(/* */);
extern void  SoundPause(/* */);
extern void  SoundUnPause(/* */);
extern void  SoundOff(/* */);


extern FuncResponse  SoundEffector_ParseArguments(
    /* int *argc, char *argv[] */
);

#else /* Sorry, no sounds! */


#define OpenSoundEffector()
#define CloseSoundEffector(); /* Hmm, these semicolons are probably useless */

#define SoundBorn();
#define SoundDead();
#define SoundBasisi();
#define SoundPaint();
#define SoundPause();
#define SoundUnPause();
#define SoundOff();

#endif


===================== CUT HERE ======================================


New visualmo.c for the "western" version of JINTORI. Contains some minor
bugs, easily fixed:
===================== CUT HERE ======================================

/*
 *      "JINTORI" Version 2.01  Mar 27, 1991
 *      VisualMonitor.c (PC-9801, Turbo-C) Version 2.01
 *      OriginalDebut: Jul 2, 1990
 *      Extension: StopCheck, DispFinalState, SystemError  Jul 7, 1990
 *      Extension: StopCheck  Oct 26, 1990
 *      Extension: DispDebugStatus  Nov 26, 1990
 *      Extension: Delay, CloseVisualMonitor  Mar 11, 1991
 *      Modify: ParseArguments  Mar 15, 1991
 *      Modify: EventLoop  Mar 27, 1991
 *      Last modified: Mar 27, 1991
 *      FOR PC-9801 + TURBO-C.
 */

/*
 * Now modified by Antti Karttunen (karttu@mits.mdata.fi) 4-AUG-1992
 * for IBM-PC compatibles + TURBO-C.
 *
 * But still buggy, (see the routine initgraf()!), and also prints status
 * texts outside of the screen, at least in CGA mode. (So modify the
 * text starting locations.)
 *
 */


#include  "PrivateIdent.h"
#include  "LimitDefinition.h"
#include  "VisualMonitor.h"

#include  "EventManager.h"
#include  "ProcessManager.h"
#include  "SoundEffector.h"
#include  "Message.h"
#include  "ArgumentParser.h"

#include  <string.h>
#include  <process.h>
#include  <conio.h>
#include  <dos.h>
#include  <graphics.h>
#include  <stdio.h>

/* cprintf uses ROM BIOS calls, instead of writing directly to the screen: */
/* extern int directvideo = 0;    Barf, not needed now. */

static char  NameOfPlayer[MaxPlayers][BUFSIZ];

#ifdef PC98

static void  pset(x, y, color)
    int  x, y, color;
{
    unsigned char  *blue = (unsigned char *)0xa8000000L;
    unsigned char  *red = (unsigned char *)0xb0000000L;
    unsigned char  *green = (unsigned char *)0xb8000000L;
    unsigned int  addr;
    unsigned char  mask;

    addr = 80 * y + x / 8;
    mask = 1 << (7- x % 8);
    blue += addr;
    red += addr;
    green += addr;
    if ((color & 1) != 0) {
        *blue |= mask;
    } else {
        *blue &= ~mask;
    }
    if ((color & 2) != 0) {
        *red |= mask;
    } else {
        *red &= ~mask;
    }
    if ((color & 4) != 0) {
        *green |= mask;
    } else {
        *green &= ~mask;
    }
}

#else

#define pset putpixel

#endif

static void  boxline(x1, y1, x2, y2, color)
    int  x1, y1, x2, y2, color;
{
    int  i;

    for (i = x1; i <= x2; i++) {
        pset(i, y1, color);
        pset(i, y2, color);
    }
    for (i = y1; i <= y2; i++) {
        pset(x1, i, color);
        pset(x2, i, color);
    }
}

static void  boxfill(x1, y1, x2, y2, color)
    int  x1, y1, x2, y2, color;
{
    int  x, y;

    for (y = y1; y <= y2; y++) {
        for (x = x1; x <= x2; x++) {
            pset(x, y, (x+y) % 2 ? color : 0);
        }
    }
}


#ifdef PC98

#define  PixelSize 2
static int  OffsetX = 40;
static int  OffsetY = (400 - FieldSizeY * PixelSize) /2;
static int  ColorTable[MaxPlayers] = {2, 6};

#else

static int  PixelSize;
static int  bordercolor = 7, headcolor = 7;
static int  OffsetX = 40;
static int  OffsetY;
static int  charwidth,charheight;

static int  ColorTable[MaxPlayers] = {1, 4};

#endif

static void  ClearScreen()
{
#ifdef PC98
    int  i;
    unsigned char  *blue = (unsigned char *)0xa8000000L;
    unsigned char  *red = (unsigned char *)0xb0000000L;
    unsigned char  *green = (unsigned char *)0xb8000000L;

    clrscr();
    for (i=0; i < 0x7f00; i++) {
        *blue++ = 0;
        *red++ = 0;
        *green++ = 0;
    }
#endif
}

#ifdef PC98

void put_text(x,y,mesg)
int x,y;
char *mesg;
{
    gotoxy(x,y);
    cprintf("%s",mesg);
}

#else

void put_text(x,y,text)
int x,y;
char *text;
{
    outtextxy(x*charwidth,y*charheight,text);
}

/* This should work so that if there's a VGA card, then use VGAHI mode
   (640x480?) (so that pixelsize will be 2 and so on), but if not, then use
   CGA medium resolution mode (320x200) with some of the modes CGAC0-CGAC3
   which have the most awful palettes I have seen in any computer.
   (Maybe it could be made user selectable which palettes and colours
    (s)he can use?)

   However, there's a bug in that initialization code, which seems to
   freeze those machines with no VGA. AND IT NEEDS FIXING!!!
 */

/* For Turbo-C & Western PC's: */
void initgraf()
{
     int graphdriver=VGA;
     int graphmode=VGAHI;
     int errorcode;


/* Some auto-detection code, not used now:
     if (registerbgidriver(EGAVGA_driver) < 0) exit(1);
     if (registerbgidriver(Herc_driver) < 0) exit(1);
     if (registerbgidriver(CGA_driver) < 0) exit(1);
 */

     initgraph(&graphdriver,&graphmode,"");

     /* If no VGA, then use CGA with 320x200 resolution & four colours. */
     if((errorcode = graphresult()) != grOk)
      {
        graphdriver = CGA;
        graphmode = CGAC0;
        detectgraph(&graphdriver,&graphmode);
      }

     if((errorcode = graphresult()) != grOk)
      {
        fprintf(stderr,
"\njintori: graphics error %d: %s\n",errorcode,grapherrormsg(errorcode));
        exit(1);
      }


     charwidth  = textwidth(" ");
     charheight = textheight(" ");
     if(graphdriver == CGA)
      {
        ColorTable[1] = 2;
        bordercolor = headcolor = 3;
        PixelSize = 1;
        OffsetX = 1;
        OffsetY = (200 - FieldSizeY * PixelSize) /2;
        charwidth >>= 1;  /* Divide by two, to get 4 */
      }
     else /* VGA */
      {
        PixelSize = 2;
        OffsetY = (400 - FieldSizeY * PixelSize) /2;
      }
/*
     MAXCOL=getmaxx();
     MAXROW=getmaxy();
 */
}


void exitgraf()
{
     closegraph();
}

#endif

void  OpenVisualMonitor()
{
#ifdef PC98
    union REGS  reg;

    reg.h.ah = 0x42;
    reg.h.ch = 0xc0;
    int86(0x18, &reg, &reg);
    reg.h.ah = 0x40;
    int86(0x18, &reg, &reg);
    textbank(1);
    textcursor(NODISP_CURSOR);
#else
    initgraf();
#endif
    ClearScreen();
}

void  CloseVisualMonitor()
{
    ClearScreen();
#ifdef PC98
    textbank(0);
    textcursor(BLINK_CURSOR | DISP_CURSOR);
#else
    exitgraf();
#endif
}

void  ClearField()
{
    boxline(
        OffsetX -PixelSize -1, OffsetY -PixelSize -1,
        OffsetX +FieldSizeX*PixelSize, OffsetY +FieldSizeY*PixelSize,
        bordercolor
    );
    boxline(
        OffsetX -PixelSize, OffsetY -PixelSize,
        OffsetX +FieldSizeX*PixelSize -1, OffsetY+FieldSizeY*PixelSize -1,
        bordercolor
    );

    put_text(56,2,"TOTAL STEPS: ");
    put_text(56,4,"PLAYER 1");
    put_text(58,6,"SCORE:           0");
    put_text(58,8,"NumOfBugs:       1");

    boxfill(70*8, 3*16, 75*8, 4*16, ColorTable[0]);
    if(NumOfPlayers > 1)
     {

        put_text(56,13,"PLAYER 2");
        put_text(58,15,"SCORE:           0");
        put_text(58,17,"NumOfBugs:       1");

        boxfill(70*8, 12*16, 75*8, 13*16, ColorTable[1]);
     }
}

void  SetDot(x, y, player, class, flush)
    int  x, y, player;
    enum PixelClass  class;
    bool  flush;
{
    int  i, j;
    int  color;

    color = (class == Head ? headcolor : ColorTable[player]);
    if (class == Territory) {
        pset(OffsetX + x*PixelSize -1, OffsetY + y*PixelSize -1, color);
        pset(OffsetX + x*PixelSize +1 -1, OffsetY + y*PixelSize +1 -1, color);
    } else {
        for (j=0; j < PixelSize; j++) {
            for (i=0; i < PixelSize; i++) {
                pset(OffsetX + x*PixelSize +i -1, OffsetY + y*PixelSize +j -1, color);
            }
        }
    }
    flush = flush;  /*NC*/
}

void  ClearDot(x, y, flush)
    int  x, y;
    bool  flush;
{
    int  i, j;

    for (j=0; j < PixelSize; j++) {
        for (i=0; i < PixelSize; i++) {
            pset(OffsetX + x*PixelSize +i -1, OffsetY + y*PixelSize +j -1, 0);
        }
    }
    flush = flush;  /*NC*/
}

static void  DispStep(step)
    long  step;
{
    char tmpbuf[8];

    sprintf(tmpbuf,"%6ld", step);
    put_text(70,2,tmpbuf);
}

void  DispScore()
{
    static struct {int x, y;}  position[MaxPlayers] = {
        {70, 6}, {70, 15} /*, {37, 1}, {37, 25} */
    };
    int  player;

    for(player = 0; player < NumOfPlayers; player++)
     {
        char tmpbuf[8];
        sprintf(tmpbuf,"%6d", Score[player]);
        put_text(position[player].x,position[player].y,tmpbuf);
#ifdef PC98
        if (Score[player] <= Score[1-player]) {
            textattr(T_WHITE | NOSECRET);
        } else if (Score[player] > FieldSizeX*FieldSizeY/2) {
            textattr(T_WHITE | REVERSE | NOSECRET);
        } else {
            textattr(T_WHITE | UNDERLINE | NOSECRET);
        }
#endif
     }
#ifdef PC98
    textattr(T_WHITE | NOSECRET);
#endif
}

void  DispNumOfBugs(player, NumOfBugs)
    int  player, NumOfBugs;
{
    char tmpbuf[8];

    static struct {int x, y;}  position[MaxPlayers] = {{70, 8}, {70, 17}};

    sprintf(tmpbuf,"%6d", NumOfBugs);
    put_text(position[player].x, position[player].y, tmpbuf);
}


    static void  Pause()
    {
        SoundPause();
        put_text(64,24,"== PAUSE == ");
        getch();
        SoundUnPause();
        put_text(64,24,"            ");
    }

void  DispDebugStatus(p, pid, status)
    int  p, pid;
    WORD  status;
{
    char tmpbuf[21];

    sprintf(tmpbuf, "%d", (int)status);
    put_text(
        (OffsetX + BugTable[p][pid].x *PixelSize) /8 +1,
        (OffsetY + BugTable[p][pid].y *PixelSize) /16,
        tmpbuf
    );
    Pause();
    put_text(
        (OffsetX + BugTable[p][pid].x *PixelSize) /8 +1,
        (OffsetY + BugTable[p][pid].y *PixelSize) /16,
        "      "
    );
}

static int  DelayTime;
void  Delay()
{
    long  i;

    for (i=0; i < DelayTime; i++) {
       i = i;
    }
}

void  DispCompileError(mesg, source, pointer)
    char  *mesg, *source, *pointer;
{
    fprintf(stderr, "%s\n%s\n%s\n", mesg, source, pointer);
}

static void  OpenAllProcessManagers()
{
    int  i;
    for (i=0; i < NumOfPlayers; i++) {
        OpenProcessManager(i);
    }
}

static void  CloseAllProcessManagers()
{
    int  i;
    for (i=0; i < NumOfPlayers; i++) {
        CloseProcessManager(i);
    }
}

void  SystemError(mesg)
    char  *mesg;
{
    put_text(1,1,mesg);
    printf("\n");
    CloseSoundEffector();
    CloseVisualMonitor();
    CloseAllProcessManagers();
    exit(3);
}


    static bool  StopCheck()
    {
        if (kbhit()) {
            switch (getch()) {
            case  0x0d:
                return  true;
            case  ' ':
                Pause();
                break;
            }
            return  false;
        } else {
            return  false;
        }
    }

    static void  DispFinalState(state)
        enum ProcessStatus  state;
    {
        switch (state) {
        case  Terminated:
            put_text(64,24,MesgFinished);
            break;
        case  TimeOut:
            put_text(64,22,MesgTimeOut);
            break;
        case  Breaked:
            put_text(64,24,MesgAborted);
            break;
        }
    }

    static void  ReadProgram()
    {
        int  i;

        for (i=0; i < NumOfPlayers; i++) {
            fprintf(stderr, NowCompiling, i +1);
            switch (Compile(i, NameOfPlayer[i])) {
            case  Aborted:
                fprintf(stderr, CannotOpenFile, i +1);
                CloseAllProcessManagers();
                exit(1);
            case  Done:
                break;
            case  Error:
                CloseAllProcessManagers();
                exit(2);
            }
        }
    }

void  EventLoop()
{
    enum ProcessStatus  status;

    OpenAllProcessManagers();
    ReadProgram();
    OpenVisualMonitor();
    OpenSoundEffector();

    InitProcessTable();
    InitField();
    StartFirstProcesses();
    do {
        status = DoStep();
        if (status == TimeOut || step % 32 == 0) {
            DispStep(step);
            if (StopCheck()) {
                status = Breaked;
                break;
            }
        }
    } while (status == Running);
    DispFinalState(status);
    while (!StopCheck());

    CloseSoundEffector();
    CloseVisualMonitor();
    CloseAllProcessManagers();
}


static char  *player[MaxPlayers];
static bool  PlayerSpecified[MaxPlayers];
static struct ArgumentSyntax  ArgumentSyntax[] = {
    {"-delay", OptionalArg, IntegerParam, &DelayTime, nil},
    {"", ObligatoryArg, StringParam, &player[0], &PlayerSpecified[0]},
    {"", OptionalArg, StringParam, &player[1], &PlayerSpecified[1]},
    {nil, nil, nil, nil, nil}
};
FuncResponse  VisualMonitor_ParseArguments(argc, argv)
    int  *argc;
    char  *argv[];
{
    FuncResponse  res;
    int  i;

    res = ParseArguments(argc, argv, ArgumentSyntax);
    NumOfPlayers = 0;
    for (i=0; i < MaxPlayers; i++) {
        if (PlayerSpecified[i]) {
            NumOfPlayers++;
            strcpy(NameOfPlayer[i], player[i]);
        }
    }
    return  res;
}

===================== CUT HERE ======================================

-- 
Antti Karttunen       --  $B%"%s%C%F%#!!%+%k%C%H%%%M%s(J  (et{ty|t|n)
karttu@mits.mdata.fi  --  Apatheist, although not particularly proud of it.
Newsgroups: rec.games.corewar