Buatlah Tamagotchi / Giga Pet yang disederhanakan!

9

Tamagotchi dan Giga Pets adalah perangkat elektronik kecil yang disimulasikan sebagai hewan peliharaan virtual kecil. Hewan peliharaan ini memiliki beberapa statistik, seperti kesehatan, kelaparan, dll.
Saya baru-baru ini menulis contoh ini:

import msvcrt,os,sys;d=m=100;h=s=t=p=0;f=10
while 1:
 os.system('cls'if os.name=='nt'else'clear');print("health:",d,"\nhunger:",h,"\nsleep:",s,"\nfood:",f,"\npotions:",p,"\nmoney:",m);t+=1
 if msvcrt.kbhit():
  k=ord(msvcrt.getch())
  if k==102 and h>8 and f:f-=1;h-=9
  if k==115:s=0
  if k==112 and p:p-=1;d+=9
  if k==98 and m>8:m-=9;p+=1
  if k==116 and m>8:m-=9;f+=1
 if t>99:
  t=0;h+=1;s+=1
  if s>80:s=0;h+=9
  if h>80:d-=1
  if d<1:sys.exit(0)
  if d>79:m+=1

Ini adalah hewan peliharaan virtual tanpa tulang dalam 467 byte! Saya kemudian bertanya-tanya seberapa bagus pro golf code bisa melakukannya, jadi sekarang, tantangannya.

Tantangan

Buat program yang melacak 6 statistik hewan peliharaan virtual, dan perbarui dari waktu ke waktu dan sebagai respons terhadap input pengguna. Statistiknya adalah: kesehatan dan uang (mulai dari 100), makanan (mulai dari 10), dan kelaparan, tidur, dan ramuan (mulai dari 0).

Program harus memperbarui nilai sebagai respons terhadap peristiwa berikut:

  • Ketika program tidak menerima input, program harus melakukan pembaruan secara berkala (interval antara pembaruan tidak boleh lebih pendek dari setengah detik atau lebih lama dari satu detik). Setiap pembaruan melakukan hal berikut:

    • Lapar dan Tidur masing-masing bertambah 1.
    • Jika Kelaparan 80 atau lebih, Kesehatan berkurang 1.
    • Jika Sleep adalah 80 atau lebih, itu diatur ulang ke 0, dan Hunger bertambah dengan tambahan 9.
    • Jika Kesehatan 80 atau lebih, Uang bertambah 1.
    • Jika Health adalah 0, program keluar.
  • Program juga harus segera merespons penekanan tombol berikut oleh pengguna (ini berarti Anda harus menggunakan fitur bahasa atau pustaka yang dapat mendeteksi kunci yang ditekan dan meresponsnya segera, daripada hanya membaca dari input standar), melakukan tindakan berikut:

    • f: Jika Kelaparan lebih besar dari 8 dan Makanan bukan nol, maka Makanan berkurang 1 dan Kelaparan menurun 9.
    • s: Tidur diatur ulang ke 0.
    • p: Jika Ramuan lebih besar dari nol, Ramuan berkurang 1 dan Kesehatan meningkat 9.
    • b: Jika Uang lebih besar dari 8, maka Uang berkurang 9 dan Ramuan bertambah 1.
    • t: Jika Uang lebih besar dari 8, maka Uang berkurang 9, dan Makanan meningkat sebesar 1.

Setiap kali nilai statistik berubah, mereka harus ditampilkan di layar dalam formulir . Keenam statistik harus ditampilkan setiap kali ada perubahan; dan statistik dalam tampilan harus dipisahkan dengan koma atau baris baru.Stat: value

Tantangan ini mengikuti aturan normal : program terpendek yang memenuhi spesifikasi menang di atas. (Perhatikan bahwa seperti biasa, jika bahasa lebih baru daripada kompetisi, pengajuan harus ditandai sebagai tidak bersaing.)

