October 19, 2012

Alıntı (Salih Dinçer):

>

in ile const arasında hiç bir fark yok!

Aslında var ama derleyiciler scope'u henüz desteklemiyor: in, 'const scope'un eşdeğeri. Yani hem değiştirilemez (const), hem de işlevden dışarıya kaçırılamaz (scope).

Alıntı:

>

kullanmadığımız zaman parametre değişkenlerine bellekte farklı bir şekilde yer ayrılıyor

Orası derleyicinin bileceği iş. :) Tabii biz bu belirteçlere anlamsal açıdan yaklaşmalıyız.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 19, 2012

Alıntı (mert):

>

Acaba: "Eğer gelişmekte olan bir programlama dilinde ..."

Zararı yok ama gerek de yok.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 28, 2012

Bayramı fırsat bilerek programımızı terkeden kahramanımız, epey semirmiş ve dinlenmiş olarak geriye döndüğünden ve artık onun diğer silahlarını da başarıyla kullanabileceğine inandığımız yetenekli bir işlevi olduğunu düşündüğümüzden diğer ek silahları olan "kılıç, tabanca, tüfek, bomba" kullanımı ile ilgili tasarımımızı artık gerçekleştirebiliriz.

Kahramanımızın bayramda ceplerini parayla doldurmuş olduğunu bildiğimizden (büyüklerin elleri, küçüklerin gözleri:-), hazır kendisine ek olanaklar sağlamaya kalkışmışken, kendisine bu parayı oyunun içinde kullanma şansını da tanımamız gereksin.

Bu durumda kahramanımız; hem düşmanları ile karşılaşırken aldığı darbelerde enerjisinden ve parasından bir miktar kaybedecek, hem de ilerleyen aşamalarda elindeki parayı da kullanarak elde edeceği "bisiklet, motosiklet, atv, pikap, tank" gibi araç gereçlerini kullanacak.

Peki bu durumda programımı nasıl gerçekleştirebilirim?:

1 - Kahramanımın edinebileceği; bıçak, kılıç, tabanca, tüfek, bomba silahlarını ve bisiklet, motosiklet, atv, pikap, tank gibi araçlarını kullanabilmek için isimli sabit değerlerden yani enum'dan yararlanabilirim.
2 - İkinci aşamada tanımladığım işlevi bıçakDarbesiniHesapla() yerine, 'enerjisiniHesapla()' olarak yeniden düzenlersem, kahramanımızın vurduğu/aldığı darbeleri bu işlevde hesaplattırır kazandığı/ kaybettiği enerji değerlerini ölçebilirim.
3 - Benzer bir ek işlev daha tasarlayıp kazandığı/kaybettiği para değerlerini de ona hesaplattırabilirim. Onun adına da 'parasınıHesapla()' deyip geçiveririm.

Böylece iki işlev ve bir enum türü ile programımın şimdiki bölümünü tasarlayabilirim.

Hımm, işe yarar görünüyor. Deneyelim görelim:

import std.stdio;

enum DarbeTipi { Bıçak = 10, Kılıç = 25, Tabanca = 55, Tüfek = 70, Bomba = 90 }

double enerjisiniHesapla (in double enerji, DarbeTipi darbe)  //[1]
{
   double enerjiÖlçeği = enerji - (darbe * 1_000);
   return enerjiÖlçeği;
}

double parasınıHesapla (in double para, DarbeTipi darbe)      // [1]
{
   double paraÖlçeği  = para - (darbe * 500);
   return paraÖlçeği;
}

void main()
{
   double kahramanınEnerjisi = 100_000;
   double kahramanınParası   = 100_000;
   enum darbe                = DarbeTipi.Bomba;

   double kahramanEnerjisi   = enerjisiniHesapla(kahramanınEnerjisi, darbe);
   double kahramanParası     = parasınıHesapla(kahramanınParası, darbe);

   writeln("Kahramanın Enerjisi : ", kahramanEnerjisi);
   writeln("Kahramanın Parası   : ", kahramanParası);
}

'// Kahramanın Enerjisi : 10000
// Kahramanın Parası : 55000'

