Fragestellung: Ist es möglich ein Basic-Game zu entwickeln, das auf den meisten 8Bit-Homecomputern wie C64,MSX,MS-DOS,ZX81 etc läuft? Läuft bestenfalls mit keinen! bis kleinen Änderungen?
BASIC war die Sprache der 8Bit Homecomputer. Sie war alt (Darthmouth 1964), klein, eine Interpretersprache und dadurch relativ einfach zu implementieren.
Erste Erkenntnisse zur „Lingua-Franca“ BASIC
Es würde also nahe liegen sie als die Lingua-Franca zu benutzen über alle 8bit-HomeComputer hinweg. Und das trifft mehr oder minder für den ersten Darthmouth-Standard auch zu. Mehr oder weniger läuft alles dadrauf – nimmt man es nicht so genau mit Strings (Definierte Stringlänge bei Atari400/800, kein einfaches Concat mit +, Input) oder dem RND-Befehl (RND(4) QW-Basic).
Leider war Basic aber auch auf Input-Output-Programme für die frühe Entwicklung von Programme entwickelt worden, das heisst letztlich die Shell. Und so fehlt der Sprache per Standard jede Art von Keypressing-Funktionalität oder auch Grafikmöglichkeiten. Und hier legten sich die verschiedenen Computerhersteller wirklich ins Zeug Inkompatibilität aufzubauen. Allein die Geschichte um das Atari Basic zeigt auf was die Probleme waren: Der normale Interpreter brauchte schon 8k (Rom-Grösse mit akzeptablen Preis) – Atari wollte aber logischerweise auch Grafik-Commandos im Basic haben. Wie also reduzieren das Ganze? Indem man Befehle strich und anschliessend Befehle zusätzlich ins ROM verlagerte (wo es anscheinend unendlich langsam war).
All dies zeigt auf, dass diese Homecomputer letztlich zuerst als Hardware-Software-Paket verkauft wurden (obwohl Atari sein Basic zuerst seperat verkaufte). Die Kompatibilität war zuerst einmal da, indem man die meisten BASIC Lernkurse damit machen konnte. Danach wollten alle einzeln brillieren. Damit liessen sich natürlich de facto keine Platform übergreifende Software entwicklen und verkaufen, zumal auch keine Compiler existierten. Natürlich hatte auch jede Platform ihren eigenen Zeichensatz mit eigenen GrafikChars.
LineJeweled – Game in der Lingua-Franca „BASIC“
Um überhaupt eine Game über verschiedene Plattformen entwickeln zu können, musste also benutzt werden, was im Standard-Output möglich ist. Und das ist Print und Print ; (Lineprinter waren mal sehr in Mode). Ein Grafikaufbau mit CLS (Clearscreen) ist wegen Geschwindigkeit und Verfügbarkeit des Befehls oder seiner Simulation (30x Print „“) leider nicht möglich.)
Das heisst letztlich musste eine Spielmechanik gefunden werden, die ein einfaches Actiongetriebenes Game doch möglich macht und auch funktioniert, wenn man nicht auf dem Bildschirm zeichnen kann. Nach vielen Experimenten stellte sich heraus, dass man am Besten sich mit einer Variante von BeJeweled oder 3+ Gewinnt bedient. Das Spiel schreibt fortwährend das Spielfeld fort und der Spieler kann bei der Cursorposition einen zufälligen Edelstein einfügen. So kann der Spieler* 3+ Reihen in jede Richtung generieren und Punkte sammeln. Technisch muss auch nichts im Spielfeld geändert werden. Und das Spiel lebt vom Printen von Linien und verlängert das Spielfeld automatisch gegen oben. Dadurch entsteht ein für die Verhältnisse komplexes Spiel.
Auf dem C64 sieht das wie folgt aus:

Da die Anzeigen nicht immer neu gezeichnet werden, müssen sie einmal pro Linie geschrieben werden. Dadurch schreibt das Spiel auch seine eigne History per PRINT ins Fenster.
Der Aufbau:
AkutellerScore | Aktuelle Linie | NächsterEdelstein | Spielfeld > Gemachte Reihen + Punkte
Das Spiel ist deswegen Action getrieben, weil das Spiel unabhängig vom Spieler Edelsteine setzt und immer schneller wird.
LineJewels
Das Spiel kann hier in einem BBCMicro Emulator Online gespielt werden:
Let’s Play LineJewels >

