ตามล่า Wumpus


39

ตอนที่ฉันยังเป็นเด็กอยู่เด็ก ๆ จะเดินเข้าไปในร้านคอมพิวเตอร์และเล่น Hunt the Wumpus จนกว่าพนักงานจะเตะเราออกไป มันเป็นเกมง่ายๆที่เขียนโปรแกรมได้ที่คอมพิวเตอร์ที่บ้านในช่วงกลางปี ​​1970 เครื่องจักรจึงเป็นพื้นฐานที่แทนที่จะเป็นไมโครโปรเซสเซอร์ที่มีขนาดเท่าลูกไก่ฉันคิดว่าบางคนอาจมีลูกไก่ตัวจริงอยู่ในนั้น

มาสร้างยุคสมัยนั้นด้วยการจำลองเกมบนฮาร์ดแวร์ที่ทันสมัย

  1. ผู้เล่นเริ่มต้นในห้องสุ่มบนแผนที่ icosahedral (ดังนั้นมีทั้งหมด 20 ห้องเชื่อมต่อกันเหมือนใบหน้าของ icosahedron และทุกห้องมีทางออกสามทาง)

  2. Wumpus เริ่มต้นในห้องอื่นที่สุ่มเลือก และกลิ่นของมันสามารถตรวจจับได้ในห้องใดห้องหนึ่งในสามห้องที่อยู่ติดกับที่ตั้งแม้ว่าจะไม่สามารถบอกทิศทางของกลิ่นได้ เกมรายงานเฉพาะ "คุณได้กลิ่น wumpus"

  3. ผู้เล่นถือธนูและลูกธนูจำนวนอนันต์ซึ่งเขาสามารถยิงได้ตลอดเวลาเข้าไปในห้องด้านหน้าของเขา หากวุสปัสอยู่ในห้องนั้นจะตายและผู้เล่นชนะ หากวุสตัสไม่ได้อยู่ในห้องนั้นจะตกใจและย้ายไปยังห้องใดห้องหนึ่งในสามห้องที่เชื่อมต่อกับที่ตั้งปัจจุบัน

  4. หนึ่งห้องที่เลือกแบบสุ่ม (รับประกันว่าจะไม่เป็นห้องที่ผู้เล่นเริ่ม) มีหลุมที่ลึกที่สุด หากผู้เล่นอยู่ในห้องใด ๆ ที่อยู่ติดกับหลุมเขารู้สึกถึงลม แต่ไม่มีเงื่อนงำว่าประตูสายลมมาจากไหน ถ้าเขาเดินเข้าไปในห้องพร้อมกับหลุมเขาตายและ wumpus ชนะ Wumpus ไม่ได้รับผลกระทบจากหลุม

  5. หากผู้เล่นเดินเข้าไปในห้องของ wumpus หรือถ้า wumpus เดินเข้าไปในห้องของผู้เล่น wumpus จะชนะ

  6. ผู้เล่นระบุทิศทางที่เขาเผชิญกับตัวเลข (1 = ขวา, 2 = ซ้าย, 3 = หลัง) จากนั้นการกระทำ (4 = ยิงลูกศร, 5 = เดินไปในทิศทางที่ระบุ)

  7. เพื่อการให้คะแนนแต่ละสตริงของเกม ("คุณรู้สึกสบาย" "คุณได้กลิ่น wumpus" "ลูกศรของคุณไม่โดนอะไรเลย" เป็นต้น) สามารถพิจารณาได้หนึ่งไบต์ ห้ามใช้สิ่งนี้เพื่อซ่อนรหัสเกมในข้อความ นี่เป็นเพียงการโต้ตอบกับผู้เล่น

  8. หัก 10% ของจำนวนไบต์ของคุณสำหรับการติดตั้ง megabats ซึ่งเริ่มต้นในห้องสุ่มที่แตกต่างจากผู้เล่น (แม้ว่าพวกเขาสามารถแชร์ห้องกับ wumpus และ / หรือหลุม) หากผู้เล่นเดินเข้าไปในห้องพร้อมกับค้างคาวค้างคาวจะพาผู้เล่นไปยังห้องที่เลือกแบบสุ่มอีกครั้ง (รับประกันว่าจะไม่เป็นห้องที่มีหลุมหรือปากมัน) ก่อนที่จะบินไปยังที่ตั้งใหม่ของพวกเขาเอง ในสามห้องที่อยู่ติดกับค้างคาวพวกเขาจะได้ยินเสียงแหลม แต่ผู้เล่นไม่ได้รับข้อมูลเกี่ยวกับเสียงที่มาจากห้อง

  9. หัก 35% ของจำนวนไบต์ของคุณสำหรับการใช้อินเทอร์เฟซแบบกราฟิกที่แสดงแผนที่ icosahedral และการบ่งชี้ข้อมูลที่ผู้เล่นมีเกี่ยวกับตำแหน่งของหลุมหลุมและค้างคาว (ถ้ามี) ที่เกี่ยวข้องกับ ผู้เล่น. เห็นได้ชัดว่าหากการเคลื่อนไหวของ wumpus หรือผู้เล่นถูกย้ายโดยค้างคาวแผนที่จำเป็นต้องรีเซ็ตตามนั้น

  10. จำนวนไบต์ต่ำสุดตามที่ได้รับการปรับจะชนะ

ซอร์สโค้ดพื้นฐานสำหรับรุ่นของเกม (ไม่จำเป็นต้องสอดคล้องกับกฎข้างต้นและไม่ว่าในกรณีใด ๆ ที่ไม่ได้รับการพรากจากกันอย่างเต็มที่) สามารถพบได้ในเว็บไซต์นี้และอื่น ๆ


คำอธิบายบางอย่าง: 3. ถ้าวุสตัสไม่ได้อยู่ในห้องนั้นมันจะตกใจและย้ายไปที่หนึ่งในสามของห้อง .. ดังนั้นถ้าคุณยิงธนูและพลาดไปล่ะววคัสนั้นอาจมาฆ่าคุณใช่ไหม? และ wumpus จะเคลื่อนไหวก็ต่อเมื่อตกใจไม่งั้นมันก็จะอยู่เฉยๆ? 6. ฉันเข้าใจว่าส่วนหัวของผู้เล่นขึ้นอยู่กับห้องที่เขามาจาก ดังนั้นถ้าเขามาจากทางใต้ตัวเลือกของเขาจะเป็น 1.northeast 2.northwest 3.south และถ้าเขามาจากทางเหนือมันจะตรงกันข้าม กฎของคุณก็ดูง่ายกว่า / นักกอล์ฟมากกว่าโปรแกรมอ้างอิง (ซึ่งฉันยังไม่ได้ตรวจสอบอย่างละเอียด) ฉันถูกต้องไหม?
เลเวลริเวอร์เซนต์

โอ๊ะ! ฉันไม่สามารถหาใด ๆภาพของกราฟคู่ของทุกที่ฮอว์คิงในสุทธิ
Jack M

1
@ สตีฟเวอร์ริลใช่แล้วถ้าคุณพูดถึงมันอาจจะมาและฆ่าคุณ หากคุณไม่สางมันจะไม่เคลื่อนไหว มีหลายรูปแบบในเกม; หลายรุ่นอนุญาตให้ลูกศรล้อมรอบและฆ่าคุณตัวอย่างเช่น ฉันตัดมันออกไป
Michael Stern

3
@ JackM แผนที่ของใบหน้าของ icosahedron นั้นเหมือนกับแผนที่ของจุดยอดของ dodecahedron และพบว่ากราฟนั้นง่าย ลองตัวอย่างwolframalpha.com/input/?i=DodecahedralGraph+edgerulesหรือคำสั่ง Mathematica ที่เทียบเท่า GraphData ["DodecahedralGraph", "EdgeRules"] ไม่ว่าคุณจะได้ {1 -> 14, 1 -> 15, 1 -> 16, 2 -> 5, 2 -> 6, 2 -> 13, 3 -> 7, 3 -> 14, 3 -> 19, 4 -> 8, 4 -> 15, 4 -> 20, 5 -> 11, 5 -> 19, 6 -> 12, 6 -> 20, 7 -> 11, 7 -> 16, 8 -> 12, 8 -> 16, 9 -> 10, 9 -> 14, 9 -> 17, 10 -> 15, 10 -> 18, 11 -> 12, 13 -> 17, 13 -> 18, 17 -> 19, 18 -> 20}
Michael Stern

2
@ JackM ไม่ "ย้อนกลับ" หมายถึงการหันหลังกลับและเดินกลับไปตามที่คุณมา หากคุณกดปุ่ม "ย้อนกลับ" สองครั้งคุณจะสิ้นสุดตำแหน่งที่คุณเริ่ม ไม่จำเป็นต้องเก็บสถานะเกมก่อนหน้า
Michael Stern

คำตอบ:


21

GolfScript, 163

:n;:`"You shot the wumpus.
""The wumpus ate you.
""The pit swallowed you.
"{19:|rand}2*0|{[:,~,4%"ftvh"=.,+,@-]{20%}%}:^{;.^.+.3$?>"You feel a breeze.
"1$6"You smell a wumpus.
"4$8{$?-1>*p}2*'"#{'|):|';`head -1`}"'++~{3%}/={=3$=|{"Your shot missed.
"p@^3rand=@@}if}{=@;}if.[|4$6$]?.)!}do])=

คะแนนนั้นได้มาจากการนับไบต์ (290) เพิ่มจำนวนของสตริงที่ใช้สำหรับการโต้ตอบกับผู้ใช้ (6) และลบความยาวรวมของสตริงเหล่านั้น (133) linefeeds เป็นส่วนหนึ่งของสตริงและมีส่วนร่วมในการนับไบต์

เหตุการณ์สำคัญ

  1. ส่งคำตอบของ professorfishจาก Bash ไปยัง GolfScript คะแนน: 269

  2. ทำตามคำแนะนำของPeter Taylorในความคิดเห็น คะแนน: 250

  3. Peter Taylor ปรับโครงสร้างรหัสทั้งหมดของฉันใหม่และช่วยฉันบีบตารางการค้นหา คะแนน: 202

  4. แทนที่ตารางการค้นหาของห้องที่อยู่ติดกันด้วยวิธีการทางคณิตศาสตร์ คะแนน: 182

  5. Refactored input, output และฟังก์ชั่นที่รองรับวิธีการทางคณิตศาสตร์ คะแนน: 163

“ ขอบคุณมาก!” ไปถึง Peter Taylor สำหรับความช่วยเหลือทั้งหมดของเขา

มันทำงานอย่างไร

ห้องทั้ง 20 ห้องเป็นจุดยอดของรูปทรงสิบสองหน้าซึ่งได้รับการกำหนดหมายเลขจาก 0 ถึง 19 ในรูปแบบต่อไปนี้:

กราฟสองมิติ

ในการค้นหาห้องที่อยู่ติดกับห้องNและเรียงตามลำดับตามเข็มนาฬิกาเราต้องพิจารณาสี่กรณี:

  • หากยังไม่มี≡ 0 4 สมัย (vertexes สีน้ำเงิน) ห้องที่อยู่ติดกันมี19 - N , N + 2 สมัยที่ 20และN - 2 สมัย 20

  • หากยังไม่มี≡ 1 4 สมัย (vertexes สีเขียว) ที่ห้องที่อยู่ติดกันมี19 - N , N - 4 สมัย 20และN + 4 สมัย 20

  • หากยังไม่มี≡ 2 4 สมัย (vertexes สีเหลือง) ที่ห้องที่อยู่ติดกันมี19 - N , N - 2 สมัยที่ 20และN + 2 สมัย 20

  • หากยังไม่มี≡ 3 4 สมัย (vertexes สีแดง) ที่ห้องที่อยู่ติดกันมี19 - N , N + 4 สมัย 20และN - 4 สมัย 20

# The function “p” is implemented as “{`print n print}”. By storing an empty string in 
# “n” and nullifying “`”, “p” becomes an alias for “print”.

