Vergleiche dazu auch https://www.macintoshrepository.org/4984-bonyx
Spielmechanik
Woher die Spielmechanik kommt, kann ich heute leider nicht mehr eruieren. Die Spielmechanik ist simple, vielleicht fast zu einfach:

Es geht darum, dass man gleiche Steinreihen verschwinden lässt. Die Steine sind allerdings ungeordnet auf einem Stappel. Man kann nun Steine vom Stapel werfen nach unten, wo sie sich in einer neuen Lage sammeln. Sind alle vom selben Typ verschwinden sie, andernfalls werden sie nach oben geschoben. Sind alle Steine weg ist der Level gelöst. Allerdings gibt es eine Art Zeitlimit in Form eines Balkens, der langsam von oben nach unten fährt.
Code
Der Code ist in C in CodeWarrior geschrieben. Siehe dazu auch hier: https://research.swissdigitization.ch/?p=6270
CodeAufbau
Prinzipiell besteht der Code aus zwei Files:
_rock.c – das Spiel (keine Ahnung warum der Name vermutlich das ursprüngliche Template)
_hollywood.c – der music tracker (Soweit ich weiss per Zufall gefunden und kam aus Genf)
Hollywood.c
/* bonYxII */Includes
#include <CursorDevices.h>
#include <sound.h>
#include <math.h>
#include <Gestalt.h>
/* MUSIC IS ON */
#include <QuickTimeComponents.h>
#include <Components.h>
#include "Hollywood.h"
#include "Hollywood.c"Defs Game
int registr=0;    // 0 == nicht registriert 1 == registriert
int ev=0;         // EVENT=1 eingeschaltet
EventRecord    theEvent;
int ai;
Point integerPosition, position;    /* The position of our object, in integer and fixed-point*/
Point centerOfScreen;           /* The center of the screen*/
Point theMouse;                 /* A Point that we get the mouse position in*/
Rect drawingRectangle;          /* A rectangle used for drawing*/
Point speed;                    /* The accumulated speed*/
Rect    windRect,maxrec;
GDHandle         thisGDevice;
RgnHandle gOldVisRgn = NULL;  
KeyMap theKeys;
CGrafPtr bsack,banima,btest;
 int qweer=-10,aanzr=0;