ender_scythe
sumber
Anda tidak mengatakan apa statistik awal
Biru
1
Keluaran harus dalam "cara yang mudah dibaca" adalah ambigu, dan karenanya "ish sekali per detik". Anda harus mengirimkan tantangan ke kotak pasir untuk mendapatkan umpan balik dan meningkatkannya sebelum Anda memposting ke utama ...
FlipTack
1
Bagaimana ini tidak jelas? Saya berharap tidak jelas memiliki lebih banyak detail, karena itu sendiri tidak jelas.
ender_scythe
2
Sandbox tidak membantu lagi, karena sudah ada jawaban. Orang-orang yang telah menandai ini sebagai tidak jelas harus mengatakan mengapa itu tidak jelas, bukannya menjadi tidak jelas sendiri.
ender_scythe
1
@BlueEyedBeast (dan pemilih dekat lainnya) Saya juga ingin tahu apa yang tidak jelas. Versi asli memiliki beberapa masalah yang signifikan, tetapi sepertinya pengeditan memperbaikinya. Paling tidak, sudah cukup jelas bagi Carcigenicate dan saya untuk memberikan pengiriman. Bagikan beberapa detail tentang apa yang Anda temukan tidak jelas sehingga ender_scythe dapat memperbaikinya.
Ray

Jawaban:

6

C, 424 406 386 357 byte

#define x(a,b,c)if(*#a==C){if(b>8){c-=9;}Z=0;}
L,M=100,H,S=-1,F=10,P,Z,C;t(){H++;S++;L-=H>79;if(S>79)S=0,H+=9;Z=1/L/2;alarm(1);}main(){nodelay(initscr(),L=M);signal(14,t);for(t(H=S);C=getch();Z=Z||printf("\rhealth: %d,hunger: %d,sleep: %d,food: %d,potions: %d,money: %d\n",L,H,S,F,P,M)){x(s,9,S=9;S)x(p,P+8,P--;L+=18;L)x(f,H,F--;H)x(b,M,P++;M)x(t,M,F++;M)}}

Saya menghargai perlunya input mentah dan pembaruan asinkron dalam spec masalah. Meskipun itu memerlukan beberapa overhead dari pengaturan ncurses dan penangan sinyal, senang memiliki tantangan sesekali yang (semoga) tidak akan otomatis dimenangkan oleh salah satu bahasa golf khusus.

Anda tidak menentukan secara pasti bagaimana permainan berakhir ditunjukkan, jadi yang ini lenyap dengan tangisan kematian Tamagotchi tradisional dari "Pengecualian titik mengambang (inti dibuang)".

Tidak disatukan

/* Playing a bit fast and loose with the prototyping rules by omitting these;
 * none of the functions I'm using from them *exactly* match the default
 * prototype of `int f();`
 */
//#include <curses.h>
//#include <stdio.h>
//#include <signal.h>
//#include <unistd.h>

#define x(a,b,c)if(*#a==C){if(b>8){c-=9;}Z=0;}
L,M=100,H,S=-1,F=10,P,Z,C;

t() {
    H++;
    S++;
    L-=H>79;
    if(S>79)S=0,H+=9;
    Z=1/L/2;//0 if L>0. otherwise the pet dies of a floating point error
    alarm(1);
}

main(){
    nodelay(initscr(),L=M);
    signal(14,t);
    for(t(H=S); C=getch(); Z=Z||printf("\rhealth: %d,hunger: %d,sleep: %d,food: %d,potions: %d,money: %d\n",L,H,S,F,P,M)){
        x(s,9,S=9;S)
        x(p,P+8,P--;L+=18;L)
        x(f,H,F--;H)
        x(b,M,P++;M)
        x(t,M,F++;M)
    }
}
sinar
sumber
2

PHP, 396 413 byte

(Sial, entri golf kode pertama saya yang harus saya edit dalam hitungan byte. Diedit untuk menghapus sleep () panggilan, karena tidak benar-benar mematuhi aturan yang dimaksudkan.)