Herausforderungen: Keypressing, RND, Strings
Prinzipiell ist die Grundmechanik bei allen Varianten diesselbe – also ein Code. Probleme gab es hier mit der Funktion von RND (Einige Interpreter spucken hier einen Integer aus RND(4) > 0-4) und die Stringbehandlung: Atari verwendet eine selbstdefinierte gefixte Länge. Einige Interpreter können keine Befehle mit „:“ aneinanderhängen. Und andere wiederum kennen wie das Orginal nur [A-Z] und [AA-ZZ] Variabeln wie das Darthmouth-Orginal. Der Code musste also jeweils so angepasst werden, dass er mit all diesen Varianten läuft, wobei das Problem ist: Gewisse Interpreter geben Fehlermeldung aus, wenn die Syntax nicht ihrer Syntax entspricht. All dies liess sich jedoch irgendwie umschiffen.
Die grösste Herausfoderung war/ist sicherlich das Nutzen von Keypressed, da dieses nicht im UrBasicStandard vorhanden war und darum auf jedem Computer irgendwie anders implementiert wurde. Keypress-Detection ist aber auch essentiell ist für jede Art von Actionspiel. Aus diesem Grund gibt es am Anfang eine Auswahl der Computer. Damit lässt sich dann einfach die jeweilige Keypressed-Routine, die funktioniert nutzen. Eine Autodetection scheint (wie beim RND) nicht möglich zu sein, zu unterschiedlich sind die Dinge und zu verschieden auch die Befehlssätze. So kennt nicht jedes Basic PEEK!
Auch die Grösse des RAMs spielt vorallem bei dem Array der Edelsteine eine Rolle und so war dann DIM(10,100) für einige Computer schon zuviel.
Fazit: C64, MSX, Amstrad, BBC Micro, MS-DOS (GW-BASIC), Atari400/800
Prinzipiell scheint es unmöglich ein Actionbasiertes Game zu machen, dass auf allen 8Bit Computern läuft. Zu divergent sind die verschiedenen Dialekte oder anders gesagt, das Fehlen von INKEY im ursprünglichen Standard.
Im Fall von LineJewels wurde der Kompromiss gemacht und die Keypressing-Routine mehrfach ausgeführt, dadurch läuft es zumindest auf 6-Systemen. Sicherlich könnte man noch PET hinzunehmen (ähnlich wie C64) und eine SMAKY Version einbauen. Bei ZX81 und Spektrum ist es meiner Meinung nach schwierig bzw. muss noch ausprobiert werden (Der ZX81 speichert das Programm nicht als Source-Code sondern in Codes).
Den Code direkt auf dem C64 ausführen? Hier findet man das File dazu D64 >
Versionen
Atari 400/800 Version

Amstrad Version

Noch nicht offizielle PET-Version