:n;:`

# Push the messages corresponding to the three possible outcomes of the game.

"You shot the wumpus.\n""The wumpus ate you.\n""The pit swallowed you.\n"

# Place the wumpus and the pit in randomly selected rooms different from room 19; place 
# the player in room 19, with his back to room 0.

{19:|rand}2*0|

# Function “^” takes a single number as its argument and returns an array of all the
# adjacent rooms to the room that number corresponds to.

{

  [

    :,~       # Store the room number in “,” and negate it ( ~N ≡ 19 - N mod 20 )

    ,4%       # Push the room number modulus 4.

    "ftvh"=   # If it is equal to 0|1|2|3, push 102|116|118|104 ≡ 2|-4|-2|4 mod 20.

    .,+,@-    # Determine the room number plus and minus the integer from above.

  ]{20%}%     # Take all three room numbers modulus 20.

 }:^

{             # STACK: Strings Pit Wumpus Previous Current Function|Index

  ;           # STACK: Strings Pit Wumpus Previous Current

  # Find the adjacent rooms to the current room, duplicate them and remove the rooms 
  # before the first occurrence of the previous room. Since the rooms are ordered in
  # clockwise fashion, the array of adjacent rooms will begin with the rooms 
  # corresponding to the following directions: “Back Left Right”

  .^.+.3$?>   # STACK: Strings Pit Wumpus Previous Current Adjacent

  # Push two more messages and their respective triggers.

  "You feel a breeze.\n"1$6"You smell a wumpus.\n"4$8

  # STACK: ... Pit Wumpus Previous Current Adjacent String Adjacent 6 String Adjacent 8

  # Do the following twice: Duplicate the nth stack element and check if it's present in 
  # the array of adjacent rooms. If so, print the string below it.

  {$?-1>*p}2*

  # Read one line (direction, action, LF) from STDIN. The counter “|” is needed so the 
  # result won't get cached.

  '"#{'|):|';`head -1`}"'++~

  {3%}/       # Replace 1|2|3|4|5|LF with their character codes modulus 3 (1|2|0|1|2|1).

  ={          # If the player shoots an arrow:

    =3$=      # Determine the specified room and check if it corresponds to the wumpus.

      |       # If it does, push and invalid room number ( | > 19 ).

      # If it does not, say so and move the wumpus to a randomly selected adjacent room.

      {"Your shot missed."p@^3rand=@@}

    if

  }{           # If the player moves:

    =@;        # Place him into the selected room.

  }if

  # STACK: Pit Wumpus Previous Current Invalid?

  # Determine if the player's current room number is either invalid, the wumpus's room
  # number or the pit's room number (first match).

  .[|4$6$]?

  # If there is no match, the index is -1 and incrementing and negating it yields “true”.

  # STACK: Strings Pit Wumpus Precious Current Invalid? Index Boolean

# Repeat loop is the boolean is falsy. If repeated, the first instruction of the loop 
# will pop the index.

}do      

# Consolidate the entire stack into an array. And pop its last element: the index.
# Replace the array with the element corresponding to that index.

])=

# GolfScript will execute “print n print”.

1
คุณสามารถบันทึก 1 Qด้วย19rand 97+; 2 @ด้วย97%3*&>... ต่อ 1 โดย inlining Qเป็น{19rand 97+}2*:,\:Hไม่กี่โดยแทนที่|ด้วยซึ่งมักจะเป็นวิธีที่ดีที่สุดที่จะทำ* ไม่มีจุดประสงค์และฉันคิดว่าตัวแปรอีกสองสามอย่างสามารถกำจัดได้โดยใช้สแต็ก ifB
Peter Taylor

1
ลืมพูดถึงเคล็ดลับอื่นบ่อย: การแปลงฐานสำหรับตารางการค้นหา คุณสามารถแทนที่ 62 ตัวอักษรสำหรับรายการ adjacency ด้วยสตริง 33-char ตามด้วย256base 20base(และอาจกำจัด +/- 97 บางรายการ) ข้อเสียเพียงอย่างเดียวคือมันจะต้องมีอักขระที่ไม่สามารถพิมพ์ได้
Peter Taylor

1
ฉันบันทึกอีก 13โดยการ refactoring เป็น GS ที่ใช้สำนวนมากขึ้น (ส่วนใหญ่ใช้ stack มากกว่าตัวแปร); และยังมีค่าใช้จ่ายเพิ่มเติมอีก 10 ค่าที่ทำให้ผลผลิตออกมาน้อยลง นั่นคือนอกเหนือจากการบีบอัดตารางการค้นหาที่กล่าวถึงในความคิดเห็นก่อนหน้าของฉัน
Peter Taylor

1
ไม่เลยฉันสนุกกับมัน ฉันแค่ผิดหวังที่วิธีการค้นหาตารางนั้นดีกว่าวิธีทางคณิตศาสตร์มากกว่าที่ฉันตั้งใจจะใช้ BTW ฉันคิดว่าเวอร์ชั่นปัจจุบันของคุณมีข้อบกพร่องเล็ก ๆ น้อย ๆ เพราะถ้าคุณยิงธนูศรพลาดและทำให้สะดุ้งตื่นขึ้นมาในห้องของคุณมันจะแสดงเฉพาะYou were killed by the wumpusกับลูกศรที่หายไปเท่านั้น นั่นเป็นสาเหตุที่ฉันผนวกท้ายในเวอร์ชันที่ไม่สวย
Peter Taylor

1
2*2+=>)2*
Peter Taylor

15

REV0 C ++ (Visual Studio บน Windows) 405

#include"stdafx.h"
#include<stdlib.h>
#include<time.h>
int main(){srand(time(NULL));char i,h=rand()%19,w=rand()%19,p=19,d=0,q,e,m[]="e@LwQMQOSOLT";while(p-h&&p-w){for(i=3;i--;){q=(p+m[p%4*3+i])%20;if(q==w)puts("you smell a wumpus");if(q==h)puts("you feel a breeze");}scanf_s("%d",&i);e=(d+i/10)*m[p%4]%3;q=(p+m[p%4*3+e])%20;if(i%5){if(q==w){puts("YOU KILLED THE WUMPUS!");h=p;}else{puts("arrow missed");w=(w+m[w%4*3+rand()%3])%20;}}else{p=q;d=e;if(p==h)puts("YOU FELL IN A HOLE!");}if(p==w)puts("THE WUMPUS GOT YOU!");}}

ด้านล่างนี้คือ playthrough ซึ่งแสดงให้เห็นว่า (หากคุณไม่ได้เริ่มติดกับอันตราย) ด้วยการเล่นที่ถูกต้องคุณสามารถชนะได้เสมอ ผู้เล่นรู้สึกว่าสบายหันหลังกลับและหมุนวนทวนเข็มนาฬิกาจนจบ เมื่อเขาใช้เวลา 5 ก้าวในการรู้สึกถึงสายลมอีกครั้งเขาก็รู้รูไปทางขวาของเขาและออกไปให้ไกลที่สุด ในทำนองเดียวกันเมื่อเขาได้กลิ่นวุสปัสโดยไม่รู้ว่ามันถูกหรือซ้ายเขาก็หันหลังกลับและวนตามเข็มนาฬิกา เขาใช้เวลา 5 ครั้งในการดมกลิ่นวูมปัสอีกครั้งดังนั้นเขาจึงรู้ว่ามันอยู่ทางซ้ายและยิงด้วยความมั่นใจ

หากเขาวนลูปไปทางอื่นเขาจะพบว่าววัสเร็วขึ้นและรู้ว่ามันเป็นไปในทิศทางเดียวกันกับที่เขาหมุน

ป้อนคำอธิบายรูปภาพที่นี่

REV1 C (GCC สำหรับ Cygwin), 431-35% โบนัส = 280.15

#define u(t,s,c) if(t){puts(s);c;}
i,d,e,a,b;main(){srand(time(0));char q,p=19,h=rand()%p,w=rand()%p,*m="e@LwQMQOSOLT-\\/\n \v ";  
while(p-h&&p-w){
  for(i=3;i--;){q=(p+m[p%4*3+i])%20;u(q==w,"you smell a wumpus",a|=2<<p)u(q==h,"you feel a breeze",b|=1<<p)}
  for(i=20;i--;)printf("%c%c",i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),m[i%4+15]);
  scanf("%d",&i);e=(d+i/10)*m[p%4]%3;q=(p+m[p%4*3+e])%20;
  if(i%5){u(q-w,"arrow missed",w=(w+m[w%4*3+rand()%3])%20;a=0)else u(1,"YOU KILLED THE WUMPUS!",h=p)}
  else{p=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)}
  u(p==w,"THE WUMPUS GOT YOU!",)}}

เพิ่มบรรทัดใหม่เพื่อความชัดเจน การเปลี่ยนแปลงจาก Rev 0 มีดังนี้:

ขอบคุณมากที่ @Dennis สำหรับการแนะนำคอมไพเลอร์ GCC บน Cygwin Linux emulator สำหรับ Windows คอมไพเลอร์นี้ไม่ต้องการincludes ในโปรแกรม rev 0 และอนุญาตintประเภทเริ่มต้นสำหรับตัวแปรและmain.นี่คือเคล็ดลับการเล่นกอล์ฟที่เปลี่ยนแปลงชีวิต!

นอกจากนี้การรันใน Linux หมายความว่า\fทำให้เคอร์เซอร์เลื่อนลงโดยไม่ทำ carriage return (ต่างจากใน Windows ที่เพิ่งสร้างสัญลักษณ์ที่พิมพ์ได้) ซึ่งอนุญาตให้ย่อคำสั่ง printf ที่พิมพ์บนบอร์ดได้

เคล็ดลับเพิ่มเติมจากเดนนิสในความคิดเห็นและหนึ่งในตัวฉันเอง: เปลี่ยนเงื่อนไขเมื่อตรวจสอบว่าลูกศรกดปุ่ม wumus: if(q==w)> if(q-w)(..else .. is reverse)

เพิ่มเติมจากการแสดงกราฟิกที่แสดงข้อมูลที่ผู้เล่นรู้เกี่ยวกับตำแหน่งที่มีกลิ่นของ wumpus / สายลมรู้สึกว่ารับโบนัส 35% (ฉันลบ debug เวอร์ชั่นเก่าซึ่งแสดงตำแหน่งที่แน่นอนของ wumpus และ hole ซึ่งสามารถเห็นได้ในประวัติการแก้ไข)

REV2 C (GCC สำหรับ Cygwin) โบนัส 389-35% = 252.85

#define Q(N) (N+"QTLOQMQOSOLT"[N%4*3+e])%20
#define P printf(
i,d,e,a,b;main(){int p=19,q=srand(&p),h=rand()%p,w=rand()%p;
while(p-h&&p-w){
  for(e=3;e--;){q=Q(p);q-w||P"You smell a wumpus\n",a|=2<<p);q-h||P"You feel a breeze\n",b|=1<<p);}
  for(i=20;i--;)P"%c%c",i-p?48+(a>>i&2)+(b>>i&1):"-\\/"[d],"\n \v "[i%4]);
  scanf("%d",&i);e=(d+i/9)*"edde"[p%4]%3;q=Q(p);
  if(i%5){e=rand()%3;w=q-w?P"Your arrow didn't hit anything\n",a=0)&Q(w):(p=20);}
  else p=q,d=e;
}
P p-20?p-w?"YOU FELL IN A HOLE!\n":"THE WUMPUS GOT YOU!\n":"YOU KILLED THE WUMPUS!\n");}

ขอขอบคุณเดนนิสอีกครั้งสำหรับการทำซ้ำรหัสของฉัน:

ค่าคงที่ของ Char m[]ถูกแทนที่ด้วยตัวอักษร (ฉันไม่รู้ว่าคุณสามารถจัดทำดัชนีตามตัวอักษรได้)

การเพาะหมายเลขสุ่มด้วยตัวแปรสแต็ก (ขึ้นอยู่กับระบบบางระบบสุ่มการจัดสรรหน่วยความจำเป็นการวัดความปลอดภัย)

แมโครที่putsถูกแทนที่ด้วยแมโครด้วยprintfและรหัสเพิ่มเติมซึ่งจะต้องดำเนินการเมื่อข้อความที่แสดงอยู่ภายในprintfอาร์กิวเมนต์ (ประโยชน์ที่ได้จากใบหน้าที่ printf ไม่พิมพ์อาร์กิวเมนต์สองสามตัวสุดท้ายหากตัวระบุรูปแบบไม่เพียงพอในสตริงรูปแบบ) ifแทนที่ด้วย||

การคำนวณตำแหน่งใหม่ของผู้เล่น / wumpus วางไว้ในมาโครใหม่

รับ / วางข้อความที่อยู่นอกwhileลูป ifแทนที่ด้วยตัวดำเนินการตามเงื่อนไข

การใช้ตัวดำเนินการตามเงื่อนไขในสายการยิงลูกศร หากผู้เล่นพลาดสิ่งนี้จะต้องมีทั้งการพิมพ์ข้อความและปรับตำแหน่ง wumpus เดนนิสเสนอวิธีการรวมกันหลายวิธีprintfและการคำนวณตำแหน่งของ wumpus ลงในนิพจน์เดียว แต่ฉันได้ไปกับหนึ่งในตัวของฉันเอง printfส่งกลับจำนวนของตัวอักษรที่พิมพ์ซึ่งYour arrow didn't hit anything\nเป็น 31 (11111 ไบนารี.) 31&Q(w)==Q(w)ดังนั้น

การมีส่วนร่วมอื่น ๆ ของฉันในการแก้ไขนี้ได้ทำการกำจัดวงเล็บเหลี่ยมที่ไม่จำเป็นออกไป

เอาท์พุต

ที่นี่ผู้เล่นพบว่า Wumpus อยู่ที่ไหน แต่เลือกที่จะสำรวจอย่างละเอียดเพื่อค้นหาว่าหลุมอยู่ที่ใดเช่นกัน ซึ่งแตกต่างจากรุ่น debug เก่าของฉันซึ่งแสดงให้เห็นว่า wumpus และหลุมอยู่ตลอดทั้งเกมนี้แสดงเฉพาะห้องที่ผู้เล่นเข้าเยี่ยมชมและรู้สึกถึงสายลม (1) หลอม wumpus (2) หรือทั้งสอง (3) (หากผู้เล่นยิงธนูและพลาดไปตัวแปรaที่บรรจุข้อมูลตำแหน่งของ wumpus จะถูกรีเซ็ต)

ป้อนคำอธิบายรูปภาพที่นี่

การเป็นตัวแทนของ ICOSAHEDRON

หมายเหตุ: ส่วนนี้อ้างอิงจาก rev 1

คุณสมบัติเด่นของฉัน! ไม่มีกราฟในรหัสของฉัน หากต้องการอธิบายวิธีการทำงานให้ดูแผนที่โลกด้านล่าง จุดใด ๆ บน icosahedron สามารถแสดงเป็นละติจูด 0-3 และลองจิจูด 0-4 (หรือหมายเลขเดียว, long*4+lat.) เส้นลองจิจูดที่ทำเครื่องหมายไว้บนแผนที่จะผ่านใบหน้าเหล่านั้นที่มีศูนย์ลองจิจูดเท่านั้นและเส้นละติจูดผ่าน ศูนย์กลางของใบหน้าที่มีละติจูดเป็นศูนย์

ผู้เล่นสามารถมุ่งเน้นใน 3 แกนไปได้แทนด้วยสัญลักษณ์ดังนี้ทิศตะวันตกเฉียงใต้-ทิศตะวันออกเฉียงเหนือทิศตะวันตกเฉียงใต้ทิศตะวันตกเฉียงเหนือตะวันออกเฉียงใต้\ /ในห้องใดก็ตามเขามีทางออกเดียวให้กับเขาในแต่ละแกน ในจอแสดงผลแสดงว่าเครื่องเล่นทำลูปตามเข็มนาฬิกาจนจบ โดยทั่วไปจะง่ายต่อการระบุจากผู้เล่นที่ทำเครื่องหมายว่าเขามาจากไหนดังนั้นเขาจึงได้รับอนุญาตให้ไป

กรณีหนึ่งที่ยากเล็กน้อยสำหรับตาที่ไม่ได้ฝึกหัดคือตาที่สี่ เมื่อคุณเห็นการเอียงในหนึ่งในแถวขั้วโลกเหล่านี้ผู้เล่นมาจากเซลล์ขั้วโลกที่อยู่ใกล้ปลายด้านนอกสุดของเอียงและหันหน้าเข้าหาเส้นศูนย์สูตร ดังนั้นผู้เล่นจะหันหน้าไปทางทิศตะวันออกเฉียงใต้และทางเลือกของเขาคือ: 15 (SOUTH, เซลล์ทางด้านขวา) 25 (ทิศตะวันออกเฉียงเหนือ, เซลล์ด้านบน) หรือ 35 (ทิศตะวันตกเฉียงเหนือ, เซลล์ด้านล่าง)

โดยทั่วไปแล้วฉันจับคู่ icosahedron กับตาราง 5x4 โดยเซลล์มีหมายเลข 19 ถึง 0 ตามลำดับที่พิมพ์ การย้ายทำได้โดยการเพิ่มหรือลบออกจากตำแหน่งปัจจุบันขึ้นอยู่กับละติจูดและทิศทางของผู้เล่นตามตารางด้านล่าง

ถ้าผู้เล่นออกไปด้านล่าง (ตะวันตก) ของบอร์ดเขาจะกลับมาที่ด้านบน (ตะวันออก) และในทางกลับกันตำแหน่งของเขาจึงถูกนำไปเป็นโมดูโล 20 โดยทั่วไปการเคลื่อนไหวจะถูกเข้ารหัสเป็น m [] โดยเพิ่ม ascii 80 ( P) ถึงค่า raw ที่แสดงตัวอักษรด้านล่าง แต่สามารถเพิ่มหลักการใดก็ได้จาก 20 รายการโดยไม่ส่งผลกระทบต่อการดำเนินการ

Table of addition values for moves

Direction Symbol Latitude 0  1  2  3     Latitude 0 1 2 3

0, N-S      -             1 -1  1 -1              Q O Q O  
1, NE-SW    \            -4  1 -1  4              L Q O T
2, NW-SE    /             4 -3  3 -4              T M S L

อินพุตของผู้เล่น (หารด้วย 10 เพื่อลบตัวเลขที่สอง) จะถูกเพิ่มไปยังทิศทางปัจจุบันของเขาและนำโมดุลโล 3 ไปสู่ทิศทางใหม่ของเขา วิธีนี้ใช้ได้ผลดีในกรณีส่วนใหญ่ อย่างไรก็ตามมีปัญหาเมื่อเขาอยู่ในห้องขั้วโลกและเดินไปทางเสา จะชัดเจนเมื่อพับแผนที่ด้านล่างว่าถ้าเขาออกจากห้องหันหน้าไปทางทิศตะวันออกเฉียงเหนือเขาจะเข้าสู่จตุรัสใหม่หันหน้าไปทางทิศตะวันออกเฉียงใต้ดังนั้นจึงต้องทำการแก้ไข นี้จะกระทำในบรรทัดโดยคูณด้วยe=(d+i/10)*m[p%4]%3; m[p%4]สี่ค่าแรกของม. [] ได้รับการคัดเลือกดังกล่าวว่านอกเหนือไปจากฟังก์ชั่นของพวกเขาเหนือพวกเขายังมีลักษณะ และm[1]%3==m[2]%3==1 m[0]%3==m[3]%3==2สิ่งนี้ทำให้ทิศทางเดียวสำหรับห้องศูนย์สูตรและใช้การแก้ไขที่จำเป็นสำหรับห้องขั้วโลก

เวลาตรรกะที่จะทำการแก้ไขจะเป็นหลังการย้าย อย่างไรก็ตามในการบันทึกตัวละครมันจะทำก่อนที่จะย้าย ดังนั้นค่าบางค่าใน m [] ต้องถูกย้าย ดังนั้นอักขระ 2 ตัวสุดท้ายLTแทนที่จะเป็นตัวอย่างของTLตารางข้างต้น

ป้อนคำอธิบายรูปภาพที่นี่

รหัสที่ไม่ได้แปล

นี่คือรหัส rev 1 ซึ่ง obfuscated น้อยกว่า rev 2

สิ่งนี้จะทำงานบน GCC / Linux ฉันได้รวมอยู่ในความคิดเห็นเกี่ยวกับรหัสพิเศษที่จำเป็นในการทำให้มันทำงานบน Visual studio / Windows มันแตกต่างกันมาก!

//Runs on gcc/linux. For visual studio / windows, change printf(...) 
//to printf(" %c%c%c",9*(i%4==1),i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),10*!(i%2)) and uncomment the following lines
//#include"stdafx.h"
//#include<stdlib.h>
//#include<time.h>
//#pragma warning(once:996;once:430) //allow the use of scanf instead of scanf_s, allow default type=int. 
//Though rather than using the pragma, it is shorter to follow compiler recommendation and use scanf_s and int.

#define u(t,s,c) if(t){puts(s);c;}  //if(test){puts(string);additional code;}

i,     //player input, loop counter
d,e,   //current and proposed direction
a,b;   //bit flags for where wumpus smelt / breeze felt

main(){
    srand(time(0));
    char q,p=19,h=rand()%p,w=rand()%p,  //Initialise player, hole and wumpus. q stores proposed player position.
    *m="e@LwQMQOSOLT-\\/\n \f ";        //Chars 0-11: movetable. Chars 12-14:symbol for player. Chars 15-18: graphics format.   

    while(p-h&&p-w){

        // Print warnings
        for(i=3;i--;){q=(p+m[p%4*3+i])%20;u(q==w,"you smell a wumpus",a|=2<<p)u(q==h,"you feel a breeze",b|=1<<p)}

        // graphic display 
        for(i=20;i--;)printf("%c%c",i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),m[i%4+15]);

        // Get player input and work out direction and room 
        scanf("%d",&i);
        e=(d+i/10)*m[p%4]%3;
        q=(p+m[p%4*3+e])%20;

        // i%5 is false if player inputs 5 (move player) otherwise true (shoot arrow) 
        if(i%5)
        {u(q-w,"arrow missed",w=(w+m[w%4*3+rand()%3])%20;a=0)else u(1,"YOU KILLED THE WUMPUS!",h=p)}
        else{p=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)}
        u(p==w,"THE WUMPUS GOT YOU!",)
    }

}

ปัญหาและปัจจัยที่เกี่ยวข้อง

ฉันใช้ประโยชน์จากจุดที่เอ่ยถึง @professorfish ถ้าหาก wumpus และหลุมเริ่มต้นในสถานที่สุ่มไม่มีความจำเป็นสำหรับผู้เล่นที่จะเริ่มต้นในสถานที่สุ่ม ผู้เล่นเริ่มต้นในห้องที่ 19 ซึ่งหันหน้าไปทางทิศเหนือ

ฉันเข้าใจว่าเมื่อตั๊กแตนเป็น "ไม่ได้รับผลกระทบจากหลุม" ตั๊กแตนสามารถเริ่มต้นได้หรือเข้าไปในห้องที่หลุมอยู่ โดยทั่วไปสิ่งนี้ทำให้สิ่งต่าง ๆ ง่ายขึ้นยกเว้นเพียงจุดเดียว ฉันไม่มีตัวแปรเฉพาะที่ระบุว่าเกมจบลงแล้ว มันจบลงเมื่อผู้เล่นนั้นเกิดขึ้นพร้อมกับวุสตุสหรือหลุม ดังนั้นเมื่อผู้เล่นชนะฉันจะแสดงข้อความที่ชนะ แต่ย้ายหลุมไปยังผู้เล่นเพื่อควักออกจากวง! ฉันไม่สามารถวางผู้เล่นลงหลุมเนื่องจากวุดปัสอาจอยู่ที่นั่นและฉันจะได้รับข้อความเกี่ยวกับวู้ดปัสที่ฉันไม่ต้องการ

rev0program ทำงานได้อย่างสมบูรณ์แบบใน visual studio แต่ IDE กล่าวว่า "stack stack รอบ ๆ i เสียหาย" เมื่อออก นี่เป็นเพราะ scanf พยายามที่จะใส่intลงในchar.เดนนิสรายงานพฤติกรรมที่ไม่ถูกต้องบนเครื่อง Linux ของเขาเพราะสิ่งนี้ อย่างไรก็ตามมันได้รับการแก้ไขโดยการใช้ประเภทที่ถูกต้องใน rev 1

บรรทัดสำหรับแสดงบอร์ดในรอบที่ 0 นั้นค่อนข้างงุ่มง่ามและแตกต่างกันเล็กน้อยบนแพลตฟอร์มอื่น ๆ ในprintf(" %c%c%c")ตรงกลาง% c จะแสดงตัวอักษรที่พิมพ์ได้ % c สุดท้ายคือ ASCII 0 หรือ ASCII 10 (\ n, ขึ้นบรรทัดใหม่กับ carriage return ใน Windows) ดูเหมือนจะไม่มีอักขระใน Windows ที่ใช้งานได้ในคอนโซลที่จะลงบรรทัดโดยไม่ต้องคืนค่าขนส่ง หากฉันไม่ต้องการแท็บ c% แรก (ASCII 0 หรือ ASCII 9 ก่อนอักขระละติจูด 1 แท็บนั้นไม่ได้ระบุอย่างชัดเจนในพฤติกรรมของพวกเขา) พื้นที่ชั้นนำปรับปรุงการจัดรูปแบบ (ทำให้ละติจูด 3 และ 2 อักขระใกล้กับละติจูด 1 อักขระ .) Rev 1 มี revison ของบรรทัดนี้ซึ่งใช้อักขระ \ f formfeed ดังนั้นจึงไม่ต้องการอักขระรูปแบบที่จุดเริ่มต้นของ printf ทำให้สั้นลง แต่ \ f ไม่ทำงานใน Windows


1
ฉันรักการเขียน
Michael Stern

ฉันไม่แน่ใจว่าเป็นเพราะการปรับเปลี่ยนที่ฉันต้องทำเพื่อรวบรวมกับ GCC บน Linux (ลบรวมแรกแทนที่scanf_sด้วยscanfและรวมstdio.hถ้าฉันรวบรวมเป็น C ++ rater กว่า C) แต่มันไม่ทำงานสำหรับ ฉัน. ตัวอย่างเช่นถ้าฉันไปทางซ้ายแล้วกลับมาที่จุดเริ่มต้น ( 15 35) ฉันอยู่ในห้องที่แตกต่างจากที่ฉันเริ่มเข้ามา
เดนนิส

@Dennis ฉันได้ติดตามที่มาของข้อผิดพลาดเมื่อออก มันเป็น scanf_s (ควรจะปลอดภัย!) ซึ่ง "ทำลายสแต็กรอบ ๆ ตัวแปร i" เมื่อพยายามใส่สิ่งที่ฉันถือว่าเป็นจำนวนเต็ม 32 บิตเป็นถ่าน ดังนั้นสิ่งแรกที่ฉันอยากจะแนะนำคือตรวจสอบประเภทที่ scanf ใช้สำหรับ "% d" และเปลี่ยนตัวแปร i เป็นประเภทนั้น ฉันได้รับคำตอบที่ถูกต้องพร้อมข้อผิดพลาดในการออกจากถ่านคำตอบที่ถูกต้องไม่มีข้อผิดพลาดในการออกจาก int และคำตอบที่ไม่ถูกต้องสำหรับชนิดของ Microsoft __int64 (ยาวยาวเทียบเท่ายกเว้นฉันใส่ "% lld") รุ่นที่ไม่ดีและคุณมีปัญหากับจอแสดงผลหรือไม่?
เลเวลริเวอร์เซนต์

@steveverrill: ใช่ฉันได้ลองทั้งสองรุ่นแล้ว ประเภทของiปัญหาแน่นอน หน้าคนพูดว่า: " dตรงกับจำนวนเต็มทศนิยมลงนามเลือก; ชี้ต่อไปจะต้องชี้ไปยังint ." การเปลี่ยนประเภททำให้มันใช้ได้ดี
Dennis

@ สตีฟเวอร์ริลล์: ฉันไม่รู้ว่า VS จัดการกับสิ่งต่าง ๆ อย่างไร แต่ถ้าคุณคอมไพล์กับ GCC (ในฐานะ C ไม่ใช่ C ++) คุณสามารถบันทึกตัวอักษรจำนวนมากได้ ไม่จำเป็นต้องมีการรวมหากคุณแทนที่NULLด้วย0และscanf_sด้วยscanfคุณไม่จำเป็นต้องใช้intมาก่อนmainและคุณสามารถย้ายiและdนอกส่วนหลัก (ค่าเริ่มต้นเป็นintและเริ่มต้นได้ที่0) นอกจากนี้คุณยังสามารถกำหนดp=19,h=rand()%p,w=rand()%pให้เปลี่ยนm[]ด้วยและมันควรจะเป็นไปได้ที่จะกำหนดแมโครสำหรับกรณีของ*m if(...==...)puts(...);
เดนนิส

9

GolfScript, 269 ตัวอักษร

{puts}:|;20,{;9{rand}:r~}$3<(:>"B:%d`w85>2n+Fup`y/>@D-=J7ldnx/W5XsLAb8~"{32-}%"`\24"{base}/3/{[.[~@].[~@]]}%:A=3r=0=:F;~:W;:P;{>A={0=F=}?:^P&!!{"You feel a breeze"|}*^W&!!{"You smell a wumpus"|}*'"#{'9.?r';STDIN.gets()}"'++~);(3%^=\4`={W={"Your arrow hit the wumpus"|0}{"Your arrow didn't hit anything"|W A=0=3r=:W>=.!\{"The wumpus catches you"|}*}if}{>:F;:>W=.!\{"You ran into the wumpus"|}*>P=.!\{"You fell into the pit"|}*&}if}do