Membutuhkan OS unix-ish untuk STDIN non-blocking. Anehnya, menggunakan switch / case versus cascading jika / yang lain menghasilkan kode sumber yang lebih pendek, tetapi versi terkompresi berikutnya lebih lama.

<?eval(gzinflate(base64_decode('bY5BT8MwDIXv/Ao0WWujtVJ7YmtITwiNAwhp3KutOE20pImWVGxa999J1IEAcbH87O892wlUqsEjtmnivD/d5rLd9qZPCHX+gFvdOPTNTpl2L/su3bw9PL1kBaEwMHAMLCsocFaGKhjo0BT0Q0iFaUnO4JmXGlPyPZI8TWHPeIe+nbIIGccJqsGTXbi4p4EKEEt4Qs6xH+rlfA6c5DnwEYacregFlcMvziUk/FLQnzN79drosiOIxV/X7kroeklAh9BxsQD7m/H/MXxi4iKoob5bxRuCTtpFHd8Jn8ab0S7iLOz0pO5LgkfpQ0wrzGyNW+VFBSJ7Nj2eKtDZozHvFfBsPfQdHioYso1CtBW47NV4aXpXgb2Z0csn')));

Tidak Disatukan:

<?
shell_exec('stty -icanon');
stream_set_blocking(STDIN, 0);
$u = $s = $p =0;
$f = 10;
$h = $m = 100;
while(1) {
    $t=time();
    while(1)
        if (($k = fgetc(STDIN)) || time() > $t)
            break;
    if ($k == 'f'){
        if ($u > 8 && $f) --$f | $u -= 9;
    } elseif ($k == 's')
        $s = 0;
    elseif ($k == 'p') {
        if ($p) --$p | $h += 9;
    } elseif ($k == 'b') {
        if ($m > 8) $m -= 9 | ++$p;
    } elseif ($k == 't') {
        if ($m > 8) $m -= 9 | ++$f;
    } else {
        if (++$u > 79) --$h;
        if (++$s > 79) $s = 0 | $u += 9;
        if ($h > 79) ++$m;
        if ($h < 1) exit;
    }
    echo"Health:$h,Money:$m,Food:$f,Hunger:$u,Sleep:$s,Potions:$p\n";
}
Alex Howansky
sumber
Ini tidak "segera merespons pada penekanan tombol berikut oleh pengguna". Ia menunggu hingga panggilan sleep(1)kembali sebelum memproses input. Meskipun itu memproses perintah yang antri sebelum melakukan pembaruan berikutnya, jadi mungkin baik-baik saja.
Ray
Ya, dicatat. Kata-katanya tidak jelas sehingga saya mengambil sedikit interpretasi karena cara ini lebih pendek. :) Jika saya punya waktu hari ini, saya akan mengkodekan solusi alternatif dengan loop waktu dan menyajikan keduanya untuk dipertimbangkan.
Alex Howansky
2

Mathematica, 374 byte