Evet ama, daha düşmanın enerjisi ve parasını hesaplayacağım değil mi? Hem kahramanımız sadece bir düşman ile karşılaşacaksa bunun adı da oyun olmaz zaten. Çok sayıda ve farklı yeteneklerde, farklı araç gereçler kullanan düşmanlardan söz edeceksek eğer, ben her karakterin sadece para ve enerji durumları için bile iki farklı işleve başvurmalıyım.
Yine ayrıca işlevlerim tamı tamına birbirinin aynısı. Yani aslında temelde yapılan iş bir adetken ben bu işi iki ayrı işlev kullanarak yapabiliyorum.
Bu sorunun olası bir çözümü de tek bir işlev kullanarak hem enerji hem para değerlerini o işleve hesaplattırmak ve elde edilen enerji ve para değerlerini bir dizi halinde döndürüp gerektiğinde kullanmak.

Ancak bu defa da, kodlarım olması gerekenden daha fazla karmaşık olacak ki, programımızda sade bir yapı istediğimizi en başından söylemiştik.

Yeterince palazlandığımız başka nasıl belli olacak?

[1] Dikkat edileceği gibi aslında her iki işlevimizde aynı işi yapmakta.

İlgi: http://ddili.org/ders/d/yapilar.html

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 29, 2012

Hıhım.
Alıntı:

>

acehreli:
Yine herhalde ileride geliştireceksindir ama ben yine de karışayım. :)

Karışmak ne demek :-) Ne kadar katılım o kadar anlaşılırlık. Hep karışın lütfen.Her biriniz konuya katışın ki çeşitlensin. Mutlaka değinmeyi unuttuğum birşeyler kalacaktır geride. Ne kadar az kalırsa o kadar iyi. Çünkü gerekli gereksiz bir sürü soru oluşuyor kafalarda bu aşamalarda genellikle. Nasıl yapsam sorusuna yanıt da arıyoruz.

Enum burada başlangıç yaklaşımı yani ilk akla gelen. Daha sınıflardan bihaberiz, eldeki olanakların yapılara kadarı öğrenilmiş, uygulanmaya çalışılıyor. Yapılar dersi, nesne yönelimli programlamayı oldukça geniş özetliyor. Aslında bBu dersin sonunda programcımızın kafasında sizin de belirttiğiniz gibi bir ışık yanacak. Engebeli yollardan uzaklara gidilmesinin ne kadar zor olduğu anlaşılacak. vs. vs.. Hikâye yazıyoruz öte yandan :-)))

Alıntı:

>

acehreli: DarbeTipi'ni bir tür olarak kullanıyorsun ve zaten de öyle olmalı.

Ona rağmen işlev içinde

double enerjiÖlçeği = enerji - (darbe * 1_000);

gibi basit bir hesaba gerek görülmesi bile enum'un bizi yolda bırakabileceği mesajını veriyor. Olması gereken tasarım sizin şurada belirttiğiniz http://ddili.org/forum/post/3767 gibi olacak sona doğru.

Belki orada özellikler, sarma gibi yöntemlere de değinebiliriz diye düşünüyorum.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 28, 2012

Yine herhalde ileride geliştireceksindir ama ben yine de karışayım. :)

DarbeTipi'ni bir tür olarak kullanıyorsun ve zaten de öyle olmalı. Ancak, bu türün değerlerinin o türün bütün sorunlarını çözebilmesi biraz şans oluyor. Örneğin, o türün enerjisi değerinin bin katı olarak ve parası değerinin beş yüz katı olarak hesaplanabiliyor. Tabii ki bu genel hesap her tür için doğru olmayabilir.

O yüzden herhalde daha sonra sınıflar kullanarak NYP'ye geçeceksin. (?) O zaman her tür kendi özel değerlerini üye işlevlerinin dönüş değerleri olarak sağlayabilir.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 29, 2012

Alıntı (mert):

>

Yine ayrıca işlevlerim tamı tamına birbirinin aynısı. Yani aslında temelde yapılan iş bir adetken ben bu işi iki ayrı işlev kullanarak yapabiliyorum.
Bu sorunun olası bir çözümü de

Ben bu sözlerden çok yakında (belki 4. aşamada) NYP'ya geçeceğimizi algılıyorum. Muhtemelen o zaman her şey daha güzel olacak.

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

October 29, 2012

Alıntı:

>

Ben bu sözlerden çok yakında (belki 4. aşamada) NYP'ya geçeceğimizi algılıyorum. Muhtemelen o zaman her şey daha güzel olacak.