โปรดทราบว่า 163 ถูกหักออกจากการนับจำนวนอักขระสำหรับสตริงที่มีการเข้ารหัสยาก ถ้าคุณต้องการ debug output โดยระบุหมายเลขห้องเพิ่มบรรทัดต่อไปนี้ทันทีหลังจากที่เกิดขึ้นครั้งแรกของ^:

'  YOU 'F'->'>+++puts'  DIRECTIONS [BRL] '^`+puts'  PIT 'P+puts'  WUMPUS 'W+puts 

ตัวอย่างเซสชัน (พร้อมเอาต์พุตดีบักเพิ่มเติม):

  YOU 6->11
  DIRECTIONS [BRL] [6 7 16]
  PIT 7
  WUMPUS 5
You feel a breeze
25
  YOU 11->16
  DIRECTIONS [BRL] [11 17 15]
  PIT 7
  WUMPUS 5
35
  YOU 16->11
  DIRECTIONS [BRL] [16 6 7]
  PIT 7
  WUMPUS 5
You feel a breeze
15
  YOU 11->6
  DIRECTIONS [BRL] [11 10 1]
  PIT 7
  WUMPUS 5
15
  YOU 6->10
  DIRECTIONS [BRL] [6 15 5]
  PIT 7
  WUMPUS 5
You smell a wumpus
14
Your arrow didn't hit anything
  YOU 6->10
  DIRECTIONS [BRL] [6 15 5]
  PIT 7
  WUMPUS 0
25
  YOU 10->5
  DIRECTIONS [BRL] [10 14 0]
  PIT 7
  WUMPUS 0
You smell a wumpus
24
Your arrow hit the wumpus

นี่คือรหัสการทำงานแรก กลับมาอีกครั้งเพื่อเล่นกอล์ฟเพิ่มเติม
ฮาเวิร์ด

รหัสของฉันปัจจุบันมีความยาว 1 อักขระ ฉันกำลังมองหาวิธีที่เป็นไปได้ในการเล่นกอล์ฟต่อไป!
Timtech

ไม่ใช่ว่าคุณต้องการความช่วยเหลือจากฉัน แต่คุณสามารถบันทึก 14 ตัวอักษรโดยกำหนด{puts}:|;5 ตัวอักษรโดยแทนที่RและWด้วย-และ>(อนุญาตให้กำจัดช่องว่างโดยรอบ) และ 9 ตัวอักษรโดยการวาง'> 'print(ดูเหมือนจะไม่ต้องการคำถาม)
Dennis

@Dennis ขอขอบคุณ ฉันจะใช้คำแนะนำของคุณอย่างแน่นอน
ฮาเวิร์ด

9

JavaScript (ECMAScript 6) - 2197 1759 -45% = 967.45 ตัวอักษร

เกือบจะตีกอล์ฟเสร็จแล้ว ...

รวมถึง GUI พร้อมแผนที่ Icosahedral และ Mega-Bats สำหรับโบนัสเต็มรูปแบบ

GUI ของ Wumpus

  • แต่ละห้องมี 4 ปุ่ม: X(หลุม); B(Mega-Bat); W(Wumpus); และP(คุณ)
  • ตำแหน่งปัจจุบันของคุณคือสีน้ำเงิน
  • ปุ่มจะเป็นสีแดงหากวัตถุที่ใช้แสดงอยู่ในตำแหน่งนั้นและเป็นสีเขียวหากไม่ได้อยู่ในตำแหน่งนั้นอย่างแน่นอน
  • WและPปุ่มสามารถคลิกได้เฉพาะในห้องที่อยู่ติดกับตำแหน่งปัจจุบันของคุณ
  • หากคุณชนะพื้นหลังจะเปลี่ยนเป็นสีเขียวและถ้าคุณตายพื้นหลังจะเปลี่ยนเป็นสีแดง

รหัส:

P=x=>parseInt(x,36);Q=(y,a=4)=>[P(x)<<a for(x of y)];e=Q("def45c6di7ej1ai1bj2af3bf9dg8eh46b57a1gh0280390678ci9cj24g35h",0);X=Q("o6fl6afnik27bloscfaf");Y=Q("icp8i8t4jej4encjjan6");A='appendChild';C='createElement';W='width';H='height';G='background-color';L='disabled';I='innerHTML';N='className';D=document;R=Math.random;B=D.body;E=[];F=1<0;T=!F;Z="XBWP";s=D[C]('style');s.type='text/css';t='.A{position:absolute;left:25px;top:25px}.D{'+W+':50px;'+H+':50px}.D button{'+W+':25px;'+H+':25px;float:left}.R{'+G+':red}.G{'+G+':green}.B{'+G+':blue}';for(i in X)t+='#D'+i+'{left:'+X[i]+'px;top:'+Y[i]+'px}';s[A](D.createTextNode(t));D.head[A](s);c=D[C]('canvas');c[N]='A';c[W]=c[H]=500;B[A](c);x=c.getContext('2d');x.beginPath();d=(i,b,v)=>{for(j=0;j<3;j++){E[e[3*i+j]][b][L]=v}};a=(i,l,v)=>{t=F;for(j=0;j<3;j++)t=e[3*i+j]==l?T:t;if(t)M[v]++;b=E[i][v];b.c=-1;for(j=0;j<3;j++)E[e[3*i+j]][v].c+=t?1:-1;for(j of E)j[v][N]=j[v].c==M[v]?'R':'G';};M=[0,0,0];S=v=>{M[v]=0;for(i of E){i[v][N]='';i[v].c=0}};for(i in X){for(j=3*i;j<3*i+3;j++)x.moveTo(X[i],Y[i])|x.lineTo(X[e[j]],Y[e[j]]);B[A](v=D[C]('div'));v[N]='A D';v.id='D'+i;E[i]=[];for(j in Z){b=E[i][j]=v[A](D[C]('button'));b[L]=T;b.i=i;b.c=0;b[I]=Z[j];}E[i][4][O='onclick']=function(){d(P,2,T);d(P,3,T);if(this.i==W)c[N]+=' G';else{S(2);W=e[3*W+R()*3|0];if(W==P)c[N]+=' R';else{a(P,W,2);d(P,2,F);d(P,3,F)}}};E[i][3][O]=function(){d(P,2,T);d(P,3,T);E[P][3][N]='';P=this.i;if(W==P||Q==P){c[N]+=' R';return}else if(Z==P){j=P;do{P=R()*20|0}while(P==W||P==Q||P==j);do{Z=R()*20|0}while(Z==j||Z==P);S(1)}d(P,2,F);d(P,3,F);E[P][3][N]='B';a(P,Q,0);a(P,Z,1);a(P,W,2)}}x.stroke();P=R()*20|0;do{W=R()*20|0}while(W==P);do{Q=R()*20|0}while(Q==P);do{Z=R()*20|0}while(Z==P);E[P][3][N]='B';a(P,Q,0);a(P,Z,1);a(P,W,2);d(P,2,F);d(P,3,F)

คุณจะได้รับ 1066 โดยไม่มี ECMA 6 โดยใช้คอมไพเลอร์ปิด
AMK

ฉันสงสัยว่ามันจะง่ายขึ้นแค่ไหนเมื่อคุณมีภาพกราฟิกเพื่อช่วยลดสิ่งที่อยู่ 1+ แต่มันเป็นเรื่องเล็กน้อยง่ายเกินไป :)
Sylwester

9

Bash, 365 (เวอร์ชันการทำงานแรก 726!)

ติดตาม GOLFSCRIPT หรือไม่

@Dennis ได้ทำการเล่นกอล์ฟทั้งหมดสำหรับฉันแล้ว ขอบคุณ!

โปรแกรมถือว่าอินพุตที่ถูกต้อง อินพุตที่ถูกต้องคือทิศทางที่คุณเลือก (1 สำหรับขวา 2 สำหรับซ้าย 3 สำหรับด้านหลัง) ตามด้วยการกระทำของคุณ (4 สำหรับการถ่ายภาพ 5 เพื่อเดิน)

คำอธิบายบางอย่าง

ปกติแล้วฉันจะอธิบายอย่างละเอียดมาก แต่นี่อาจจะซับซ้อนเกินไปสำหรับฉันที่จะใส่ใจ

จุดสุดยอดแต่ละอันบนกราฟรูปทรงสิบสองข้างจะถูกเข้ารหัสเป็นตัวอักษร (a = 1, b = 2, ... t = 20)

ตำแหน่งเริ่มต้นของผู้เล่นอยู่ที่ 20 (และพวกเขายืนด้วยหลังของพวกเขาถึง 18) เนื่องจากมันไม่สำคัญในตัวเองเพียงตำแหน่งสัมพัทธ์ของผู้เล่นหลุมและเรื่องของบัม

ตัวแปรจัด$pเก็บตำแหน่งของผู้เล่น $rเก็บตำแหน่งก่อนหน้าของผู้เล่น $wคือ wumpus และ$h(H สำหรับหลุม) คือหลุม

รหัส

p=t
r=r
j=echo
Z=npoemfsgnohtksblbtpckdpljqnriogelfhkbqrcaiadjhagimsmjtqecrdf
q(){ $j ${Z:RANDOM%19*3:1};}
C(){ [[ ${!1} =~ ${!2} ]];}
d(){ s=${Z:30#$1*3-30:3};}
w=`q`
h=`q`
for((;;));{
b=$p
d $p
u=u${s#*$r}$s
C w p&&$j The wumpus ate you&&exit
C h p&&$j You fell in the pit&&exit
C u w&&$j You smell the wumpus
C u h&&$j You feel a breeze from a pit
read i
F=5
y=${u:i/10:1};C i F&&p=$y&&r=$b||{ d $w;C y w&&$j You killed the wumpus&&exit;$j You missed;w=${s:RANDOM%3:1};};}

ประวัติรุ่น

  1. เริ่มต้นปล่อย 698 chars
  2. แก้ไขข้อผิดพลาดที่ "คุณรู้สึกว่าสายลม" และ "คุณได้กลิ่นของ wumpus" ไม่สามารถแสดงได้ในเวลาเดียวกัน บันทึก 39 ตัวอักษรโดยสร้างฟังก์ชั่นการสร้างตัวเลขสุ่ม
  3. โปรดจำไว้ว่า wumpus นั้นเคลื่อนไหวถ้าคุณยิงและพลาด 726 ตัวอักษร
  4. ทำgrep -oEตัวแปร บันทึก 5 ตัวอักษร
  5. ทำ[a-z]{3}ตัวแปร บันทึก 3 ตัวอักษร
  6. ทำechoตัวแปร บันทึก 5 ตัวอักษร
  7. ดำเนินการตามคำแนะนำส่วนใหญ่ของ @Dennis บันทึก 72 ตัวอักษร
  8. เพิ่มคำแนะนำที่เหลือทั้งหมด บันทึก 68 ตัวอักษร
  9. บันทึก 2 ตัวอักษรจากคำแนะนำของ @DigitalTrauma
  10. แก้ไขข้อผิดพลาดที่สำคัญซึ่งคุณสามารถยิง wumpus ได้หากมันอยู่ทางด้านขวา นับตัวอักษรเดียวกัน
  11. การขยายตัวพารามิเตอร์มือสองให้โกนออก 2 $mตัวอักษรโดยใช้
  12. โกนหนวดออกเป็นจำนวนมากโดยการทิ้งgrepและรู้สึกไวขึ้นเล็กน้อย
  13. กำหนดCเป็นฟังก์ชั่นการค้นหา regexp เพื่อใช้ใน if statement และEฟังก์ชั่นการพิมพ์ "You kill the wumpus" และออกจาก
  14. บันทึก 1 อักขระโดยการจัดเรียงใหม่ "if statement"
  15. บันทึกตัวอักษรจำนวนมากโดยการกำจัดdและลบวงเล็บเหลี่ยมที่ไม่จำเป็นออก
  16. แก้ไขข้อบกพร่อง เพิ่มตัวอักษรจำนวนมาก :(
  17. การประหยัด MOARR ( http://xkcd.com/1296/ )
  18. อีกความคิดของ @Dennis (บันทึกสองสามตัวอักษร) และความคิดสร้างสรรค์ของฉัน (ab) ใช้การอ้อม (ประหยัด 1 อักขระ)
  19. การแก้ไขรูปแบบสำหรับ q ()
  20. เพิ่มเอาต์พุตที่เหมาะสมอีกครั้ง

วิ่งตัวอย่าง

"In:" is input, "Out: is output"

ผู้เล่นเดินไปรอบ ๆ สักครู่กลิ่นวูมบัสและหน่อ พวกเขาคิดถึงและวุสปัสเข้ามาในห้องของพวกเขาและกินมัน

ใน: 15

ใน: 15

ใน: 25

ใน: 25

ใน: 15

ออกมา: คุณได้กลิ่น wumpus

ใน: 14

ออก: คุณพลาด

Out: คนป่ากินคุณ


1
ฉันคิดว่าคุณสามารถทำให้โค้ดของคุณสั้นลงอย่างน้อย 100 ไบต์ 1. exitมีความยาวเกินหนึ่งไบต์g=1และไม่จำเป็นต้องทดสอบข้อความที่ไม่เป็นศูนย์gและบางelifข้อความ 2. คุณสามารถใช้((i==35))แทน[ $i = 35 ]และแทน...&&... if ... then ... fi3. q(){ L=({a..s});$j ${L[RANDOM%19]};}และn=`$k $w$m<<<$d`;w=${n:RANDOM%2+1:1}บันทึกทั้งสองไม่กี่ไบต์
เดนนิส

1
แทนที่while :;do... doneด้วยfor((;;);{... }เพื่อการประหยัด 3 ถ่าน
Digital Trauma

1
@professorfish: ฉันคิดว่าฟังก์ชั่นจะทำงานได้ดีกว่าวิธีการ string-grep-cut ปัจจุบัน ยกตัวอย่างเช่นd(){ x=npoemfgnshtoksblbtckpdpljqniorelgfhkbqraicadjaghimsmjtqecrdf;s=${x:3*30#$1-30:3};}จะช่วยให้คุณเปลี่ยนคำจำกัดความของsและnด้วยและd $p d $wหากคุณเพิ่มเติมกำหนดu=${s#*$r}$s(และปรับคำจำกัดความของlและfตาม) คุณจะไม่ต้องการ$kและ$mอีกต่อไป ฉันบันทึก 83 ไบต์ฉันคิดว่า นอกจากนี้ยังq ()ไม่จำเป็นต้องใช้พื้นที่ใน
Dennis

1
@professorfish: และคุณสามารถบันทึก 3 ไบต์เพิ่มเติมโดยการกำหนดและการเปลี่ยนเช่นสองไปบรรทัดสุดท้ายด้วยc(){ [[ $1 =~ $2 ]];} c $r $b||{ $j You missed;d $w;w=${s:RANDOM%2+1:1};}
Dennis

1
@professorfish: การใช้ฟังก์ชันที่ฉันแนะนำควรสั้นลง 3 ไบต์ คุณสามารถบันทึก 106 ไบต์เพิ่มเติมโดยการเปลี่ยนสี่สายหลังจากb=$pที่มีd $p;u=u${s#*$r}$sเส้นหลังread iด้วยและการกำจัดy=${u:i/10:1};C $i 5&&{ p=$y;r=$b;}||{ d $w;C $y $w&&$j You killed the wumpus&&exit;$j You missed;w=${s:RANDOM%2:1};} E()
Dennis

6

GolfScript ( 206 198)

[5:C,]{{.{[~@]}:>~.{-1%}:<~}%.&}8*({[.<><.<><]}:F~-{99rand}$~5,{.<{>.'You smell a wumpus.\n'4{$F@?~!!*}:Q~{print}:,~}3*{>.'You feel a breeze.\n'5Q,}3*'"#{'C):C';STDIN.gets()}"'++~~:&9/{>}*&5%{'You killed the wumpus.'3Q{\<{>}3rand*\"Your arrow didn't hit anything.\n",0}or}{\;.'You fell into the pit.'4Q}if\.'You were killed by the wumpus.'4Q@or:n!}do];

ในที่สุดก็ถึงกับรุ่นตารางการค้นหาของเดนนิสซึ่งมันยืมมาไม่มาก สิ่งที่น่าสนใจเกี่ยวกับรุ่นนี้คือมันไม่มีตารางการค้นหาสำหรับเค้าโครงห้อง

60 symmetries การหมุนของฮอว์คิงเป็น isomorphic จะสลับกันเป็นกลุ่มในวันที่ 5 ตัวอักษร A_5 หลังจากลองใช้วิธีการทุกรูปแบบในการเป็นตัวแทนของกลุ่มอย่างกระชับฉันได้กลับมาสู่วิธีที่ง่ายที่สุด: แต่ละองค์ประกอบมีการเปลี่ยนแปลงที่เท่าเทียมกัน กลุ่มสามารถสร้างขึ้นจากสองเครื่องกำเนิดไฟฟ้าในมากกว่าหนึ่งวิธี: วิธีการฉันการใช้เครื่องกำเนิดไฟฟ้าและ3 3 1เหล่านี้ช่วยให้เราสามารถสร้าง1 = 3 3 1, และ2 = 3 3 1 3 13 = 3

สังเกตว่าทิศทางนั้น3สอดคล้องกับองค์ประกอบของคำสั่งที่ 2 เพราะหลังจากผ่านประตูด้านหลังคุณไปแล้วประตูนั้นก็อยู่ข้างคุณอีกครั้ง ทิศทาง1สอดคล้องกับองค์ประกอบของคำสั่งที่ 5 เดินไปรอบ ๆ จุดยอดของรูปทรงไอโซโทป (องค์ประกอบในทำนองเดียวกัน2) และการรวมกัน3 1นั้นเป็นลำดับที่ 3 เนื่องจากจะวนรอบห้องที่อยู่ติดกับห้องที่เริ่มด้านหลังคุณ

ดังนั้นเรากำลังมองหาการเรียงสับเปลี่ยนของคำสั่งที่ 2 เพื่อเป็นตัวแทนของทิศทาง3และการเรียงสับเปลี่ยนของคำสั่งที่ 5 เพื่อเป็นตัวแทนทิศทาง1ที่3 1เป็นคำสั่งที่ 3

มีการเรียงสับเปลี่ยน 15 ลำดับของคำสั่งที่ 2 ใน A_5 และสำหรับแต่ละอันจะมีการเปลี่ยนลำดับผู้สมัคร 8 ครั้งสำหรับ1(และด้วยเหตุนี้3 1) มีสถานที่ท่องเที่ยวที่ชัดเจนที่จะเป็น[4 3 2 1 0]สำหรับ3: -1%ย้อนกลับอาร์เรย์เป็นเพียง พีชคณิตสหายที่เป็นไปได้3 1ฉันได้เลือกซึ่งยอมรับว่าการดำเนินงานที่ค่อนข้างสั้นเป็น[0 1 3 4 2][~@]

Ungolfed

# Generate the 60 permutations by repeated application of `3 1` and `3`
[5:C,]{{.{[~@]}:>~.{-1%}:<~}%.&}8*
# Remove [0 1 2 3 4] and its equivalence class (apply 3 (3 1)^n 3 for n in 0,1,2)
({[.<><.<><]}:F~-
# Shuffle the remaining 57 options to select random starting points for wumpus and pit
# Note that this introduces a slight bias against them being in the same room,
# but it's still possible.
{99rand}$~
# Start player at [0 1 2 3 4]
5,
{
    # Stack: Pit Wumpus Player
    .<
    # The adjacent rooms to the player are Player<> , Player<>> , and Player<>>>
    # If the wumpus is in one of those rooms, say so.
    {
        >."You smell a wumpus.\n"4
        {
            # ... X str off
            $F@?~!!*
            # ... str off$F X ?~!! *
            # Which means that we leave either str (if off$ and X are equivalent)
            # or the empty string on the stack
        }:Q~
        {print}:,~
    }3*
    # Ditto for the pit
    {>."You feel a breeze.\n"5Q,}3*
    # Read one line from STDIN.
    '"#{'C):C';STDIN.gets()}"'++~~
    # Stack: Pit Wumpus Player Player< Input
    # Find the room corresponding to the specified direction.
    :&9/{>}*&
    # Stack: Pit Wumpus Player TargetRoom Input
    5%{
        # Shoots:
        "You killed the wumpus."3Q
        {
            \<{>}3rand*\ # Move the wumpus to an adjacent room
            "Your arrow didn't hit anything.\n", # Inform
            0 # Continue
        }
        or
    }{
        # Moves:
        \;
        # If player and pit share a room, say so.
        ."You fell into the pit."4Q
    }if
    # If player and wumpus share a room, say so.
    # NB If the player walks into a room with the pit and the wumpus,
    # the `or` favours the pit death.
    \."You were killed by the wumpus."4Q@or
    # Save the topmost element of the stack for output if we break the loop. Loop if it's falsy.
    :n!
}do
# Ditch the junk.
];

วิธีพีชคณิตที่ดี! มีข้อผิดพลาดเล็ก ๆ น้อย ๆ เป็นว่า: 10/@3%=พยายามเข้าถึงองค์ประกอบที่สี่ของอาร์เรย์ของความยาว 3 35ถ้าใส่เป็น
Dennis

@Dennis ใช่ฉันรู้หลังจากเข้านอน ฉันสามารถนึกถึงวิธีการต่าง ๆ ในการแก้ไขทั้งหมดนี้มีค่าใช้จ่าย 2
Peter Taylor

9/3%@3%=คุณจะได้รับกลับมาเป็นหนึ่งเดียวกับถ่าน
Dennis

ปัจจุบันฉันมี 7 ตัวอักษรที่มีการปรับโครงสร้างที่รุนแรงขึ้น แต่นั่นคือถ่าน 1 ตัว9/แทนที่จะ10/ยังใช้งานได้ดีขอบคุณ
Peter Taylor

5

Wumpus , 384 - 129 (สตริง) = 255 ไบต์

1SDL2vSD70L?.;;3AL1a!?,9)".supmuw a llems uoY"99+1.
II5x?,&WC2.           L2a!?,9)".ezeerb a leef uoY"93*2.
L1a!,FCFC[&WCL1a!?,"!supm",AW#16#[(=]?.;;l(&o1.
    ?,".uoy eta ",".gnih","uw eht dellik uoY"#22&oN@
     #15#L2a!?. ,"supmu","tyna tih t'ndid worra ruoY"#31&oND";"4L1a!?.;;L1xSUL1xSD=F-#81~4~?.;;;CCWC=F-#97~4~?.;;;2.
 ,"nto the pit."|       "w ehT"l&oN@
 |"i llef uoY"l2-&oN@

ลองออนไลน์! (แน่นอน TIO ไม่สมเหตุสมผลเพราะคุณไม่สามารถใช้โปรแกรมแบบโต้ตอบได้และเมื่อโปรแกรมหมดคำแนะนำใน STDIN โปรแกรมจะอ่าน0 0ซึ่งเทียบเท่ากับ3 4ดังนั้นคุณจะจบลง ยิงลูกศรจนกระทั่ง Wumpus เคลื่อนไปที่นั่นหรือฆ่าคุณ)

เมื่อเรียกใช้ภายในเครื่องตรวจสอบให้แน่ใจว่า linefeed หลังจากหมายเลขที่สองของแต่ละอินพุตถูกล้างข้อมูล (เนื่องจาก Wumpus ต้องการเพื่อตรวจสอบว่าหมายเลขนั้นอยู่เหนือ) ใน Powershell ฉันต้องป้อนอักขระอีกหนึ่งตัวหลังจาก linefeed เพื่อให้ทำงานได้ (ไม่สำคัญว่าตัวละครตัวไหน แต่ฉันเพิ่งใช้ตัวกรองคู่บรรทัดสำหรับการทดสอบ)

มีพื้นที่มากมายสำหรับการตีกอล์ฟต่อไป แต่การลองเลย์เอาต์ใหม่ที่สมบูรณ์ใช้เวลาสักครู่ คะแนนสุดท้ายยังขึ้นอยู่กับสตริงจริงที่ฉันใช้เพราะในภาษา 2D สตริง N ไบต์มีแนวโน้มที่จะเสียค่าใช้จ่ายคุณมากกว่า N ไบต์ของซอร์สโค้ดเพราะมันทำให้มีข้อ จำกัด ที่สำคัญเกี่ยวกับการจัดวางโค้ดและคุณมักจะ จำเป็นต้องแบ่งออกเป็นหลายส่วน (เกิดขึ้นคำพูดคู่เพิ่มเติม) ในตอนท้ายสุดขีดถ้าฉันลดทุก ๆ สตริงเป็นตัวอักษรเดียว (และ -129 ถึง -12) ฉันอาจจะประหยัดได้กว่าหนึ่งไบต์

คำอธิบาย

ข้อสงวนสิทธิ์แรก: แม้จะมีชื่อภาษา แต่ก็ไม่ได้ออกแบบมาเพื่อให้ใช้งานHunt the Wumpus ได้ง่ายเป็นพิเศษ แต่ก่อนอื่นฉันออกแบบภาษารอบ ๆ ชุดรูปแบบของสามเหลี่ยมลงเอยด้วยโครงสร้างข้อมูลแบบ icosahedral และตัดสินใจที่จะเรียกมันว่า Wumpus เพราะสิ่งนั้น

ใช่ในขณะที่ Wumpus ส่วนใหญ่เป็นแบบกองซ้อน แต่ก็มีการลงทะเบียน 20 รายการซึ่งจัดเรียงอยู่รอบ ๆ ใบหน้าของไอโซโทป นั่นหมายความว่าเราได้รับโครงสร้างข้อมูลเพื่อแสดงแผนที่ฟรี สิ่งเดียวที่เราทำไม่ได้ง่ายๆคือค้นหาใบหน้าที่เฉพาะเจาะจงบน icosahedron ดังนั้นเพื่อค้นหาพวกเราต้อง "roll the d20" จนกว่าเราจะพบใบหน้าที่เราต้องการ (เป็นไปได้ที่จะทำสิ่งนี้ในลักษณะที่กำหนดได้ แต่อาจต้องใช้เวลานานกว่าไบต์) การค้นหาใบหน้าเช่นนี้จะยุติลงอย่างแน่นอน (เช่นความน่าจะเป็นที่ 1) ดังนั้นการค้นหาที่ดำเนินไปตลอดกาลจึงไม่เกี่ยวข้องกับการปฏิบัติ)

รหัสด้านบนเป็นเวอร์ชั่น golfed ของการใช้งานครั้งแรกนี้ด้วยรูปแบบ saner:

1SDL2vSD70L?.;;2.  < Setup; jumps to third line which starts the main loop

3AL1a! ?,".supmuw a llems uoY"#19&oN03.          < This section checks the player's surroundings.
        L2a!?,".ezeerb a leef uoY"#18&oN04.
             AW(=12[?.;;7.

    }&WC#11.                                     < This section reads the input. The top branch moves, the bottom branch shoots
II5x^                                              and kills or moves the wumpus.
     {FCFC[&WCL1a !?,"!supmuw eht dellik uoY"#22&oN@
                    ".gnihtyna tih t'ndid worra ruoY"#31&oND#59 9L1a!?.;;L1xSUL1xSD=F-#82~9~?.;;;CCWC=F-#98~9~?.;;;#11.

L1a!?,".uoy eta supmuw ehT"#19&oN@               < This section checks whether the player dies.
     L2a!?,".tip eht otni llef uoY"#22&oN@         Otherwise, we return back to the third line.
          2.

เนื่องจากการเล่นกอล์ฟส่วนใหญ่เกี่ยวข้องกับการบีบเลย์เอาต์ฉันจะอธิบายรุ่นนี้ก่อน (จนกว่าฉันจะเพิ่มเทคนิคการตีกอล์ฟที่เหนือกว่าการปรับโครงสร้างรหัส)

เริ่มจากรหัสการติดตั้ง:

1SDL2vSD70L?.;;2.

ในขั้นต้นใบหน้าทั้งหมดจะถูกตั้งค่าเป็น0 เราจะเข้ารหัส wumpus โดยการตั้งค่า 1 บิตของใบหน้าที่เกี่ยวข้องและหลุมโดยการตั้งค่า 2 บิต ด้วยวิธีนี้พวกเขาทั้งสองสามารถอยู่ในห้องเดียวกัน ตำแหน่งของผู้เล่นจะไม่ถูกบันทึกลงบน icosahedron เลย แต่มันจะเป็นใบหน้าที่เคลื่อนไหวอยู่เสมอ (มีเพียงหนึ่งใน 20 คนที่ลงทะเบียนในเวลาเดียวกัน)

1S     Store a 1 in the initially active face to put the wumpus there.
D      Roll the d20. Applies a uniformly random rotation to the icosahedron.
L2vS   Load the value of that face (in case it's the wumpus's), set the 2-bit
       and store the result back on that face.

ตอนนี้เราต้องหาหน้าว่างแบบสุ่มเพื่อให้ผู้เล่นเข้ามา

D      Roll the D20.
70     Push 7 and 0 which are the coordinates of the D in the program.
L      Load the value of the current face.
?.     If that value is non-zero (i.e. the active face has either the
       wumpus or the pit), jump back to the D to reroll the die.
;;2.   Otherwise, discard the 0 and the 7 and jump to (0, 2), which is
       the beginning of the main loop.

ส่วนถัดไปตรวจสอบสภาพแวดล้อมของผู้เล่นและพิมพ์คำเตือนที่เหมาะสม:

3AL1a! ?,".supmuw a llems uoY"#19&oN03.
        L2a!?,".ezeerb a leef uoY"#18&oN04.
             AW(=12[?.;;7.

นี่คือลูปที่เราวิ่งผ่าน 3 ครั้ง ในแต่ละครั้งเราจะมองไปที่เพื่อนบ้านที่ถูกต้องพิมพ์สตริงที่เหมาะสมหากมีอันตรายและจากนั้นหมุน icosahedron 120 °

3    Push a 3 as a loop counter.
A    Tip the icosahedron onto the NW neighbour of the active face, which
     will be used to represent the right-hand room.
L1a  Extract the 1-bit of the value on that face.
!?,  If that value is zero, strafe to the next line, otherwise continue.

  ".supmuw a llems uoY"#19&oN03.
     Print "You smell a wumpus.", a linefeed and then jump to the next line.

L2a  Extract the 2-bit of the value on that face.
!?,  If that value is zero, strafe to the next line, otherwise continue.

  ".ezeerb a leef uoY"#18&oN04.
     Print "You feel a breeze.", a linefeed and then jump to the next line.
A    Tip back to the original active room (where the player is).
W    Rotate the icosahedron by 120°, so that the next iteration checks
     another neighbour.
(=   Decrement the loop counter and duplicate it.
12   Push 1, 2, the coordinates of the cell after the 3 (the loop counter).
[    Pull up one copy of the loop counter.
?.   If it's non-zero, jump to the beginning of the loop, otherwise continue.
;;7. Discard the 2 and the 1 and jump to (0, 7), which reads the player's
     input for this turn.

ส่วนถัดไปจะอ่านตัวเลขสองตัวจากผู้เล่นจากนั้นจึงย้ายผู้เล่นหรือยิงธนู อดีตเป็นเรื่องไม่สำคัญ ปัญหาหลักสำหรับการถ่ายลูกศรคือกรณีที่มันพลาดไป ในกรณีนี้เราก) ต้องไปหาวุดปั้มเพื่อเคลื่อนย้ายมันจากนั้นข) กลับไปที่ห้องของผู้เล่นและการวางแนวที่ถูกต้องของ icosahedron (เพื่อที่ว่า นี่เป็นส่วนที่แพงที่สุดของโปรแกรมทั้งหมด

    }&WC#11.
II5x^
     {FCFC[&WCL1a !?,"!supmuw eht dellik uoY"#22&oN@
                    ".gnihtyna tih t'ndid worra ruoY"#31&oND#59 9L1a!?.;;L1xSUL1xSD=F-#82~9~?.;;;CCWC=F-#98~9~?.;;;#11.

จุดเข้าสู่ส่วนนี้Iอยู่ทางด้านซ้าย

II   Read the integers from STDIN.
5x   XOR the second one with 5.
^    Turn either left or right, depending on the previous result. If the
     second input is 4, XORing with 5 gives 1 and the IP turns right.
     Otherwise, we get 0 and the IP turns left.

If the player entered 5, move:

}    Turn right so that the IP moves east again.
&W   If the room indicator is X, rotate the icosahedron by X*120°. This
     puts the target room south of the active face (where the back room
     normally is).
C    Tip the icosahedron onto the southern face. This moves the player there.
     Due to the way tipping works, the formerly active face will now be
     the southern neighbour, i.e. correctly at the back of the player.
#11. Jump to (0, 11), the final section which checks whether the player
     stepped into the pit or onto the wumpus.

If the player entered 4, move:

{    Turn left so that the IP moves east again.
F    Store the active face index (the player's position) on the stack.
CFC  Also store the face index of the southern neighbour (the back room)
     on the stack, so that we can recover the correct orientation if
     we need to.
[    Pull up the player's room choice.
&WC  Tip the icosahedron onto the corresponding face (same as for the move action)
L1a  Extract the 1-bit of the value on that face to check whether the arrow
     hit the wumpus.
!?,  If that value is zero, strafe to the next line, otherwise continue.

  "!supmuw eht dellik uoY"#22&oN@
     Print "You killed the wumpus.", a linefeed, and terminate the program.

".gnihtyna tih t'ndid worra ruoY"#31&oN
     Print "Your arrow didn't hit anything." and a linefeed.

This next bit is a loop which searches for the wumpus:

D    Roll the d20. The easiest way to search for the wumpus is to look at
     random faces.
#59 9
     Push 59 and 9, the coordinates of the beginning of this loop.
L1a  Extract the 1-bit of the value on the current face.
!?.  If that value is zero, jump back to the beginning of this loop to
     try another face, otherwise continue.
;;   Discard the 9 and the 59.
L1xS Unset the 1-bit of the current face to remove the wumpus there.
U    Tip the icosahedron onto a random neighbouring face. This moves us
     to a random adjacent room.
L1xS Set the 1-bit of the current face to put the wumpus there.

This next bit contains two loops which get us back to the player's room
with the correct orientation. We do this by first searching for the room
at the player's back, and then looking through its neighbours to find the
player's room.

D    Roll the d20.
=F-  Duplicate the back room index and subtract the current face index.
#82~9~
     Push 82 and 9 and pull up the difference we just computed.
?.   If the difference is non-zero (we've got the wrong room), jump back
     to the D to try again. Otherwise continue.
;;;  We've found the back room. Discard the 9, the 82 and the back room index.
C    Tip the icosahedron onto the southern face (one of the candidate
     neighbours which might be the player's room).
CWC  This begins the loop that searches for the player's room. Tip onto
     the back room, rotate by 120°, tip back. This cycles through the
     neighbours of the back room, while keeping the active face on those
     neighbours.
=F-  Duplicate the player's room index and subtract the current face index.
#98~9~
     Push 98 and 9 and pull up the difference we just computed.
?.   If the difference is non-zero (we've got the wrong room), jump back
     to the CWC to try again. Otherwise continue.
;;;  We've found the player's room and since we entered from the back room
     via C, we've also got the correct orientation. Discard the 9, the 98
     and the player's room index.
#11. Jump to (0, 11), the final section which checks whether the player
     stepped into the pit or onto the wumpus.

ว้านั่นเป็นส่วนที่ยาก ตอนนี้เราแค่ต้องตรวจสอบว่าผู้เล่นเสียชีวิตหรือไม่และเริ่มเล่นในลูปหลัก:

L1a!?,".uoy eta supmuw ehT"#19&oN@
     L2a!?,".tip eht otni llef uoY"#22&oN@
          2.

โครงสร้างของส่วนนี้จะเหมือนกับโครงสร้างที่เราใช้ในการตรวจสอบสภาพแวดล้อมของผู้เล่น: เราตรวจสอบใบหน้า 1 บิต (ห้องของผู้เล่น) และหากเป็นชุดเราจะพิมพ์The wumpus ate you.และยุติโปรแกรม มิฉะนั้นเราจะตรวจสอบ 2 บิตและเป็นชุดที่เราพิมพ์You fell into the pit.และยุติโปรแกรม มิฉะนั้นเราจะไปถึงจุด2.ที่กระโดดกลับไปที่จุดเริ่มต้นของลูปหลัก (ที่พิกัด(0, 2))


1

awk - ใหญ่

สิ่งนี้ไม่ได้สั้นอย่างที่ฉันหวังไว้ แต่ฉันใช้วิธีที่แตกต่างกันเล็กน้อยในการจัดการกับกราฟดังนั้นฉันจึงโพสต์เวอร์ชันที่ไม่ได้รับการดัดแปลง

ฉันใช้ประโยชน์จากความจริงที่ว่า icosahedron (20 polyhedron ด้าน) ภายใต้การหมุนที่รักษาทิศทางคือ isomorphic กับกลุ่มสลับระดับ 5 (5 องค์ประกอบเรียงสับเปลี่ยนที่มีจำนวนรอบความยาวเท่ากัน) ฉันเลือกพีชคณิตสองอันที่มีความยาววงรอบที่ 5 เป็น "ซ้าย" และ "ขวา" และฉันเลือกหนึ่งการเรียงสับเปลี่ยนที่มีรอบความยาว 2 เป็น "ย้อนกลับ" เมื่อใช้สิ่งเหล่านี้ฉันจะสร้างกราฟจากห้องหนึ่งโดยเดินไปตามเส้นทาง Hamiltonian (2xRRRLLLRLRL โดยใช้ 3xRB ในแต่ละห้องเพื่อจับภาพ 3 ทิศทางที่เป็นไปได้)

function meta(z,a,b,c,d) {
    if(z==COMPOSE) {
        split(a,c,"");
        split(b,d,"");
        return c[d[1]]c[d[2]]c[d[3]]c[d[4]]c[d[5]];
    }
    if(z==WALK) {
        split(R" "R" "R" "L" "L" "L" "R" "L" "R" "L,c);
        for(b = 1; b <= 20; b++) {
            map[a] = b;
            a = meta(COMPOSE,meta(COMPOSE,a,R),B);
            map[a] = b;
            a = meta(COMPOSE,meta(COMPOSE,a,R),B);
            map[a] = b;
            a = meta(COMPOSE,meta(COMPOSE,a,R),B);
            a = meta(COMPOSE, a, c[b % 10 + 1]);
        }
    }
    if(z==TEST) {
        a = map[meta(COMPOSE,U,L)];
        b = map[meta(COMPOSE,U,R)];
        c = map[meta(COMPOSE,U,B)];
        if(a==W||b==W||c==W) print "You smell the wumpus";
        if(a==P||b==P||c==P) print "You feel a breeze";
        if(map[U]==W) {
            print "You have been eaten by the wumpus";
            exit;
        }
        if(map[U]==P) {
            print "You have fallen into a bottomless pit";
            exit;
        }
    }
    if(z==ARROWTEST) {
        if(A==W) {
            print "You have slain the wumpus!";
            exit;
        } else {
            for(a in p) if(map[a]==W) break;
            W=map[meta(COMPOSE,a,v[int(rand()*3)+1])];
        }
    }
}

BEGIN {
    COMPOSE = 0;
    WALK = 1;
    TEST = 2;
    ARROWTEST = 3;
    L = 35214;
    R = 35421;
    B = 35142;
    split(R" "L" "B,V);
    meta(WALK,L);
    W = int(rand()*19)+2;
    P = int(rand()*19)+2;
    U = L;
    meta(TEST);
}

{
    d=int($0/10);
    m=$0%10;
    if(m==5) U = meta(COMPOSE,U,V[d]);
    else if(m==4) {
        A = map[meta(COMPOSE,U,V[d])];
        meta(ARROWTEST);
    }
    meta(TEST);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.