h=m=100;f=10;g=s=p=0;RunScheduledTask[g++;s++;If[g>79,h--];If[s>79,s=0;g+=9];If[h>79,m++];If[h<1,Quit[]]];Dynamic@Row[{EventHandler[InputField[],"KeyDown":>Switch[CurrentValue@"EventKey","f",If[g>8&&f>0,f--;g-=9],"s",s=0,"p",If[p>0,p--;h+=9],"b",If[m>8,m-=9;p++],"t",If[m>8,m-=9;f++]]],"
Health: ",h,"
Money: ",m,"
Food: ",f,"
Hunger: ",g,"
Sleep: ",s,"
Potions: ",p}]

Jeda baris penting karena mereka adalah karakter baris baru dalam string sehingga saya bisa menggunakannya Rowsebagai ganti Column. Jika Anda mengevaluasi ini di buku catatan Mathematica, Anda akan melihat sesuatu seperti ini:

Simulasi Tamagotchi

Anda harus mengklik di bidang input dan dengan cepat (kurang dari satu detik) mengetik karakter Anda sebelum Dynamicmenyebabkan bidang input diperbarui. Sakit kepala ini dapat dihindari sepenuhnya jika EventHandlerberada di selnya sendiri daripada menjadi elemen Row, tetapi itu akan membutuhkan menyimpan program sebagai file .nb yang akan sangat meningkatkan jumlah byte.

ngenisis
sumber
Kerja bagus! Saya akan menggunakan struktur seperti CurrentValue[EvaluationNotebook[], NotebookEventActions] = {"KeyDown" :> Switch[CurrentValue@"EventKey", "f", If[g > 8 && f > 0, f--; g -= 9], "s", s = 0, "p", If[p > 0, p--; h += 9], "b", If[m > 8, m -= 9; p++], "t", If[m > 8, m -= 9; f++]]};... ini harus membiarkan Anda menghindari kebutuhan untuk mengklik di kolom input. Menambahkan opsi , PassEventsDown -> Truepada bagian akhir kode itu akan memungkinkan Anda terus mengedit buku catatan, tetapi dapat dihapus di bagian paling akhir untuk penghematan byte :)
Greg Martin
Terima kasih, itulah fungsi yang saya cari pada awalnya! Sayangnya sepertinya lebih panjang dari yang saya miliki saat ini.
ngenisis
2

C # 6, 567 563 byte

using System;using System.Threading;class T{int L,M,F=10,H,S,P;static void Main(){T t=new T();}T(){M=L=100;var W=new Thread(new ThreadStart(Q));W.Start();while(1>0){var r=Console.Read();bool B=0>1,K=1>0;if(r=='f'&H>8&F>0){F--;H-=9;B=K;}if(r=='s'){S=0;B=K;}if(r=='p'&P>0){P--;L+=9;B=K;}if(r=='b'&M>8){M-=9;P++;B=K;}if(r=='t'&M>8){M-=9;F++;B=K;}if(B)p();}}void Q(){while(1>0){H++;S++;if(H>79)L--;if(S>79){S=0;H+=9;}if(L>79)M++;L*=L/L;p();Thread.Sleep(500);}}void p(){Console.Write($"\nhealth: {L}\nhunger: {H}\nsleep: {S}\nfood: {F}\nmoney: {M}\npotions: {P}\n");}}

Tidak Disatukan:

using System;
using System.Threading;
class T
{
    int L,M,F=10,H,S,P;
    static void Main()
    {
        T t=new T();
    }
    T()
    {
        M=L=100;
        var W=new Thread(new ThreadStart(Q));
        W.Start();
        while(1>0)
        {
            var r=Console.Read();
            var B=0>1;
            if(r=='f'&H>8&F>0){F--;H-=9;B=1>0;}
            if(r=='s'){S=0;B=1>0;}
            if(r=='p'&P>0){P--;L+=9;B=1>0;}
            if(r=='b'&M>8){M-=9;P++;B=1>0;}
            if(r=='t'&M>8){M-=9;F++;B=1>0;}
            if(B)p();
        }
    }
    void Q()
    {
        while(1>0)
        {
            H++;S++;
            if(H>79)L--;
            if(S>79){S=0;H+=9;}
            if(L>79)M++;
            L*=L/L;
            p();
            Thread.Sleep(500);
        }
    }
    void p()
    {
        Console.Write($"\nhealth: {L}\nhunger: {H}\nsleep: {S}\nfood: {F}\nmoney: {M}\npotions: {P}\n");
    }
}
Yodle
sumber
1

Clojure, 1224 702 byte

V2

Membuat semua atom kehilangan variabel bukannya berada di dalam objek negara. Itu saja menyingkirkan banyak kode. Saya juga membuat fungsi pintas a!dan s!untuk menambah dan mengurangi dari yang atomslebih mudah (pada dasarnya bertindak sebagai +=dan -=, karena Clojure tidak memiliki operator tersebut).

Saya menyadari bahwa saya mungkin dapat menghapus dengan atoms jika saya berhasil mengintegrasikan input kunci ke dalam loop. Saya harus melihat.

(ns bits.golf.pet.v2.petms)(def h(atom 100))(def j(atom 0))(def s(atom 0))(def f(atom 10))(def p(atom 0))(def m(atom 100))(defn a[sa n](swap! sa #(+ % n)))(defn v[sa n](swap! sa #(- % n)))(defn c[](a j 1)(a s 1)(if(>=@j 80)(v h 1))(if (>=@s 80)(do(reset! s 0)(a j 9)))(if(>= @h 80)(a m 1)))(defn l[k](case k\f(if(> @j 8)(do(v f 1)(v j 9)))\s(reset! s 0) \p(if(>@p 0)(do(v p 1)(a h 9)))\b(if(> @m 8)(do(v m 9)(a p 1)))\t(if(>@m 8)(do(v m 9)(a f 1)))nil))(defn b[](.start(Thread.^Runnable(fn[](while(>@h 0)(l(first (read-line))))))))(defn -main[](b)(while(>@h 0)(Thread/sleep 500)(c)(println(str"Health: "@h"\nHunger: " @j"\nSleep: "@s"\nFood: "@f"\nPotions: "@p"\nMoney:"@m"\n")))(println"You died!\n"))

Tidak Disatukan:

(ns bits.golf.pet.v2.pet)

; 100 0 0 10 0 100
(def he (atom 100))
(def hu (atom 0))
(def sl (atom 0))
(def fo (atom 10))
(def po (atom 0))
(def mo (atom 100))

(defn a! [sa n]
  (swap! sa #(+ % n)))

(defn s! [sa n]
  (swap! sa #(- % n)))

(defn apply-rules []
    (a! hu 1)
    (a! sl 1)
    (if (>= @hu 80)
      (s! he 1))
    (if (>= @sl 80)
      (do
        (reset! sl 0)
        (a! hu 9)))
    (if (>= @he 80)
      (a! mo 1)))

(defn handle-keypress [k]
    (case k
      \f (if (> @hu 8)
           (do
             (s! fo 1)
             (s! hu 9)))
      \s (reset! sl 0)
      \p (if (> @po 0)
           (do
             (s! po 1)
             (a! he 9)))
      \b (if (> @mo 8)
           (do
             (s! mo 9)
             (a! po 1)))
      \t (if (> @mo 8)
           (do
             (s! mo  9)
             (a! fo 1)))
      nil))


(defn start-listener []
  (.start
    (Thread. ^Runnable
      (fn []
        (while (> @he 0)
            (handle-keypress (first (read-line))))))))

(defn -main []
  (start-listener)
  (while (> @he 0)
    (Thread/sleep 500)

    (apply-rules)

    (println (str
               "Health: " @he "\n"
               "Hunger: " @hu "\n"
               "Sleep: " @sl "\n"
               "Food: " @fo "\n"
               "Potions: " @po "\n"
               "Money:" @mo "\n")))

  (println "You died!\n"))

V1

Ohdeargod. Pasti ruang untuk perbaikan di sini. Masalah seperti ini paling mudah dilakukan dengan efek samping, dan Clojure fungsional, jadi saya mencoba menyalahgunakan atomuntuk mengurangi jumlah kode yang diperlukan. Sayangnya, saya tidak masuk dengan rencana, jadi agak serampangan sekarang. Saya sudah mendapatkan beberapa ide untuk menyusut.

Ini adalah program lengkap. Itu bisa dijalankan dengan menjalankan -main.

(ns bits.golf.pet)(defrecord S[he hu sl fo po mo])(def new-state(->S 100 0 0 10 0 100))(def state(atom new-state))(defn update![sa k f](swap! sa #(update % k f)))(defn apply-rules[s](let [s' (atom s)u! #(update! s' %1 %2)g #(get @s' %)](u! :hu inc)(u! :sl inc)(if(>=(g :hu)80)(u! :he dec))(if(>= (g :sl)80)(do(u! :sl (fn[_]0))(u! :hu #(+ % 9))))(if(>=(g :he)80)(u! :mo inc))@s'))(defn get-input [](let [raw (read-line)](first raw)))(defn handle-keypress[s k](let [s'(atom s)u! #(update! s' %1 %2)g #(get @s' %)](case k\f(if (> (g :hu)8)(do(u! :fo dec)(u! :hu #(- % 9))))\s(u! :sl (fn [_] 0))\p(if(> (g :po)0)(do(u! :po dec)(u! :he #(+ % 9))))\b(if(>(g :mo))(do(u! :mo #(- % 9))(u! :po inc)))\t(if(>(g :mo)8)(do(u! :mo #(- % 9))(u! :fo inc)))nil@s')))(defn start-listener[](.start(Thread.^Runnable(fn[](while true(let[k(get-input)](swap! state #(handle-keypress % k))))))))(defn -main[](start-listener)(let[g #(get @%1 %2)](while true(Thread/sleep 500)(swap! state #(apply-rules %))(println(str"Health: "(g state :he)"\nHunger: "(g state :hu)"\n""Sleep: " (g state :sl)"\nFood: "(g state :fo)"\nPotions: "(g state :po)"\n""Money:"(g state :mo)"\n"))(if(<=(g state :he)0)(do(println"You died!\n")(reset! state new-state))))))

Tidak Disatukan:

(ns bits.golf.pet)

(defrecord State [he hu sl fo po mo])

(def new-state (->State 100 0 0 10 0 100))

(def state (atom new-state))

(defn update! [sa k f]
  (swap! sa #(update % k f)))

(defn apply-rules [s]
  (let [s' (atom s)
        u! #(update! s' %1 %2)
        g #(get @s' %)]
    (u! :hu inc)
    (u! :sl inc)
    (if (>= (g :hu) 80)
      (u! :he dec))
    (if (>= (g :sl) 80)
      (do
        (u! :sl (fn [_] 0))
        (u! :hu #(+ % 9))))
    (if (>= (g :he) 80)
      (u! :mo inc))
    @s'))

(defn get-input []
  (let [raw (read-line)]
    (first raw)))

(defn handle-keypress [s k]
  (let [s' (atom s)
        u! #(update! s' %1 %2)
        g #(get @s' %)]
    (case k
      \f (if (> (g :hu) 8)
           (do
             (u! :fo dec)
             (u! :hu #(- % 9))))
      \s (u! :sl (fn [_] 0))
      \p (if (> (g :po) 0)
           (do
             (u! :po dec)
             (u! :he #(+ % 9))))
      \b (if (> (g :mo))
           (do
             (u! :mo #(- % 9))
             (u! :po inc)))
      \t (if (> (g :mo) 8)
           (do
             (u! :mo #(- % 9))
             (u! :fo inc)))
      nil
      @s')))

(defn start-listener []
  (.start
    (Thread. ^Runnable
      (fn []
        (while true
          (let [k (get-input)]
            (swap! state #(handle-keypress % k))))))))

(defn -main []
  (start-listener)
  (let [g #(get @%1 %2)]
    (while true
      (Thread/sleep 500)

      (swap! state #(apply-rules %))

      (println (str
                 "Health: " (g state :he) "\n"
                 "Hunger: " (g state :hu) "\n"
                 "Sleep: " (g state :sl) "\n"
                 "Food: " (g state :fo) "\n"
                 "Potions: " (g state :po) "\n"
                 "Money:" (g state :mo) "\n"))

      (if (<= (g state :he) 0)
        (do
          (println "You died!\n\n\n\n\n")
          (reset! state new-state))))))
Carcigenicate
sumber
Itu jumlah kode yang bagus di sana.
ender_scythe
@ender_scythe Ya. Saya mencoba mematuhi praktik pengkodean setengah layak di beberapa tempat, seperti membuat applying-rulesdan handle-keypressmurni. Saya sedang menulis versi "screw-it" sekarang.
Carcigenicate