Haklısın Salih hocam. Çok uzatmadan nyp'ya aktarmalıyız :-)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 09, 2012

Merhaba,

Tartışmamızdan bu yana 1 aydan fazla zaman geçmiş...

Bakın Allah'ın işine ki ben de tam 1 aydır Legend (http://ddili.org/forum/thread/1023) oynuyorum; forumda bahsetmiştim. Diyebilirim ki bu tür oyunlarda uzmanlaştım. Bunlar gerçekten çok karışık şeylermiş. Görünen o ki bu tür oyunlar (Knight, Hereos, Legend, Metin2) çoğunluk tarafından seviliyor. Türü de MMOG oluyor zannedersem. Düşünsenize bir sürü oyun, sunucu, kahraman ve bir o kadar insan birbirleriyle sanal ortamda mücadele ediyor. Belki de devletler kozlarını bu ortamlarda paylaşmalı...:(
'(İşte bu fikir silaha giden paranın insanları yaşatmaya, ölümlerin olduğu askerlik mesleğinin de rafa kaldırılmasına sebep olabilir!)'

Neyse, konumuz yazılım olduğuna göre bu oyunlara kulağımızı kapamamız gerekiyor. Hiç grafik olaylarına girmeden bile o kadar çok kavram var ki işin içinden çıkmamız için iyi bir planlama şart. Ama temelde bir Kahraman sınıfı olmalı ve gerek düşman, gerek okçu, gerekse büyücü gibi karakterler (bu dünyada Caesar veya Lord diyorlar) bundan türeyebilmeli. Şöyle basit bir örnek hazırladım:

class Kahraman {
   real can = 100.0;   // can > 0 ise yaşıyor
   ubyte seviye = 1;   // can * seviye = gerçek gücü (HP)
   uint savunma = 1;   // reserved (sihire karşı olabilir?)
   uint saldırı = 1;   // büyücüde sihirli saldırı olacak

   this(int savunmaGücü, int saldırıGücü, int hasarOranı) {
       this.can = (can * cast(real)seviye)
                       * cast(real)savunmaGücü;
       this.savunma = savunmaGücü;
       this.saldırı = (hasarOranı * cast(uint)seviye)
                                  * saldırıGücü;
   }

   bool vur(Kahraman k) {
       if(can > 0) {
         k.can -= cast(real)saldırı;
         return false;
       }
       return true;
   }

   bool yaşıyor_mu() {
       return can > 0;
   }

   void sonrakiSeviye() {
       saldırı *= ++seviye;
   }

   string toString() {
       string durumu = format(" canı %.0f ve ", can);

       if(yaşıyor_mu) durumu ~= "yaşıyor...";
       else durumu ~= "yaşamıyor.";

       return durumu;
   }
}

 import std.stdio, std.string;

void main() { // savunma ----v   v---- saldırı
   auto okçu = new Kahraman(40, 40, 5); // <---- hasar
   auto kurt = new Kahraman(10, 10, 5);

   kurt.sonrakiSeviye;  // kurt level 2;
   kurt.sonrakiSeviye;  // kurt level 3;
   //kurt.sonrakiSeviye;  // kurt level 4;

   while(true) { // musabaka döngüsü (test amaçlı)
     if(okçu.vur(kurt)) break;
     if(kurt.vur(okçu)) break;

     okçu.can.writeln(" (okçu)");
     kurt.can.writeln(" (kurt)");
   }

   "Okçu".writeln(okçu);
   "Kurt".writeln(kurt);
}

Belki de çalışan en basit kod budur. Çünkü sırayla vuruş yapılan bir düelloyu canlandırabiliyorsunuz. Eğer karakterinizin değeri iyi ise galip çıkıyor...

Ancak olay bitmiyor!

Örneğin iksir olayları var; mesela güç iksiri içerseniz, atıyorum 1 saat (iksirin etkisini yitirme süresi) boyunca hasar oranınız %2 artıyor olabilir. Aynı şekilde savunma (defence), can (HP ~ beden) vb. şeyler var. O yüzden bu sınıfın içine, zamanlama işlevi olan bir türü, dizi olarak koymamız gerekiyor. Bunu düşünüyorum...