Code
Es sei schon gewarnt, der Code ist nicht besonders hübsch geworden. Das liegt auch daran, dass das Erweitern des Codes mit Linebasierung umständlich ist. Und so funktioniert ein ständiges Erweitern eigentlich nicht in BASIC, vermultich auch ein Grund, warum sich BASIC nicht wirklich für grössere Projekte eignete und warum sich später zeilenlose Basics durchgesetzt haben.
1 REM LINE JEWELS - CROSS 8BIT PORTABLE BASIC GAME
2 REM NEO LISTING/TYPE IN 8BIT GAME ---
3 REM C64_ VICE - F10 - IMPORT | PET_ WWW.MASSWERK.AT/PET/
4 REM AMSTRAD (CPC)_ ARNDOLD (AUTOTYPE)
5 REM MICROBBC_ BBCMIC.RO/ MSX_ WEBMSX.ORG (OPTION+B)
6 REM ATARI 800XL_ WWW.ATARIMAC.COM/INDEX.PHP
7 REM ------------- COPY FROM HERE -------------------
8 DIM F$(50):DIM A$(50):DIM AC$(50):DIM CH$(50):DIM MO$(50)
9 DIM RE$(50):DIM L$(50):DIM DX$(50):DIM OB$(50):DIM N$(50)
10 LET A$=""
11 F$="#X.O"
12 MC=0
13 CH$=""
14 LET HC = 420
15 LET AC$=""
16 VE = 0.6
17 DIM GT(10,100)
28 GOTO 70
39 REM SETTINGS
40 A$=""
41 A=0
42 CH=0
43 IF MC=2 THEN GOTO 51
44 IF MC=3 THEN GOTO 56
45 IF MC=4 THEN GOTO 58
46 REM C64-BASIC
47 A = PEEK(197)
48 IF A=10 THEN A$="A": GOTO 69
49 IF A=13 THEN A$="S": GOTO 69
50 GOTO 69
51 REM ATARI 800XL
52 CH=PEEK(764):POKE 764,255:IF CH=255 THEN GOTO 69
53 IF CH=63 THEN A$="A":GOTO 69
54 IF CH=62 THEN A$="S":GOTO 69
55 GOTO 69
56 REM MICRO BBC
57 A$=INKEY$(0):GOTO 69
58 REM GW-BASIC, MSX, AMSTRAD (ATTENTION UPPERCASE)
59 A$=INKEY$
69 GOTO 1320
70 REM GO ON
80 SP = 60
95 TS = 0
97 REM BASIC DARTHMOUTH > 64 - ONLY 2BYTE VAR NAMES!
100 GOSUB 5000
101 OB$ = "#XO."
102 PRINT "<#><.><O><O>"
103 PRINT "<#><O><O><X><X>"
104 PRINT ""
105 PRINT "LINEJEWELS - ONE BUTTON JEWLERY ";VE
106 PRINT ""
117 PRINT "ONE SOURCE FOR ALL OF THEM"
118 PRINT "NEO LISTING / TYPE-IN 8BIT-GAME"
111 PRINT "BY CHLUDENS.CH (EXPER. ARCHEOLOGY)"
112 PRINT "GREETINGS R. WERNER, S. HOELTGEN"
113 PRINT "USAGE: <S> SET STONE "
114 PRINT " <A> ONE FORWARD"
115 PRINT "TODO : CREATE 3+ LINES"
116 PRINT " WITH THE DIAMONDS ";OB$
117 PRINT "HIGHSCORE: ";HC
128 REM PRINT " ";CHR$(7);CHR$(7);CHR$(7)
130 PRINT " "
131 PRINT "COMPUTER: 1:C64 2:ATARI 800XL "
132 PRINT " 3:MICRO BBC "
133 PRINT " 4:MSDOS(GW),MSX,AMSTRAD "
134 INPUT MC
135 PRINT ""
136 PRINT ""
137 PRINT "GET RICH! "
138 PRINT "(NO CHANCE IF ARE NOT YET)"
139 PRINT ""
500 SC = 0
510 LI = 0
520 X = 0
530 AC$ = "#"
540 REM
1000 REM NEXT LINE
1001 GOSUB 6000
1002 AC$ = CH$
1005 X = 0
1006 MO$ = "INTERACTIVE"
1007 RE$ = ""
1008 REM IF SC<10000 THEN PRINT ;" ";
1009 IF SC<1000 THEN PRINT ;" ";
1010 IF SC<100 THEN PRINT ;" ";
1011 IF SC <10 THEN PRINT ;" ";
1012 L$ = ""
1013 IF LI>40 THEN L$=" "
1015 PRINT STR$(SC);" !";L$;STR$(50-LI);"! ";AC$;" ! ";
1100 GOSUB 6000
1110 REM
1119 KP = 0
1120 IF LI<2 THEN MO$ = "FORWARD"
1190 IF MO$<>"INTERACTIVE" THEN GOTO 1410
1199 H = 0
1200 REM --- CHECK KEYS AND PAUSE ---
1300 REM .
1305 REM .
1310 GOTO 40
1320 IF A$="S" THEN CH$ = AC$
1330 IF A$="S" THEN MO$ = "ENDLINE"
1332 IF A$="S" THEN RE$ = " >"
1333 IF A$="S" THEN KP = 1
1334 IF A$="S" THEN GOTO 1410
1335 IF A$="A" THEN GOTO 1410
1336 IF A$="s" THEN CH$ = AC$
1337 IF A$="s" THEN MO$ = "ENDLINE"
1338 IF A$="s" THEN RE$ = " >"
1339 IF A$="s" THEN KP = 1
1340 IF A$="s" THEN GOTO 1410
1341 IF A$="a" THEN GOTO 1410
1351 H = H + 1
1352 SP = (50 - LI)/2
1360 IF H<SP THEN GOTO 1200
1410 PRINT CH$;
1411 LET FV = 0
1412 GOSUB 7000
1418 REM ----
1420 GT(X,LI)=FV
1425 IF KP = 0 THEN GOTO 2000
1430 REM CHECK ALL - VERTICAL - HORIZONTAL ETC
1431 TS = 0
1432 FOR Q=0 TO 3
1433 VX = 0
1434 REM TS=0
1435 VY = -1
1436 GOSUB 7000
1438 IF Q=3 THEN VY = 0
1439 IF Q=3 THEN VX = -1
1440 CO = 0
1441 IF Q=1 THEN VX = -1
1442 IF Q=2 THEN VX = 1
1443 SX = X
1444 SY = LI
1445 SX = SX + VX
1446 SY = SY + VY
1447 CO = CO + 1
1460 IF SX<0 THEN GOTO 1500
1461 IF SY<0 THEN GOTO 1500
1462 IF SX>10 THEN GOTO 1500
1470 IF GT(SX,SY)=FV THEN GOTO 1445
1500 REM
1510 REM RE$ = RE$ + "";CO
1511 DX$ = "!"
1512 IF Q=1 THEN DX$ = "!"
1513 IF Q=2 THEN DX$ = "/"
1514 IF Q=3 THEN DX$ = "-"
1520 IF CO>2 THEN TS = TS + (CO*10)
1521 IF MC=2 THEN IF CO>2 THEN RE$(LEN(RE$)+1)= STR$(CO)
1522 IF MC=2 THEN IF CO>2 THEN RE$(LEN(RE$)+1)= DX$:GOTO 1524
1523 IF CO>2 THEN RE$ = RE$ + "" + STR$(CO) + ""+DX$
1524 REM IF MC<>2 THEN IF CO>2 THEN PRINT CHR$(7);
1600 NEXT Q
2000 X = X + 1
2010 REM
2020 REM
2400 IF X<10 THEN GOTO 1100
2405 SC = SC + TS
2406 IF MC=2 THEN IF TS>0 THEN RE$(LEN(RE$)+1)=STR$(TS):GOTO 2410
2407 IF TS>0 THEN RE$ = RE$ + " +" + STR$(TS)
2410 IF RE$<>"" THEN PRINT RE$;
2500 PRINT " "
2510 LI = LI + 1
2520 IF LI>49 THEN GOTO 7050
2600 REM
3900 GOTO 1000
4000 END
5000 REM CLS
5010 FOR T=0 TO 40
5020 PRINT " "
5030 NEXT T
5040 RETURN
6000 REM GET NEXT CHAR
6001 C = RND(4)
6002 IF C=0 THEN GOTO 6007
6003 IF C=1 THEN GOTO 6007
6004 IF C=2 THEN GOTO 6007
6005 IF C=3 THEN GOTO 6007
6006 C = INT(RND(1)*4)
6007 REM C64 ETC
6020 CH$ = "#"
6030 IF C=1 THEN CH$ = "X"
6040 IF C=2 THEN CH$ = "O"
6050 IF C=3 THEN CH$ = "."
6060 RETURN
7000 REM GET FIELD VALUE FROM CH$
7009 FV = 0
7010 IF CH$="X" THEN FV = 1
7020 IF CH$="O" THEN FV = 2
7030 IF CH$="." THEN FV = 3
7040 RETURN
7050 PRINT " "
7055 PRINT "END OF THE GAME"
7060 IF SC<HC THEN GOTO 7065
7061 PRINT ""
7062 PRINT "NEW HIGHSCORE! ";SC
7063 HC=SC
7065 PRINT " "
7070 PRINT "ANOTHER TRY? Y | N"
7080 INPUT N$
7090 IF N$="Y" THEN GOTO 500