int ffield[20][20][50]={{{ [...]
   int ff[100],razo=0;
    int breiteq[50]={3,4,4,3,[...],3},
        timeq[50]={1092,518,479,880,425,390,669,101,353,[...],163,212};
    int fof[100],timeqq,breiteqq;
    int ofield[10];    int field[20][20];
       SFReply  reply,replyy;
        short refnum,refnumm;
		long bietes;
	
	//---------------
	int cheat=0;  // cheat =0 deaktiviert
	
	int r=24,rr=24,rit=2;
	int alt,welch,qt;
	int anim,animz,spi=2;[Diverse Quicktime/Music-Pointers.]
// Screenhandeling (Offscreen)
void KillOffScreenPixMap (CGrafPtr offScreen){	[...] }
void CreateOffscreens (void) {  [...] }
void CreateOffScreenBitMap (Rect *theRect, GrafPtr *offScreen) { [...] }
void CreateOffScreenPixMap (Rect *theRect, CGrafPtr *offScreen) { [...] }Hauptprogramm / Spiel
/* MAIN */
void main(void)
{Init
/* DIE VARIABELN ZU BONYX II */
	int anz=0,red=0,zt=0,zzt=0;	
	int wox=120,woy=-100; 
	int woxt=0 ,woyt=0,awoxt=0,awoyt=0;
	int breiteu=3;
    int quix,quiy,quixt,quiyt,ier;
    int zlr,hi,zz,zlrt,we,zo;
	int alx=0,aly=100,aqx,aqy,x,y,out;
	int handz=0,schlagz=0,aanz=0,loe=0,uux,uuy;
    SndChannelPtr sndc0=0L,sndc1=0L,sndc2=0L;
    SndListHandle gefressen,click,levelg ,backgr,faellt,up,splat,ends,done,fluck;
    int teer,teera,rok=0,rime,rimet,fust=0;
    CCrsrHandle cune,tune;
    thisGDevice = GetMainDevice();
    
/* cleared field */
   for (ii=0;ii<20;++ii)
    for (i=0;i<20;++i)
     field[i][ii]=0;
/*
   for (anz=0;anz<50;++anz)
   { for (ii=0;ii<20;++ii)
     for (i=0;i<20;++i)
     //ffield[i][ii][anz]=0;
     breiteq[anz]=3;
     timeq[anz]=20;
	}; */
   field[0][11]=1;
      
 /* INIT */
	InitToolbox();
/* Hide the cursor - it won't make sense anyway */
	HideCursor();
/* ================== PATTERN ===================== */
   leers=GetPixPat(1);  /* schwarz bzw weisser HIntergrund */
   leerw=GetPixPat(0);[Set up window and co]
/* INSTALL CHEAT ? -- I am anfang drücken */
  GetKeys(theKeys);
  if (BitTst(&theKeys,37)==true) cheat=1;
Offscreen Init/* ============== OFFSCREENS   =============== */   
    CreateOffscreens ();
    
    SetRect(&rec,0,0,640,480);
        
    SetPort((GrafPtr) banima);
    FillCRect(&rec,leerw);    
                  
    SetPort((GrafPtr) btest);    
    FillCRect(&rec,leerw);                  
    SetPort((GrafPtr) bsack); //2 verschiedene Welten ok !!
    FillCRect(&rec,leerw);                  
[Installation aller Channels und Soundeffekte aus ResEdit ]
 [...]
 click=(SndListHandle) (GetResource(soundListRsrc,138));
 [...]// Registrationscheck
/* TESTEN OB REGISTRIERT */
                          GetVol(NULL,&reply.vRefNum);
                          FSOpen("\pSCOT",reply.vRefNum,&refnum);
                          bietes=sizeof(char)*10;
                          FSRead(refnum,&bietes,&snam[0]); // ANDERES !!
                          bietes=sizeof(int)*10;
                          FSRead(refnum,&bietes,&sser[0]); // ANDERES !!
                          FSClose(refnum); 
 					// TEST OB .. UND ODER DOCH NICHT ?
     /* --------TESTEN NOW---------- */
     for (ti=0;ti<10;++ti)
      es[ti]=snam[ti]+ti;
      
      
       es[0]=es[2]+es[3];
       es[4]=es[5]*es[1];
       es[9]=es[7]*es[8]*es[9];
       es[3]=es[1]*es[1]*es[1];
       es[7]=es[0]+es[1]+es[2]+es[3];
     for (ti=0;ti<10;++ti)
      if (es[ti]<0) es[ti]=0;
     /* VERGLEICHEN */
     tii=0;
     for (ti=0;ti<9;++ti)
     if ((es[ti]%10)==(sser[ti]-'0'))
     {  } else { tii=1;
      };
      
      if (tii==0) { /* SERIAL NUMBER IST ECHT */
     registr=1;
     // TON DAFUER ? 
     };
Loading

Menu

do { 
/* MUSICS */
if (quicktimei==1)
 if (musicflag==1) {
		HY_ServiceTasks();
		ProcessQuickTimeMovie();
 };
//if (musicflag==0)
//if (SndChannelBusy(sndc2)==false) SndPlay(sndc2,backgr,TRUE); 
                    GetMouse(&mousepix); 
                    x=mousepix.h;
                    y=mousepix.v; 
 teer=0;
 i=0;
 /* QUIT */
  if ((x<530) && (x>440))
   if ((y>339+40) && (y<380+40))
    { teer=1; 
    SetCCursor(tune);    
    
    if (Button()==true)
    { out=1; i=1;  
      SndPlay(sndc1,faellt,TRUE);
     };};
/* how to PLAY */
  if ((x<530) && (x>440))
   if ((y>40+264) && (y<40+326))
   { teer=6;
[...]

InGame

Background kopieren
/* DER LEVEL WIRD NEU GEZEICHNET */
                     SetPort((GrafPtr) myWindow );   
                     apple=GetPicture(136);  
                     SetRect(&rec,0,40,640,440 );
                     HUnlock((Handle) apple);
                     DrawPicture(apple,&rec);               
                     ReleaseResource((Handle) apple);  Steine zeichnen
for (ii=0;ii<20;++ii)
    for (i=0;i<20;++i)
     field[i][ii]=ffield[i][ii][red];
   breiteu=breiteq[red];
               
                      resi=0;
                      for (i=0;i<20;++i) 
                       for (ii=19;ii>=0;--ii) 
                       {
						 if (field[i][ii]!=0) 
						  SndPlay(sndc1,splat,TRUE); 
                       
                        for (anz=0;anz<17;anz=anz+2)      
                        if (field[i][ii]!=0)
                        {
                         
                           which=field[i][ii]-1;
						   q=i*breite;
						   qq=ii*hoehe;
                                                   
                            apple=GetPicture(200+which*5    );
						    SetRect(&rec,q+wox+32-anz*2,qq-anz+woy+16+40,q+anz*2+wox+32,qq+40+woy+16+anz);
						    HUnlock((Handle) apple);
						    DrawPicture(apple,&rec);               
						    ReleaseResource((Handle) apple); 
						    
						    if (Button()==true) {
						     i=20;
						     ii=-1;
						     anz=20;
						     resi=1;
						    }; };
						 
                          do ; while(SndChannelBusy(sndc1)==true); 
                          
						};Animationen
/* ZEICHNE ANIMATIONEN INS BANIMA */
SetPort((GrafPtr) banima );   
    SetRect(&rec,0,0,640,400);
    FillCRect(&rec,leerw);    
for (ii=0;ii<=10;++ii)
for (i=0;i<5;++i) {
    apple=GetPicture(200+ii*5+i);
    SetRect(&rec,i*64,ii*32,i*64+64,ii*32+32 );
     HUnlock((Handle) apple);
    DrawPicture(apple,&rec);               
    ReleaseResource((Handle) apple);  };
Stein verschoben
/* NUN WIRD EIN STEIN VERSCHOBEN */
					if (Button()==true)
                    { loe=0;
                    SndPlay(sndc0,click,TRUE); 
    schlagt= TickCount();         
 schlagz=0;      
 for (i=0;i<5;++i) {
   while (TickCount()<schlagt+6) { };   
				     SetRect(&re,lx,ly-40,lx+64,ly+32-40);                     
                     SetRect(&ri,640-64,400-64,640,400-32);   
                     CopyBits(&((GrafPtr) bsack)->portBits,&(((GrafPtr) banima)->portBits),&re,&ri,srcCopy, 0L);                      
			          SetRect(&re,schlagz*64,400-64,schlagz*64+64,400-32); 
                     SetRect(&ri,640-64,400-64,640,400-32);   
                     CopyBits(&((GrafPtr) banima)->portBits,&(((GrafPtr) banima )->portBits),&re,&ri,36, 0L);                      
                     SetRect(&re,640-64,400-64,640,400-32);                    
                     SetRect(&ri,lx,ly,lx+64,ly+32);
                     CopyBits(&((GrafPtr) banima)->portBits,&(((GrafPtr) myWindow)->portBits),&re,&ri,srcCopy, 0L);                      
      
     schlagt= TickCount(); 
        ++schlagz;
    };
[...]
Dev-LevelEditor
Das Spiel scheint einen Leveleditor zu besitzen.
	 for (i=0;i<10;++i)
	  ofield[i]=0;
	do
	{ 
/* EDITOR ---------------------------------------- */
                 GetKeys(theKeys);
                if (cheat==1)
                 if (BitTst(&theKeys,54)==true) { 
	     ShowCursor();                 
                    hoehe=32;
                    breite=64;
                    which=0;
					SetPort((GrafPtr) myWindow );   
                        apple=GetPicture(198);
						    SetRect(&rec,0,0,640,40);
Der LevelEditor scheint die Levels als C-Array zu speichern, wie er in der Initialiisierung genutzt wird. Hier werden also vermutlich die Daten im Code eingebunden und nicht geladen von einem File.
Lustig auch folgender Text (wie viele Kommentare in Deutsch) die Baustelle.

DevelopmentFolder

Webseite
Eine späte Version der Webseite sah so aus (1998?).

Registration übers Netz
