Svenska English
Här är mina tre enkla bidrag till Minigame 2002. Uppgiften var att skriva ett spel för en åttabitarsdator på maximalt en (1) kilobyte. Eftersom mina försök att skriva spel i assembler misslyckades kapitalt är dessa tre bidrag alla skrivna i BASIC.
De tre program som beskrivs på denna sida är släppta enligt GNU General Public License (svensk översättning), version 2.
Jag har dessutom skrivit en artikel om tävlingen för ABC-Bladet, medlemstidningen för datorföreningen ABC-Klubben.
Till dig som använder en textbaserad vävläsare: På grund av användningen av CSS visas inte dessa sidor helt korrekt i textbaserade webbläsare. Links och W3M är de som fungerar bäst, men även i dem blir radnumren felplacerade.
Detta är en implementation av spelet Connectris, en idé jag fick från den trevliga spelwebbplatsen It's Your Turn. Det är ett spel för två spelare vilket kombinerar det välkända Fyra på rad med det alltid lika populära Tetris.
De två spelarna, blå och röd, turas om att lägga i sina "brickor" i spelfältet. Du kan bara välja vilken kolumn du vill lägga din bricka i, den kommer alltid att hamna i den nedersta lediga raden. Spelaren som först får fyra brickor i dad, antingen horisontellt, vertikalt eller diagonalt, vinner.
Det speciella är att närhelst den nedersta raden blir helt fylld, så tas den ur spelet, och alla brickor flyttas ned ett steg!
Spelet kör på Commodore C128 i 80-kolumnersläge, och är skrivet helt i BASIC 7.0.
Om det startas från 40-kolumnersläge kommer det be dig om att byta läge och vänta på att en tangent trycks. Om det startas från något annat än en C128 kommer det visa ett felmeddelande och avsluta.
Jag fick frågan varför detta spel kör i C128:s 80-kolumnersläge då det inte använder sig av ens 40 kolumner. Det finns två skäl: Dels så kan jag blanda små/stora bokstäver (dialogen med användaren) med stora bokstäver/grafik (spelbrädet), dels går spelet dubbelt så fort i 2MHz-läge som i 1MHz-läge, även om det fortfarande går på tok för långsamt... :-/ (Om man kör programmet med en SuperCPU går det dock i acceptabel hastighet...)
Programmet kan hämtas här.
Startpunkt | ||
---|---|---|
1 | GOTO90 | Hoppa till huvudprogrammet |
Välj färger och skriv titeln | ||
2 |
COLOR6,6: | Grön bakgrund |
COLOR5,2: | Vit text | |
PRINT"{clear}{ct b}{ct n} C o n n e c t r i s {130}": | ||
RETURN | ||
Skriv ut vilka som spelar (överst på varje skärm) | ||
3 |
PRINT"{down}{light blue}{ct n}"a$" {black}vs {red}" b$"{black}.{down}": | |
RETURN | ||
Skriv ut brädet | ||
10 | PRINT"{142}{white} a b c d e f g h | Kolumnetiketter |
11 | FORy=.TO7: | |
FORx=.TO7: | ||
PRINT"{black}{sh -}";: | Ram | |
COLOR5,p(x,y): | Brädet innehåller färgdata | |
PRINT"●";: | En rund ring | |
NEXT: | ||
PRINT"{black}{sh -}": | ||
NEXT | ||
12 | PRINT"{cm z}{sh asterisk}{cm e}{sh asterisk}{cm e}{sh asterisk} {cm e}{sh asterisk}{cm e}{sh asterisk}{cm e}{sh asterisk}{cm e} {sh asterisk}{cm e}{sh asterisk}{cm x}": | Nederkanten |
RETURN | ||
Hämta ett drag från spelaren | ||
20 | DO: | |
DO: | ||
COLOR5,c: | C = spelarens färg | |
PRINT"{down}{ct n}"c$", your move? {142}{black}";: | C$ = spelarens namn | |
GETKEYx$: | ||
x=ASC(x$)-65: | Översätt A-H till kolumnnummer | |
PRINTx$: | ||
LOOPWHILEx<.ORx>7: | Kolla att kolumn är giltig | |
LOOPWHILEp(x,.)<>6: | Kolla att det finns ledig plats (=6=grön) | |
PRINT"ok | ||
21 | FORy=7TO.STEP-1: | Hitta nederst lediga plats |
IFp(x,y)<>6THEN | ||
NEXT | ||
22 | p(x,y)=c: | Lägg i brickan |
FORx=.TO7: | Är nedersta raden full? | |
IFp(x,7)<>6THEN | ||
NEXT: | ||
GOSUB30: | Ja! Rensa den | |
RETURN | Kan inte vinna nu | |
23 | GOSUB40: | Kolla vinstposition |
RETURN | ||
Radera nedersta raden och flytta allting ned en rad | ||
30 | FORx=.TO7: | |
FORy=7TO1STEP-1: | ||
p(x,y)=p(x,y-1): | ||
NEXT: | ||
p(x,.)=6: | 6=grön indikerar tom plats | |
NEXT: | ||
RETURN | ||
Kolla vinstposition | ||
40 | FORy=.TO7: | |
FORx=.TO4: | ||
IFp(x,y)+p(x+1,y)+p(x+2,y)+p(x+3,y)=c*4THEN50 | Horisontell vinstposition | |
41 | NEXT: | |
NEXT: | ||
FORx=.TO7: | ||
FORy=.TO4: | ||
IFx<5THEN | ||
IFp(x,y)+p(x,y+1)+p(x,y+2)+p(x,y+3)=c*4OR p(x,y)+p(x+1,y+1)+p(x+2,y+2)+p(x+3,y+3)=c*4THEN50 | Vertikal eller diagonal vinstposition | |
42 | IFx>2THEN | |
IFp(x,y)+p(x-1,y+1)+p(x-2,y+2)+p(x-3,y+3)=c*4THEN50 | Diagonal vinstposition | |
43 | NEXT: | |
NEXT: | ||
RETURN | ||
Tala om vem som vann | ||
50 | GOSUB2: | Titelrad |
COLOR5,c: | Spelarens färg | |
PRINT"{down}{ct n}You win, "c$: | ||
PRINT: | ||
GOSUB10: | Skriv ut brädet | |
GETKEYz$: | ||
RUN | Börja om | |
Fråga efter namn | ||
60 | PRINT"{down}{ct n}What's your name, "n$;: | |
INPUT" player";c$: | ||
RETURN | ||
Uppstartsrutin | ||
90 | IFINT(.1+.9)<>1THEN | Testa BASIC 7 |
PRINT"{reverse on} c128 mode ": | ||
END | ||
92 | IFRGR(0)<>5THEN | Kolla 80 kolumner |
PRINT"{reverse on} switch to 80 columns ": | ||
GRAPHIC5: | Byt till 80 kolumner | |
GETKEYz$ | ||
100 | FAST: | Dubbla hastigheten... |
GOSUB2 | Titelrad | |
120 | n$="blue": | Hämta namn på blå spelare |
DO: | ||
COLOR5,15: | ||
GOSUB60: | ||
LOOPWHILEc$="": | ||
a$=c$ | ||
130 | n$="red": | Hämta namn på röd spelare |
DO: | ||
COLOR5,3: | ||
GOSUB60: | ||
LOOPWHILEc$=""ORc$=a$: | ||
b$=c$ | ||
140 | DIMp(7,7): | Brädet |
FORx=.TO7: | Töm brädet | |
FORy=.TO7: | (fyll med gröna brickor) | |
p(x,y)=6: | 6=grön=bakgrund=tom | |
NEXT: | ||
NEXT | ||
Huvudslinga | ||
200 | c=3: | 3=röd spelare (blå börjar) |
DO: | ||
ONc/8+1GOSUB210,220: | Byt aktuell spelare | |
GOSUB2: | Titelrad | |
GOSUB3: | Vilka som spelar | |
GOSUB10: | Rita brädet | |
GOSUB20: | Hämta ett drag | |
LOOP | ||
Välj blå som aktuell spelare | ||
210 | c=15: | |
c$=a$: | ||
RETURN | ||
Välj röd som aktuell spelare | ||
220 | c=3: | |
c$=b$: | ||
RETURN |
Detta är det berömda "Masken". Jag stötte först på detta spel i och med Luxors spel Masken till ABC_80. Du är en mask (eller en larv i det här fallet) och ditt uppdrag är att äta så många mål som möjligt. Närhelst du äter ett mål växer masken. Om du kör in i väggen eller dig själv är spelet slut.
Spelet styrs med siffrorna på det numeriska tangentbordet: 8 för uppåt, 4 för vänster, 6 för höger och 2 för nedåt. Alla andra tangenter får masken att stanna, vilket betyder att spelet omedelbart tar slut!
Detta spel kör på Commodore C128 i 40-kolumnersläge, och är skrivet helt i BASIC 7.0.
Om spelet startas i 80-kolumnersläge kommer det automatiskt att växla över till 40-kolumnersläge åt dig.
Maggot är en variant på det gamla välkända Masken-temat. Jag kom först i kontakt med Masken på Luxor ABC-80, och det spelet var skrivet helt i BASIC. Nu är ABC BASIC snabb, till skillnad från Commodores BASIC, så det jag tyckte det var en intressant utmaning att skriva en variant av Masken i Commodore-BASIC, i grafikläge, som åtminstone inte var helt ospelbart långsam. Det gick väl så där.
Programmet kan hämtas här. Observera! VICE version 1.9 och 1.10 är buggiga och klarar inte av det här programmet ordentligt. Det fungerar i version 1.8.
Startpunkt | ||
---|---|---|
0 | GRAPHIC1,1: | Byt till grafikläge |
FAST: | Snabba på initieringen (och släck skärmen) | |
DEFFNr(x)=INT(RND(.)*x): | Skapa heltalsslumptal i [0,X) | |
DEFFNn(x)=x+1+zz*(x=z): | Öka X med nollställning vid Z | |
GOTO10 | Gå till huvudinitieringen | |
Förflytta masken | ||
5 | LOCATEx(h),y(h): | Flytta grafikpekaren till dit vi ska |
IFRDOT(2)THEN100 | Om det finns något där dör vi | |
6 | GETa$: | Se om vi tryckt en tangent |
IFa$<>""THENGOSUB9 | Om vi gjort det byter vi riktning | |
7 | DRAW1: | Förflytta masken |
DRAW.,x(t),y(t): | ||
t=FNn(t): | Räkna ut nästa index för svansen | |
IFti>pTHENGOSUB93 | Dags att flytta målet? | |
8 | RETURN | |
Byt riktning | ||
9 | r=4*((a$="4")-(a$="6")): | 4=vänster, 9=höger |
d=2*((a$="8")-(a$="2")): | 8=uppåt, 2=nedåt | |
RETURN | ||
Initiera spelet | ||
10 | COLOR0,7: | Blå bakgrund |
COLOR1,4: | Cyan grafik | |
COLOR4,9: | Orange ram | |
WIDTH2 | All grafik två pixlar bred | |
11 | CIRCLE,40,40,8: | Målet är en fylld cirkel |
PAINT,40,40: | ||
SSHAPEt$,32,32,55,53: | Spara som sprite | |
GRAPHIC1,1: | Töm skärmen | |
SPRSAVt$,1 | Definiera cirkeln som spritebild 1 | |
12 | FORi=1TO7STEP2: | |
BOX1,i*2,i,319-i*2,189-i: | Rita ramar runt skärmen | |
NEXT: | ||
COLOR1,14: | Ljusgrön färg | |
CHAR,0,24,"{ct n}Score: 0 | Poängräknare | |
13 | COLOR1,2: | Vit färg |
CHAR,20,24,"{ct n}www.softwolves.pp.se": | Och lite reklam... | |
COLOR1,4 | Masken är cyan | |
20 | z=1024: | Maxlängd är 1024 |
zz=z+1: | Hjälpvariablen för FNN | |
DIMx(z),y(z): | ||
FORi=.TO9: | ||
x(i)=18+i*4: | Startposition (100,18) - (100,36) | |
y(i)=100: | ||
DRAW,x(i),100: | Rita | |
NEXT: | ||
h=9: | Huvudet på index 9 | |
t=. | Svansen på index 0 | |
21 | GOSUB93: | Förbered första målet |
SLOW: | Visa skärmen | |
r=4: | Flyttar åt höger | |
d=. | Ej uppåt | |
Huvudslinga | ||
30 | DO: | |
DO: | Slinga för höger/vänster-förflyttning | |
o=h: | Minns föregående huvudindex | |
h=FNn(h): | Räkna ut nästa huvudindex | |
x(h)=x(o)+r: | Flytta åt höger/vänster | |
IFx(h)<15ORx(h)>304THEN100 | Kolla skärmkanter | |
31 | y(h)=y(o): | |
GOSUB5 | Förflytta | |
32 | LOOPWHILEr | |
40 | DO: | Slinga för upp/ned-förflyttning |
o=h: | ||
h=FNn(h): | ||
y(h)=y(o)+d: | Flytta åt uppåt/nedåt | |
IFy(h)<8ORy(h)>181THEN100 | ||
41 | x(h)=x(o): | |
GOSUB5 | ||
42 | LOOPWHILEd: | |
LOOP | ||
Träff registrerad | ||
90 | COLLISION2: | Stäng av detekteringen |
SPRITE1,1,1: | Gör målet svart för att indikera träff | |
s=s+BUMP(2): | Räkna upp poängen och nollställ kollisionen | |
COLOR1,14: | ||
CHAR,6,24,STR$(s): | Skriv ut poängen | |
COLOR1,4 | ||
91 | e=FNr(5)+3: | Slumpa fram hur mycket masken skall förlängas |
DO: | ||
o=h: | ||
h=FNn(h): | ||
IFh=tTHEN | Har vi nått maxvärdet? | |
h=o: | I så fall slutar vi förlänga | |
EXIT: | ||
ELSE | ||
x(h)=x(o): | Annars förlänger vi masken | |
y(h)=y(o): | ||
e=e-1: | ||
LOOPWHILEe | ||
92 | SPRITE1,.: | Göm målet |
MOVSPR1,.,.: | Flytta undan det från skärmen | |
p=30+FNr(60): | Slumpa tid för återkomst (0,5-1,5s) | |
GOTO94 | Nollställ klockan | |
Slumpa fram ett mål | ||
93 | x=FNr(269)+42: | Slumpa fram koordinater för målet |
y=FNr(156)+59: | ||
MOVSPR1,x,y: | Flytta dit målet | |
COLLISION2,90: | Slå på träffdetektering | |
SPRITE1,1,FNr(5)+2,.,.,.,.: | Slå på spriten | |
p=360+FNr(360) | Slumpa tid innan målet flyttas (6-12s) | |
94 | ti$="000000": | Nollställ klockan |
RETURN | ||
Slut på spelet | ||
100 | CHAR,18,24,"{ct n}Game over! Play again?": | Visa att spelet är slut |
GETKEYz$: | ||
IFz$="y"THENRUN | Starta om om så önskas | |
101 | GRAPHIC.: | Återställ textläge |
SPRITE1,.: | Ta bort målet | |
COLOR.,1: | Svart bakgrund | |
COLOR4,1: | Svart ram | |
PRINT"{clear}{ct n}{white}You caught"s"target"; | Visa poängen | |
102 | IFs<>1THENPRINT"s"; | (i plural) |
Detta är ett enkelt "undervisnings"-spel, i vilket du endast får passera det hemska trollet (som visas på skärmen som ett rätt fult huvud) om du kan svara på dess frågor korrekt. I detta fall gäller det matematiska problem.
Ange först din ålder, vilken väljer svårighetsgraden. Därefter får du de olika frågorna. Du måste svara alla frågor korrekt för att få passera!
Om frågorna är för svåra kan du testa med att ljuga om din ålder! :)
Detta spel kör på valfri åttabitars Commodoremaskin med BASIC version 2 eller senare. Det anpassar automatisk sin utdata så att den passar din skärm, oavsett om det är en VIC 20 eller en C128 i 80-kolumnersläge.
Jag vet inte om jag egentligen vill klassa det här som ett spel... Jag fick idén en kväll när jag gått och lagt mig och kunde inte få den ur huvudet, så jag gick upp och skrev ned spelet på min C128. Det som fick mig att skicka in det till tävlingen var att jag anpassade programmet så att det fungerar på alla Commodoremaskiner med BASIC 2. Jag testade för säkerhets skull det på PET 3032, VIC-20, C64 och C128... Jag blev glad när jag såg att det inte kom sist... (Jag undrar vem som var, öh, snäll nog att ge det tio av tio poäng?) Idén med tre frågor för att passera en bro kommer från filmen Monthy Pythons galna värld.
Programmet kan hämtas här.
Startpunkt | ||
---|---|---|
0 | DEFFNr(r)=RND(.)*r+1: | Slumptalsgenerator |
GOTO10 | Gå till huvudprogrammet | |
Radbryt en text och skriv ut | ||
1 | IFLEN(z$)<=wTHEN | Får texten plats på raden? |
PRINTz$;: | I så fall skriv ut den direkt | |
RETURN | ||
2 | FORi=wTO.STEP-1: | |
IFMID$(z$,i,1)<>" "THENNEXT | Leta på strategiskt blanksteg | |
3 | PRINTLEFT$(z$,i): | Skriv ut fram till blanksteget |
z$=MID$(z$,i+1): | Klipp strängen | |
GOTO1 | Och börja om | |
Huvudrutin | ||
10 | PRINT"{clear}{down}{left}";: | Ta reda på hur bred skärmen är |
w=POS(.) | ||
11 | PRINT"{home}{reverse on} none shall pass! {down}": | Skriv ut titeln |
PRINT" /\/\ {cm m}": | Avancerad grafik... | |
PRINT"/\/\/\ {sh @}": | ||
PRINT"\ \/ /": | ||
PRINT" \ /": | ||
PRINT" \/{down} | ||
12 | DIMa$(99): | Räkneord |
FORi=1TO19: | Hämta in ord för 1-19 | |
READa$(i): | ||
NEXT: | ||
FORi=20TO90STEP10: | ||
READa$(i): | Hämta in tiotal | |
FORj=1TO9: | ||
a$(i+j)=a$(i)+a$(j): | Konstruera räkneord inom varje tiotal | |
NEXT: | ||
NEXT | ||
20 | z$="none shall pass unless he answers me right. tell me your age": | |
GOSUB1 | ||
21 | INPUTa%: | Hämta ålder, dvs. svårighetsgrad |
IFa%<2ORa%>130THEN90 | Kolla att svaret är rimligt | |
22 | m=10: | Lägsta svårighetsgraden har bara ental |
n=m: | ||
IFa%>11THEN | ||
m=20: | Nästa svårighetsgrad har upp till | |
n=12: | tolvans multiplikationstabell | |
IFa%>15THEN | ||
m=99 | Nästa grad har alla tal | |
23 | y$="what is ": | Frågetext |
IFa%<8THEN30 | Lägsta svårighetsgraden har inte multiplikation | |
25 | f1%=FNr(m): | Fråga 1 |
f2%=FNr(n) | ||
26 | z$=y$+a$(f1%)+" times "+a$(f2%): | Multiplikation |
GOSUB1: | ||
INPUTp: | ||
IFp<>f1%*f2%THEN90 | ||
30 | t1%=FNr(m): | Fråga 2 |
t2%=FNr(t1%): | ||
IFt2%=0THEN30 | Se till att vi inte subtraherar noll | |
31 | z$=y$+a$(t2%)+" from "+a$(t1%): | Subtraktion (blir alltid positiv) |
GOSUB1: | ||
INPUTs: | ||
IFs<>t1%-t2%THEN90 | ||
35 | a1%=FNr(m): | Fråga 3 |
a2%=FNr(m): | ||
IFa1%+a2%=0THEN35 | ||
36 | z$="tell me the sum of "+a$(a1%)+" and "+a$(a2%): | Addition |
GOSUB1: | ||
INPUTa: | ||
IFa<>a1%+a2%THEN90 | ||
Vinst | ||
80 | z$="you may pass!": | Grattis, du vann! |
GOSUB1: | ||
END | ||
Förlust | ||
90 | z$="that's not correct!": | Du förlorade |
GOSUB1: | ||
END | ||
Räkneord | ||
100 | DATAone,two,three,four,five,six,seven,eight,nine,ten, eleven,twelve,thirteen,fourteen,fifteen,sixteen, seventeen,eighteen,nineteen | |
101 | DATAtwenty,thirty,fourty,fifty,sixty,seventy, eighty,ninety |