Sonra silahlar var. Şimdi, yukarıdaki örnekte okçu kullandığım için (kurtun da dişleri var) çok ayrıntıya girmemiş oldum. Ancak kasktan tutun da üzerinize taktığınız aksesuara kadar (biz buna eşya yani item diyelim) çok şey var. Her birinin herhangi bir veya daha fazla özelliğinize olumlu etkisi var. Belki bunlar işin ilgi çeken ayrıntısı. Ama silah ile donatmak veya donatılanı başka bir değerli eşya ile değiştirmek önemli. Böylece sonsuz çeşitlikte karakterler oluşuyor!

Neyse, o kadar çok şey yazabilirim ki vaktinizi almayayım. Onun yerine bir soru sorayım: Bu kahraman bir okçu değil de büyücü olsaydı sınıfı ilerisi için nasıl olgunlaştırırdık?

Ek bilgi de vereyim. Büyücülerin saldırısı yerine sihirli saldırısı var ve doğal olarak da sihirli savunması. Aslında her karakterin sihirli savunması var. Çünkü rakip (düşman) sihir yapabilir. Örneğin cinler, periler geliyor. Hatta bunlar birden fazla geliyor!

Dip Not: Sonraki aşama ordu kavramı olabilir? Öyle ki her bir kahraman diğer kahramana birleştiriliyor. Bir ekip oluyorsunuz ve oyunda tek karakter olarak görünüyor. Bunu da pratik bir şekilde çözebileceğimizi düşünüyorum.

Başarılar...

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 09, 2012

İsimlerine bakarsak, Kahraman üst sınıf, Okçu, Büyücü, vs. de alt sınıf oluyor. Önemli olan hangi işlemlerin ve verinin her Kahramanda mutlaka buldunduğunu belirlemek ve onları Kahraman düzeyinde gerçekleştirmek. Her kahramanın özel işlemleri ve verileri de o özel kahraman düzeyinde gerçekleştirilebilir.

Yukarıdakiler en temel kavramlar. Bunların üzerine yararları görüldükçe design patterns da uygulanabilir.

Benim sıradüzenlerde karşılaştığım bir yapı şöyle:
'
Kahraman
|
KahramanOrtak
/
İksirleÖlen İksirleGüçlenen (bu düzey ve alttaki böyle olmak zorunda değil)
/ / \ /
Okçu ... ... ... Büyücü
'

  • interface Kahraman: Bir interface. Burada her kahramanda olan ve oyunda gereken bütün işlemler bulunur: karşılaş(Kahraman k), yaşıyor_mu(), iç(Eşya e), al(Eşya e), vs.

  • class KahramanOrtak: Her kahramanda bulunan ortak özellikler buradadır. Örneğin her kahramanın canı varsa buraya gelebilir: real can, real seviye, vs.

  • class İksirleÖlen ve İksirleGüçlenen: iç() işlevine İksir geldiğinde can=0 olur veya olmaz.

  • class Okçu, Büyücü, vs. Bunlar her kahramanın en özel işlemlerini ve verilerinin tutarlar.

Yukarıda en alttaki iki düzey aslında öyle olmak zorunda değil. İksirleÖlen veya İksirleGüçlenen gibi ikili (veya çoklu) ayrımlar sıradüzende düzey olamazlar çünkü onun gibi bir çok farklı olanak bulunabilir.

iç(Eşya e) işlevine tekrar bakarsak, belki de bir yöntem, bu türlere belirli eşya içildiğinde ne olacağını anlatan işlevleri kurucularında vermektir:

class Okçu : KahramanOrtak
{
   this(/* ... */)
   {
       // ...
       super.içmeEtkisiEkle(new İksirleÖlme(/* ... */));
   }
   // ...
}

KahramanOrtak'a yapılan o çağrı, KahramanOrtak'ın "içince neler olsun" bilgisini tutan diziye bir bilgi ekler. Eğer iç(Eşya e) işlemi KahramanOrtak düzeyinde gerçekleştirilirse, eldeki "neler olsun" dizisinde ilerlenir ve bu kahramanda gereken değişiklikler yapılabilir.

class KahramanOrtak : Kahraman
{
   real can;
   İçmeEtkisi[] içinceNelerOlsun;

   void içmeEtkisiEkle(İçmeEtkisi ii)
   {
       içinceNelerOlsun ~= ii;
   }

   void iç(Eşya e)
   {
       foreach (etki; içinceNelerOlsun) {
           etki.etkile(this, e);

           if (!yaşıyor_mu()) {
               break;
           }
       }
   }

