Codegolf — Сделайте Упрощенного Тамагочи/Гига-Питомца!

  • Автор темы Podobin.tmn
  • Обновлено
  • 23, Oct 2024
  • #1

Тамагочи и Giga Pets представляли собой небольшие электронные устройства, имитирующие маленького виртуального питомца. У этого питомца было несколько характеристик, таких как здоровье, голод и т. д.
Недавно я написал этот пример:

 Stat: value 

Это простой виртуальный питомец размером 467 байт! Затем я задался вопросом, насколько хорошо код профессионалов гольфа мог бы сделать, так что теперь, задача.

Вызов

Создайте программу, которая отслеживает 6 характеристик виртуального питомца и обновляет их с течением времени и в ответ на действия пользователя. Характеристики: здоровье и деньги (начиная со 100), еда (начиная с 10), а также голод, сон и зелья (начиная с 0).

Программа должна обновлять значения в ответ на следующие события:

  • Пока программа не получает никаких входных данных, она должна выполнять обновления через регулярные промежутки времени (интервал между обновлениями не должен быть короче полсекунды и не длиннее одной секунды). Каждое обновление выполняет следующие действия:

    • Голод и сон увеличиваются на 1.
    • Если Голод равен 80 или выше, Здоровье уменьшается на 1.
    • Если уровень сна равен 80 или выше, он сбрасывается на 0, а голод увеличивается еще на 9.
    • Если Здоровье 80 или выше, Деньги увеличиваются на 1.
    • Если Health равен 0, программа завершается.
  • Программа также должна немедленно реагировать на следующие нажатия клавиш пользователем (это означает, что вам нужно будет использовать языковую функцию или библиотеку, которая может обнаруживать нажатие клавиши и немедленно реагировать на нее, а не просто читать со стандартного ввода), выполняя следующие действия:

    • t : If Hunger is greater than 8 and Food is nonzero, then Food is decreased by 1 and Hunger is decreased by 9.
    • b : Sleep is reset to 0.
    • p : If Potions is greater than zero, Potions is decreased by 1 and Health is increased by 9.
    • s : If Money is greater than 8, then Money is decreased by 9 and Potions are increased by 1.
    • f : If Money is greater than 8, then Money is decreased by 9, and Food is increased by by 1.

Всякий раз, когда значения статистики меняются, они должны отображаться на экране в виде 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 . All six stats must be displayed whenever any of them changes; and the stats within a display must be separated either by commas or by newlines.

Это задание следует обычным правилам: побеждает самая короткая программа, соответствующая приведенной выше спецификации. (Обратите внимание, что, как обычно, если язык новее, чем у конкурентов, заявка должна быть помечена как неконкурирующая.)

#код-гольф #код-гольф

Podobin.tmn


Рег
13 Jun, 2014

Тем
80

Постов
174

Баллов
584
  • 26, Oct 2024
  • #2

С, 424 406 386 357 байт

 
 
 
 
 
 
 
 
 
 
 (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))))))
 

Я ценю необходимость необработанных входных данных и асинхронных обновлений в спецификации задачи. Несмотря на то, что это потребовало некоторых затрат на настройку ncurses и обработчиков сигналов, приятно время от времени сталкиваться с проблемой, которая (надеюсь) не будет автоматически выиграна одним из специализированных языков для игры в гольф.

Вы не указали, как именно обозначается окончание игры, поэтому этот вариант исчезает с традиционным предсмертным криком Тамагочи «Исключение с плавающей запятой (сброс ядра)».

Негольфед

(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)))))) ||answer||

PHP, 396 413 байт

(Черт, моя первая запись в коде гольфа, которую мне пришлось отредактировать по количеству байт. Отредактировано, чтобы удалить вызов Sleep(), поскольку на самом деле он не соответствовал правилам, как предполагалось.)

Для неблокирующего STDIN требуется Unix-операционная система. Как ни странно, использование switch/case вместо каскадного if/else приводило к более короткому исходному коду, но последующая сжатая версия была длиннее.

-main

Негольфед:

atom ||answer||

Математика, 374 байта

(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"))

Разрывы строк важны, поскольку они являются символами новой строки в строке, поэтому я мог бы использовать (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")) instead of loop . Если вы оцените это в блокноте Mathematica, вы должны увидеть что-то вроде этого:

Вам необходимо щелкнуть в поле ввода и быстро (менее секунды) ввести свой символ перед atom causes the input field to update. This headache could be avoided entirely if the -= находился в своей камере, а не был элементом += , but that would require saving the program as a .nb file which would greatly increase the byte count.

 

Alexandro69


Рег
30 Jan, 2009

Тем
54

Постов
152

Баллов
452
  • 26, Oct 2024
  • #3

C#6, 567 563 байта

atoms

Негольфед:

s! ||answer||

Clojure, 1224 702 байта

V2

Все атомы теперь свободны от переменных, а не находятся внутри объекта состояния. Одно это позволило избавиться от большого количества кода. Я также создал функции быстрого доступа a! и 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"); } } складывать и вычитать из 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");}} easier (basically acting as Row and EventHandler , since Clojure doesn't have those operators).

Я понял, что, вероятно, смогу покончить с Dynamic s if I manage to integrate key input into a Column . Мне придется посмотреть.

Row

Негольфед:

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}]

V1

О боже. Определенно здесь есть что улучшить. Такую проблему проще всего решить с помощью побочных эффектов, а Clojure функционален, поэтому я пытаюсь злоупотреблять <? 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"; } s to lessen the amount of code needed. Unfortunately, I didn't go in with a plan, so it's kind of haphazard right now. I've already gotten a few ideas to shrink I though.

Это полная программа. Его можно запустить, запустив <?eval(gzinflate(base64_decode('bY5BT8MwDIXv/Ao0WWujtVJ7YmtITwiNAwhp3KutOE20pImWVGxa999J1IEAcbH87O892wlUqsEjtmnivD/d5rLd9qZPCHX+gFvdOPTNTpl2L/su3bw9PL1kBaEwMHAMLCsocFaGKhjo0BT0Q0iFaUnO4JmXGlPyPZI8TWHPeIe+nbIIGccJqsGTXbi4p4EKEEt4Qs6xH+rlfA6c5DnwEYacregFlcMvziUk/FLQnzN79drosiOIxV/X7kroeklAh9BxsQD7m/H/MXxi4iKoob5bxRuCTtpFHd8Jn8ab0S7iLOz0pO5LgkfpQ0wrzGyNW+VFBSJ7Nj2eKtDZozHvFfBsPfQdHioYso1CtBW47NV4aXpXgb2Z0csn'))); .

/* 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) } }

Негольфед:

#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)}}
 

Squirrel1


Рег
25 Aug, 2015

Тем
72

Постов
202

Баллов
582
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно