首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >捕猎乌姆帕斯

捕猎乌姆帕斯
EN

Code Golf用户
提问于 2014-04-21 17:47:45
回答 2查看 6.7K关注 0票数 40

当我还是个孩子的时候,孩子们会在电脑商店里闲逛,在我们被工作人员赶出去之前,他们会玩“捕猎乌姆普斯”。这是一个简单的游戏,在20世纪70年代中期的家用电脑上可编程,机器非常简陋,所以我认为它们中的一些可能有真正的小鸡。

让我们通过在现代硬件上复制游戏来唤起过去的时代。

  1. 玩家从一个二十面体地图上的随机房间开始(因此总共有20个房间,像一个二十面体的面一样相互连接,每个房间都有三个出口)。
  2. 巨蟒从一个随机选择的不同的房间开始。乌姆普斯臭气熏天,它的气味可以在它的位置附近的三个房间中的任何一个被检测到,尽管气味的方向无法被玩家确定。游戏中只报道“你闻到了一股乌姆普斯味”。
  3. 玩家携带着一个弓箭和无数的箭,他可以随时射入他面前的房间。如果wumpus在那间屋子里,它就死了,玩家就赢了。如果wumpus不在那间屋子里,它就会被吓到,并随机进入与其当前位置相连的三个房间中的任何一个。
  4. 一个,随机选择的房间(保证不会是玩家开始的房间)包含一个无底洞。如果玩家在靠近坑的任何一个房间,他会感觉到一阵微风,但不知道是从哪扇门吹来的。如果他带着坑走进房间,他就死定了,乌姆帕斯赢了。巨蟒不受坑的影响。
  5. 如果玩家走进wumpus的房间,或者wumpus走进玩家的房间,wumpus就赢了。
  6. 玩家用一个数字指定他面对的方向(1 =右,2=左,3=后),然后是动作(4 =射箭,5=沿着指定的方向行走)。
  7. 为了得分,每场比赛(“你感觉到微风”、“你闻到一股乌姆普斯的味道”、“你的箭没有击中任何东西”等)。可以被认为是一个字节。不要滥用这个来隐藏文本中的游戏代码;这只是为了与玩家交互。
  8. 减去10%的字节数来实现百万字节,这些字节数从与播放器不同的随机空间开始(尽管它们可以与wumpus和/或坑共享一个房间)。如果玩家和蝙蝠一起走进房间,蝙蝠就会把玩家带到另一个随机选择的房间(保证不会是有坑的房间或里面的wumpus ),然后飞到他们自己的新的随机地点。在与蝙蝠相邻的三个房间里,人们可以听到它们的吱吱声,但没有给玩家任何关于声音来自哪个房间的信息。
  9. 将35%的字节计数用于实现图形界面,该图形界面显示二十面体地图,以及玩家到目前为止相对于玩家所拥有的有关坑的位置、wumpus和蝙蝠(如果适用的话)的某种信息。显然,如果wumpus移动或球员被蝙蝠移动,地图需要相应地重置。
  10. 经调整后的最低字节计数获胜。

游戏版本的基本源代码(不一定符合上述规则,在任何情况下,完全不打高尔夫球)可以在本网站和其他地方找到。

EN

回答 2

Code Golf用户

发布于 2014-04-22 17:05:08

GolfScript,269个字符

代码语言:javascript
运行
复制
{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。如果希望调试输出,指示房间号,请在第一次出现^之后添加以下行:

代码语言:javascript
运行
复制
'  YOU 'F'->'>+++puts'  DIRECTIONS [BRL] '^`+puts'  PIT 'P+puts'  WUMPUS 'W+puts 

一个示例会话(具有额外的调试输出):

代码语言:javascript
运行
复制
  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
票数 9
EN

Code Golf用户

发布于 2018-02-13 09:57:21

乌姆普斯,384-129(字符串)=255个字节

代码语言:javascript
运行
复制
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),我可能会节省一吨字节。

解释

首先,免责声明:尽管语言的名称,它的设计并不是为了使实现亨特的Wumpus特别容易。相反,我首先设计了以三角形为主题的语言,最后形成了一个二十面体的数据结构,并因此决定将其命名为Wumpus。

所以是的,虽然Wumpus主要是基于堆栈的,但它也有20个寄存器,它们围绕着一个二十面体的表面排列。这意味着,我们得到一个免费表示地图的数据结构。我们唯一不能轻易做的事情就是在二十面体上找到特定的面孔,所以为了搜索它们,我们需要“滚动d20”,直到我们找到我们正在寻找的脸。(这是有可能的,但这需要更多的字节。)搜索这样的面孔会终止几乎可以肯定 (即概率1),因此永远运行搜索在实践中并不是一个问题。

上面的代码是这个第一个实现的黄金版本,它有一个更清晰的布局:

代码语言:javascript
运行
复制
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.

由于高尔夫运动主要涉及压缩布局,所以我现在只解释这个版本(直到我添加了任何超出代码重组范围的高尔夫技巧)。

让我们从安装代码开始:

代码语言:javascript
运行
复制
1SDL2vSD70L?.;;2.

最初,所有面都设置为0。我们将通过设置对应面的1位来编码wumpus,并通过设置2位设置凹坑。这样,他们就可以在同一个房间里了。玩家的位置将不会被记录在二十面体上,相反,它将永远是活跃的面(每次20个寄存器中只有一个是活动的)。

代码语言:javascript
运行
复制
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.

现在我们需要找一个随机的空脸把玩家放进去。

代码语言:javascript
运行
复制
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.

下一节将检查玩家的周围环境并打印适当的警告:

代码语言:javascript
运行
复制
3AL1a! ?,".supmuw a llems uoY"#19&oN03.
        L2a!?,".ezeerb a leef uoY"#18&oN04.
             AW(=12[?.;;7.

这是一个循环,我们运行了3次。每次,我们看到正确的邻居,打印适当的字符串(S),如果有危险,然后旋转二十面体120°。

代码语言:javascript
运行
复制
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.

下一节从播放机读取两个数字,然后移动播放机或射箭。前者微不足道,后者则不那么重要。射箭的主要问题是射偏的情况。在这种情况下,我们( a)需要去寻找wumpus来移动它,然后b)返回玩家的房间和二十面体的正确方向(这样“后退”仍然是“后退”)。这是整个项目中最昂贵的部分。

代码语言:javascript
运行
复制
    }&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

代码语言:javascript
运行
复制
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.

唉,这是最难的部分。现在,我们只需要检查播放机是否死了,否则从主循环开始:

代码语言:javascript
运行
复制
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)处)。

票数 6
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/26128

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档