Kare Kaplumbağa

Commodore 64 için BASIC ile yazılmış Mahjong Solitaire Oyunu
Wizofwor, Ekim 2015

image

Bill Kendrick'in Atari BASIC'de yazdığı, Minijong'u gördüğümde C64 versionu hazırlama fikrine karşı koyamadım. Sonuçta BASIC kodları açıklamalarıyla birlikte karşımda duruyordu. Bir hafta sonunda Kare Kaplumbağa ortaya çıktı.

Nasıl oynanıyor?

Bilmeyenler için Mahjong Solitaire Mahjong taşlarıyla oynanan bir tür iskambil falı. Amaç birinin aynı taşları eşleştirerek toplamak. Yüzleri görünür şekilde dizili taşlardan sadece sol veya en sağı serbest olanlar alınabiliyor. Taşlar üst üste dizildiği için alttaki taşlara ulaşmak için önce üst sıradakileri temizlemek gerekiyor.

Oyun 2. porta takılı joystickle oynanıyor. Taş seçimi için joystickle istediğiniz taşın üstüne gelip ateşe basmalısınız. Birbirinin aynı iki taşı seçerek toplayabilirsiniz.

Dosyalar

Kod açıklamaları

Hazırlık

1 rem mahjong game by wizofwor

10 print "{clr}{home}":print"             kare kaplumbaga"

20 dim b(196) : rem board, oyun alani (4 seviye)
25 dim bz(196): rem oyun alanı yüksekliği
28 dim bc(196): rem tas rengi 
30 dim p(120) : rem secim havuzu
40 dim c(2)  : rem secilen taslar

İlk olarak oyunun adını ekrana yazıyorum. Kare kaplumbağa ismi saçma görünse de bir anlamı var. Bunu yazının sonunda açıklayağım.

Oyunun adını ekrana yazdıktan sonra dizi kullanacağım değişkenlerinin boyutlarını belirtiyorum. Oyun alanım 7x7 genişlikte ve dört seviyeden oluşuyor. Yani 7x7x4=196 elemanlı bir diziye ihtiyacım olacak. b() oyun alanındaki taşların değerini, bz() taşların yüksekliğini, bc() renk değerini saklayacak.

Her katta birer sıra boşluk bırakacağım. Bu yüzden 120 taş dizeceğim. Seçim havuzunu hesaplayacağım p() dizisi için 120 değer yeterli olacak. Seçilen taşlar içinse 3 elemanlı bir dizi yeterli olacak.

50 rem *** secim havuzunu hazirlayalim
60 for i=0 to 120 :p(i)=int(i/8)+1: nexti

Seçim havuzuna taşları 8'li gruplar halinde dizmek için ufak bir numaraya başvuracağım. int(i/8) deyiminin sonucu 8 döngüde 1 artıyor.

70 gosub 2000: rem acilis mesaji

Açılış mesajını yazmak için altprograma dallanacağım.

80 rem *** taslari karistiralim
90 print "{clr}{down}{yel} taslar karistiriliyor"

Kare Kaplumbağa'yı petcat kullanarak yazdığımı söylemiş miydim? petcat'in bir güzelliği de 64 klavyesi kullanmadan yazamayacağınız özel karakterleri süslü parantezler '{' ve '}' )yardımıyla yazmanıza olanak vermesi. {clr}{down}{yel} ekranı temizle, bir satır aşağı in, sarı renge geç anlamına geliyor.

100 for i=120to0 step-1
110 r=rnd(i)*i:c=p(i):p(i)=p(r):p(r)=c:poke1103,i:nexti:poke1103,32

Seçim havuzundaki taşları karıştırıyorum.

120 rem *** oyun alanini cizelim
130 print "{clr}{home}":print"{grn}             kare kaplumbaga":print
140 fori=0to39step2:poke1144+i,206:poke1145+i,205:poke2023-i,206:poke2022-i,205:nexti
150 fori=4to22step2:poke1024+i*40,205:poke1024+(i+1)*40,206:poke2143-i*40,205:poke2143-(i+1)*40,206:nexti

Oyun alanı etrafındaki çerçeveyi çiziyorum.

200 rem *** taslari dizelim
210 k=0
220 for z=0 to 3: for y=0+z to 6-z: for x=0+z to 6-z: gosub1100: k=k+1:nextx:nexty:nextz