   // ...
}

Garip ayrıntılara daldım ama umarım kahramanlar arasındaki farklılıkların nasıl her tür tarafından bilinmesinin gerekmediğini gösterebilmişimdir. Her ne kadar kahramanın canını KahramanOrtak yönetiyor bile olsa, aslında iksir içince ölünme kavramından onun bile haberi yok. Onun tek bildiği, bir eşya içince bazı etkilerin olabildiği. Tek yaptığı, içilen eşyayı (ve kahramanın kendisini) o etkilere geçirmek ve onların kahramanı etkilemesini sağlamak.

Tabii onun işleyebilmesi için İçmeEtkisi'nin de bir interface olması çak yararlıdır:

interface İçmeEtkisi
{
   void etkile(Kahraman k, Eşya e);
}

class İksirleÖlme : İçmeEtkisi
{
   void etkile(Kahraman k, Eşya e)
   {
       // Eğer içilen bir İksir ise k'nin canının sıfır yap
       // Hatta, belki de Kahraman'ın asıl türüne göre farklı etki bile yapılabilir.
   }
}

NYP'nin sorunlu taraflarından birisi de tam o noktada başlar. Veya şöyle söyleyelim: çoğu NYP dilinde bulunmayan bir olanak tam o noktada gerekir: Yukarıda etkile() içinde İksirleÖlme sınıfında olduğumuzu biliyoruz. Yani eşya bir İksir olduğunda kahramanı öldüreceğiz ama elimizde yalnızca bir Eşya var. Onun İksir olduğunu nasıl bilebiliriz?

Tekrar bakalım: etki.etkile(this, e) yapılan yerde tek bir türe göre havale yapılmıştır. Dil bize tek tür üzerinde havale olanağı sunmuştur: etki'nin asıl türü (çalışma zamanındaki türü, dinamik türü) İksirleÖlme olduğu için programın akışı İksirleÖlme.etki() işlevine geçmiştir. Ama görüldüğü gibi, bu tek tür üzerinden olmaktadır: Program akışı Kahraman'ın ve Eşya'nın çalışma zamanındaki türlerine bağlı olmamıştır. NYP'de bu sorunun adı "double dispatch"tir (hatta bu durumda belki de "multiple dispatch").

Double dispatch C++ veya D tarafından sağlanmaz (başka dillerde var mı, bilmiyorum). Bunun çözümü programcının görevidir. Bir çözüm, Eşya'nın typeid'sine bakmak ve İksir ise ona göre davranmaktır. typeid Eşya'nın çalışma zamanındaki asıl türünü verir. Ama bu bilgiye bakma gereği, saf NYP'den uzaklaşma anlamına gelir ve dilin yetersizliği olarak görülür.

Ama bunlar göz korkutmasın. Ben saf NYP uygulandığında karşılaşılabilecek bir sorun olarak gösterdim. Başka çözümler de bulunabilir. NYP'de (OOP'de) "Double dispatch"i araştırmak gerek.

Temellerimize dönersek, bu gibi işler NYP'nin olmadığı C gibi dillerde bile yapılabildiğine göre aslında o kadar zorlamaya gerek yok. Belki de en basit yöntem neyse onu uygulamak en iyisi... :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

December 10, 2012

Hocam çok güzel yazmışsın eline sağlık...

Ben zannedersem, daha basit bir yapı düşünüyorum ama interface konusunu unutmuşum; neden olmasın! Zaten bir süre sonra böyle bir yapı kaçınılmaz olacak. Ama konunun gelişimi açısından basit parçalar ile yola devam etsek nasıl olur?

Örneğin zamanlama konusunda bugün şöyle bir şey yazdım: http://dpaste.dzfl.pl/4018d6c4

Aynı şekilde süresiz eşyalar, zaman damgası olmadan da kullanılabilir. Aslında daha eklenecek çok şey var. Bunlardan biri de 'durumuYedekle()' ve 'geriYükle()' gibi iki üye işlev. Çünkü musabaka öncesi güncel durum yedeklenip bittiğinde geri yüklenmesi gerekiyor. Bu tür oyunlar çok elli musabakalar şeklinde düzenlendiği için böyle bir kural var...

Mert Hocam, sen ne düşünüyorsun? Hızlı girmedik inşaallah...:D

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]