BASIC (mehr dazu hier >) erfunden in den 60er Jahre (noch weitgehend im CommandLine Input/Output Frame) hat eine lange Geschichte der Radiation hinter sich. BASIC fehlte strategisch so etwas wie inkludierbare Frameworks, die dann auf jedem System wieder anders implementiert werden mussten. Es war ja auch unter anderem als Programmiersprache fürs Lernen konzipiert worden.
Es entstanden deswegen eine Menge verschiedene Dialekte, in denen eigentlich nur noch die Grundbefehle gemeinsam sind, aber selbst die Nutzung dieser 26-Grundbefehle ist oft unterschiedlich (Dim-Defintionen etwa). Man kann sich sogar fragen, ob selbst Assembler-Programme ohne Zeilennummern ‚moderner‘ waren. Vor allem die 80er Jahre mit ihren Basic-HomeComputer-Interfaces waren prägend. Und so läuft fast kein Basic-Programm auf verschiedenen Plattformen. Noch einschneidender war selbstverständlich das Aufkommen von Zeilenlosen-Basics wie etwa GFA-Basic ab den 16/32Bit-Homecomputern, das eine Kompatibilität fast unmöglich machte.
Will man heute ein BASIC Programm schreiben, das auf so vielen Plattformen wie möglich läuft, muss man sich start beschränken auf die minimalen Befehle. Das schwierigste ist natürlich die Ausgabe, da BASIC in seiner ursprünglichen Form eigentlich auf LinePrinter ausgelegt ist (60er Jahre) bzw. Bildschirme als Lineprinter funktionierten. Grafikbefehle Fehlanzeige. Der Rechner war hier wirklich als „Rechner“ gedacht.
Noch schwieriger ist es, etwas im Action-Bereich zu machen. Also da, wo es um Keypressing geht und das optionale Nutzen von Input. Hier wird es sehr schwierig, da das Dartmouth-Basic, soweit ich das sehe, über kein eigenes Kommando verfügt und so jede Implementation dann selbst etwas „gewurstelt“ hat, um das zu ermöglichen. Ein weiteres Problem ist selbstverständlich die Möglichkeit irgendwie die Geschwindigkeit zu messen, bei heute im Vergleich zu damals unendlich schnellen Systemen.
Die letzten zwei Anforderungen muss man also auf jeder Installation – soweit ich das sehe – selbst implementieren.
Action-Angehauchtes „Be Jeweled“ oder 3+ gewinnt
Anbei wurde versucht ein einfaches BASIC-Spiel zu implementieren, dass ActionAspekte hat und dennoch auf allen Plattformen ohne grosse Anpassungen laufen wird (Zeilenbasiert).
Herausgekommen ist am Ende ein vereinfachtes „Be jeweled“ mit Lineprint als Ausgabe.
Das Spiel schreitet voran und fügt per PRINT neue „Edelsteine“ hinzu. Dabei wartet das Spiel eine Sekunde, bis der nächste Stein angehängt wird. In dieser Zeit kann der Spielende seinen Stein anfügen. Im vorliegenden Fall ist es ein „.“. Danach wird die Linie beeendet und abgerechnet.
Game Design Specials
Interessant ist an dieser Art Spiele zu entwerfen, dass man niemals zurück kann, sondern nur vorwärts (nach unten). Das heisst alle sich verändernden Daten müssen angefügt werden. Die Innovation beim vorliegenden Fall liegt in der Nutzung auch dieser schon „genutzten“ Steine für das aktuelle Spielgeschehen.
Dies trifft ebenso auf den Score zu, dieser wird erst in der nächsten Line upgedatet. Und so kann selbstverständlich auch immer nur ein Stein pro Linie eingesetzt werden. Die Einschränkungen sind krass und so muss die Spielmechanik angepasst werden, um etwas Spiebares zu kreieren. Das Spiel schreibt also – wie bei LPrintern üblich – seine eigene Geschichte. Der Screen ist dabei nicht ausschliesslich der aktuelle Zustand des Spiels, der immer wieder überschrieben wird.
Visuell sind solche Spiele schwierig wie alle Zeichensatzspiele: Denn wir erkennen sehr gut Zeichen Buchstaben und diese sind schwer ablösbar von ihrem Zeichencharakterkontext. Und ja: Es gibt Spezialzeichen. Nur bei welchen Systemen ist das je gleich? Wer unterstützt dann reines ASCII etc.
Source-Code
Der folgende Source-Code ist noch nicht optimiert (auf andere System). zeigt aber schon in welche Richtung, die Varianten gehen könnten.
GW-Basic
10
60 rem settings
80 invspeed = 60
100 gosub 5000
110 print "ONE BUTTON JEWELERY"
111 print "usage: <a> set stone <s> one forward"
120 print " "
500 score = 0
510 lines = 0
520 x = 0
530 act$ = "#"
540 dim gfield(10,1000)
1000 rem next line
1001 gosub 6000
1002 act$ = ch$
1005 x = 0
1006 mode$ = "interactive"
1007 result$ = ""
1008 if score<100 then print " ";
1009 if score <10 then print " ";
1010 print score;" | ";lines;" | ";act$;" | ";
1100 gosub 6000
1110 rem
1119 keypressed = 0
1120 if lines<2 then mode$ = "forward"
1190 if mode$<>"interactive" then goto 1410
1200 for h = 0 to invspeed
1300 rem check
1305 rem
1310 a$=inkey$
1320 if a$="a" then ch$ = act$
1330 if a$="a" then mode$ = "endline"
1332 if a$="a" then result$ = " < "
1333 if a$="a" then keypressed = 1
1340 if a$="a" then goto 1410
1350 if a$="s" then goto 1410
1360 if a$<>"u" then goto 1400
1370 print "debug"
1381 for n=0 to lines
1382 for nn = 0 to 10
1383 print gfield(nn);" - ";
1384 next nn
1385 print " "
1386 next n
1400 next h
1410 print ch$;
1411 let fieldval = 0
1412 gosub 7000
1420 gfield(x,lines)= fieldval
1425 if keypressed = 0 then goto 2000
1430 rem check all - vertical - horizontal etc
1431 tempscore = 0
1432 for q=0 to 3
1433 vx = 0
1434 vy = -1
1435 gosub 7000
1438 if q=3 then vy = 0
1439 if q=3 then vx = -1
1440 count = 0
1441 if q=1 then vx = -1
1442 if q=2 then vx = 1
1443 startx = x
1444 starty = lines
1445 startx = startx + vx
1446 starty = starty + vy
1447 count = count + 1
1460 if startx<0 then goto 1500
1461 if starty<0 then goto 1500
1462 if startx>10 then goto 1500
1470 if gfield(startx,starty)=fieldval then goto 1445
1500 rem how many counted?
1510 rem result$ = result$ + "counted ";count
1511 direction$ = " | "
1512 if q=1 then direction$ = " \ "
1513 if q=2 then direction$ = " / "
1514 if q=3 then direction$ = " - "
1520 if count>2 then tempscore = tempscore + count*10
1521 if count>2 then result$ = result$ + " " + count + "*"+direction$
1600 next q
2000 x = x + 1
2010 rem
2020 rem
2400 if x<10 then goto 1100
2405 score = score + tempscore
2407 if tempscore>0 then result$ = result$ + " + "+tempscore
2410 if result$<>"" then print result$;
2500 print " "
2510 lines = lines + 1
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
6010 c = rnd(4)
6020 ch$ = "#"
6030 if c=1 then ch$ = "O"
6040 if c=2 then ch$ = "X"
6050 if c=3 then ch$ = "."
6060 return
7000 rem get field value from ch$
7005 fieldval = 0
7010 if ch$="X" then fieldval = 1
7020 if ch$="O" then fieldval = 2
7030 if ch$="." then fieldval = 3
7040 return