Sıra taşları dizmekte. Oyun alanının her seviyesinde (z) için satır(y) ve sütün(x) için bir taş yerleştiriyorum. hangi taşı kullanacağımı (k) değişkeniyle belirtiyorum.

230 for i=347 to 880 step40: poke1024+i,102: poke55296+i,0: next
240 for i=854 to 866: poke1024+i,102: poke55296+i,0: next

Biraz da estetik. Taşları dizdikten sonra altlarına gölge çizeceğim.

250 cn=84 : poke 1260,(cn/10+48) : poke 1261,(cn-int(cn/10)*10+48)

Oyun alanında kaç taş olduğunu ekrana basıyorum.

260 poke 214,23:poke 211,5:sys 58732
270 print "{grey2}tahtayi sifilarlamak isin 's'"

Her oyun çözülebilir değil. Bunun manası oyun sık sık tıkanacak ve sıfırlamak gerekecek. Bu yüzden bir 'sıfırlama' tuşu atamak gerekli. Kursoru satır 23, sütun 5'e aldıktan sonra. Bununla ilgili notumu yazıyorum.

280 time$="000000"

Ana döngüye girmeden önce. Zaman sayacını sıfırlayacağım.

Ana döngü

300 rem *** ana döngü
310 t=55296+293+y*80+x*2: poket,1: poket+1,1: poket+40,1: poket+41,1

Taşları dizerken x ve y değişkenlerini kullanmıştık. x ve y hala son yerleştirlen taşın pozisyonu saklıyor. Renk belleğinde bu pozisyona denk gelen alanları değiştirerek taşı beyaza boyayacağım. Böylece döngünün sonunda tekrar orjinal renge boyadığımda bir flash efekti oluşacak.

320 jj=peek(56320) : if (jjand16)=0 then gosub1300
330 jj=15-(jjand15)
340 if jj=1 then dy=-1 : goto380
350 if jj=2 then dy=+1 : goto380
360 if jj=4 then dx=-1 : goto380
370 if jj=8 then dx=+1 : goto380

Joystick'i kontrol etme zamanı. İlk olarak ateşe basılıp basılmadığına bakıyorum. (Bit 4) Ateşe basıldığında program taş seçme rutinine dallanacak.

Ateşe basılmadıysa yönleri kontrol edebilirim (Bit0-3). Burada Joystick'i aynı anda iki yöne çekmek mümkün olmadığı için işi tek bir AND komutuyla halleden eski bir numaradan fayfdalandım.

380 i=x+y*7
390 poket,bc(i):poket+1,bc(i):poket+40,bc(i):poket+41,bc(i)

310'uncu satırda beyaz yaptığım taş rengini düzeltiyorum. (flash efekti)

400 x=x+dx: dx=0: y=y+dy: dy=0
410 if x<0 then x=6
420 if x>6 then x=0
430 if y>6 then y=0
440 if y<0 then y=6

Yukarıda hesapladığım dy ve dx değerlini uyguladıktan sonra koordinatları kontrol etmeliyim. Kursor oyun alanının dışına çıkmamalı.

450 poke 214,5:poke 211,2:sys 58732
460 t$=time$: print "{yel}";mid$(t$,3,2);":";right$(t$,2)

Sol tarafta geçen süreyi basıyorum.

470 geta$:ifa$="s"then80

'S' tuşuna basılıp basılmadığını kontrol ediyorum. Eğer basıldıysa oyunu sıfırlayacağım. Bunun için taşları karıştırdığım satıra geri dönüyorum.

480 goto300

Ana Döngü burada bitiyor.

Alt programlar

1100 rem *** tas yerlestirme
1110 i=x+y*7
1120 if z=0 then bc(i)=15
1130 if z=1 then bc(i)=3
1140 if z=2 then bc(i)=13
1150 if z=3 then bc(i)=7
1160 b(i)=p(k) : bz(i)=z : t=1317+y*80+x*2
1170 poket,b(i)+128 : poket+1,103+128 : poket+40,111+128 : poket+41,122+128
1180 t=t-1024+55296
1190 poket,bc(i): poket+1,bc(i): poket+40,bc(i): poket+41,bc(i): return

Taş yerleştirme rutini, o anki x ve y koordinatlarında olması gereken taşı çizer.

1300 rem *** tas secme
1310 z=bz(x+y*7) : zl=-1 : zr=-1
1320 if x>0 then zl=bz(x+y*7-1): rem soldaki taşın yüksekliği
1340 if x<6 then zr=bz(x+y*7+1): rem soldaki taşın yüksekliği
1350 if (z<=zl)and(z<=zr) then poke 53280,4:i =i+1: i=i-1: poke 53280,11: return
1360 if p=0 then c(p)=b(x+y*7): poke1340,c(p): x1=x: y1=y: z1=z: p=1: return
1370 if p=1 then c(p)=b(x+y*7): poke1341,c(p): x2=x: y2=y: z2=z: p=2
1380 if p=2 and x1=x2 and y1=y2 then p=0: poke1340,32: poke1341,32: return
1390 if c(0)<>c(1) then p=0: poke53280,0: poke1340,32: poke1341,32: poke53280,11: return
1400 rem *** bundan sonra taslari topluyoruz
1410 x=x1 : y=y1 : if z1=0 then gosub1500 : goto 1430
1420 z=z1-1: gosub1100
1430 x=x2 : y=y2 : if z2=0 then gosub1500 : goto 1460
1450 z=z2-1: gosub1100
1460 poke1260,32: poke1261,32: p=0: poke53280,1: poke53280,11
1470 cn=cn-2 : poke 1260,(cn/10+48) : poke 1261,(cn-int(cn/10)*10+48)
1480 if cn=0 goto 2200: rem kutlama mesajı
1490 p=0 : poke1340,32 : poke1341,32 : return

Ana döngü joystick'in tuşuna basıldığında bu alt programa dallanıyor.

1300-1390 taş seçme:

1400-1490 taş toplama:

1500 rem *** tas silme
1510 i=x+y*7: bc(i)=0
1520 b(i)=102: bz(i)=-1 : t=1317+y*80+x*2
1530 poket,102 : poket+1,102 : poket+40,102 : poket+41,102
1540 if y=0 then poket,32: poket+1,32
1550 if x=0 then poket,32: poket+40,32
1560 t=t-1024+55296
1570 poket,bc(i): poket+1,bc(i): poket+40,bc(i): poket+41,bc(i): return

Toplanan taşların altı boş olduğunda toplanan taşların yerine gölge deseni çizmek için. bu alt programa dallanılıyor. Taşın pozisyonuna göre tam veya parçalı gölge deseni çiziliyor.

2000 rem *** acilis mesaji
2010 poke53280,12:poke 53281,11
2020 print "{clr}{home}":print"{grn}            kare kaplumbaga":print
2030 print "{gry3} kare kaplumbaga bir mahong solitare   "
2040 print " turevidir.":print
2050 print " oyunun amaci dizili taslari ikiserli "
2060 print " olarak eslestirerek 84 tasin hepsini"
2070 print " toplamaktir.":print
2100 print " renkler yukseklikleri temsil eder"
2110 print " 1.seviye - {gry2}gri{gry3}   3.seviye - {lgrn}yesil{gry3}"
2120 print " 2.seviye - {lblu}mavi{grey3}  4.seviye - {yel}sari{grey3}":print
2080 print " sadece sagi veya solu bos olan taslari"
2090 print " kullanabileceginizi unutmayin":print""
2140 print"{grn} baslamak icin her hangi bir tusa basin":print
2150 print"{yel}                               wizofwor"
2160 geta$:ifa$=""then2160
2170 print"{clr}":return
2200 rem *** kutlama mesajı
2210 print "{clr}{down}{down}{down} kutlarim. oyunu kazandiniz :)":print
2220 print " toplam sure:";mid$(t$,3,2);":";right$(t$,2):print
2230 print "{lblu} yeniden baslamak icin bir tusa basin"
2240 geta$:ifa$=""then2240
2250 print"{clr}":goto 80

Mesajları basan alt programlar için açıklama yazmaya gerek yok. Bu rutinler açılış ve oyunun sonundaki kutlama mesajları için.

Kare Kaplumbağa

Yazının başında Kare Kaplumbağa ismi açıklayacağımı söylemiştim. Mahjong aslında bizdeki Okeye benzeyen bir oyun. Mahjong taşlarını üst üste dizerek oynanan bu oyunun tam adı ise Mahjong Solitaire, Shangai Mahjong veya Turtle Mahjong. Turtle Mahjong'da taşlar bir kaplumbağayı andıracak düzende diziliyor. Benim versiyonumda taşlar kare şeklinde dizildiği için oyunun adı Kare Kaplumbağa oldu.