1. Who's up for a little game?
- Posted by ChrisB (moderator) Jan 13, 2011
- 3254 views
- Last edited Jan 23, 2011
It might or might not fall flat on its face.
Here is the start of 'Hunt the Wumpus' based on http://www.atariarchives.org/morebasicgames/showpage.php?page=179
--Hunt the Wumpus --the classic 70's game --converted from the BASIC atari archives include std/console.e include std/text.e include std/regex.e as re include std/get.e --trying to stick closer to the spirit of the BASIC Wumpus! constant YOU = 1, WUMPUS = 2, PITS1 = 3, PITS2 = 4, BATS1 = 5, BATS2 = 6, ARROWS = 7 --------------------------------------------------------------------------------------------- procedure instructions() --------------------------------------------------------------------------------------------- clear_screen() puts(1, "Welcome to Hunt the Wumpus\n") puts(1, "The wumpus lives in a cave of 20 rooms. Each room has 3 tunnels\n") puts(1, "leading to other rooms. (Look at a dodecahedron to see how this\n") puts(1, "works - if you don't know what a dodecahedron is, ask someone).\n") puts(1, "\n") puts(1, "Hazards\n") puts(1, "Bottomless pits - 2 rooms have bottomless pits in them. If you\n") puts(1, " there you fall in (and lose). \n") puts(1, "Superbats - 2 other rooms have superbats. If you go there, a \n") puts(1, " superbat grabs you and takes you to some other random room \n") puts(1, " (which could be..... troublesome!\n") puts(1, "\n") puts(1, "The wumpus is not bothered by such hazards (he has sucker feet,\n") puts(1, "and is too big to lift). Usually he is asleep. Two things wake him\n") puts(1, "up : your entering his room, and your shooting an arrow.\n") puts(1, "If the wumpus wakes up, he moves one room (P=0.75) or stays\n") puts(1, "put (P=0.25). After that, if he is in the same room as you\n") puts(1, "he eats you up (and you lose), or he goes back to sleep!\n") puts(1, "\n") any_key("Press any key..........") puts(1, "Each turn, you may move, or shoot a crooked arrow.\n") puts(1, " Moving - you can move one room (through a tunnel)\n") puts(1, " Shooting - you have 5 arrows - you lose when you run out.\n") puts(1, " Each arrow can go through 1 to 5 rooms, you aim by telling\n") puts(1, " the computer the rooms you want it to go through. If the arrow\n") puts(1, " can't go that way (no tunnel, it moves at random to an adjacent \n") puts(1, " room. If the arrow hits the wumpus, you win, if it hits you,\n") puts(1, " you lose.\n") puts(1, "\n") puts(1, "When you are 1 room away from a hazard, the computer will say\n") puts(1, " Wumpus - I smell a wumpus\n") puts(1, " Bats - Bats nearby\n") puts(1, " Pit - I feel a draft\n") puts(1, "\n") puts(1, "Good luck!\n") wait_key() end procedure --------------------------------------------------------------------------------------------- function initialise_caves() --------------------------------------------------------------------------------------------- -- Remember to swap row and column from the BASIC source in future references. return {{2,5,8}, {1, 3, 10}, {2, 4, 12}, {3, 5, 14}, {1, 4, 6}, {5, 7, 15}, {6, 8, 17}, {1, 7, 9}, {8, 10, 18}, {2, 9, 11}, {10, 12, 19}, {3, 11, 13}, {12, 14, 20}, {4, 13, 15}, {6, 14, 16}, {15, 17, 20}, {7, 16, 18}, {18, 9, 17}, {19, 11, 18}, {20, 13, 16, 19}} end function --------------------------------------------------------------------------------------------- function ask(sequence prompt, sequence filter) --------------------------------------------------------------------------------------------- /* print prompt and wait for an answer filter is a regular expression to filter answer */ re:regex valid_answer=re:new(filter,CASELESS) sequence answer puts(1,prompt) while 1 do answer=gets(0) answer=answer[1..$-1] if sequence(re:find(valid_answer,answer)) then exit else puts(1,"\ninvalid answer, try again\n"&prompt) end if end while return answer end function --------------------------------------------------------------------------------------------- function mkStatusList() --------------------------------------------------------------------------------------------- sequence status = {0,0,0,0,0,0,5} --setting [7] to arrow count sequence list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} integer r for i = 1 to 6 do r = rand(20) -- select a number between i and 20 inclusive status[i] = list[r] -- copy the value to status list[r] = list[i] -- removing list[r] from the list end for return status end function --------------------------------------------------------------------------------------------- procedure show_where_you_are(sequence status, sequence caves) --------------------------------------------------------------------------------------------- printf(1, "You are in room %d\n", {status[YOU]}) printf(1, "There are tunnels leading to rooms ", {}) for i = 1 to length(caves[status[YOU]]) do printf(1, "%d ", {caves[status[YOU]][i]}) end for puts(1, "\n") end procedure --------------------------------------------------------------------------------------------- procedure detect_hazards(sequence status, sequence caves) --------------------------------------------------------------------------------------------- sequence hzd = {} if find(status[BATS1],caves[status[YOU]]) or find(status[BATS2],caves[status[YOU]]) then hzd = append(hzd, "Bats nearby!") end if if find(status[PITS1],caves[status[YOU]]) or find(status[PITS2],caves[status[YOU]]) then hzd = append(hzd, "I feel a draft!") end if if find(status[WUMPUS],caves[status[YOU]]) then hzd = append(hzd, "I smell a wumpus!") end if if length(hzd) = 0 then return end if for i = 1 to length(hzd) do puts(1, hzd[i] & "\n") end for end procedure --------------------------------------------------------------------------------------------- function move_hunter(sequence status, sequence caves) --------------------------------------------------------------------------------------------- object dest_room sequence s s = prompt_string("\nMove to which room? ") dest_room = value(s) dest_room = dest_room[2] if find(dest_room, caves[status[YOU]] ) = 0 then puts(1, "You cannot get to that room from here!\n\n") return status end if puts(1, "\n") status[YOU] = dest_room return status end function --------------------------------------------------------------------------------------------- function detect_entered_hazards(sequence status, sequence caves) --------------------------------------------------------------------------------------------- --bats if status[YOU] = status[PITS1] or status[YOU] = status[PITS2] then puts(1, "AAAAARRGGHHHHH! Fell in a pit!\n") status[YOU] = -1 return status end if if status[YOU] = status[BATS1] or status[YOU] = status[BATS2] then puts(1, "Bats grabbed you - off to another room!\n") while 1 do status[YOU] = rand(20) --don't want the hunter in a room with the wumpus, bats or pits! if status[YOU] = status[BATS1] or status[YOU] = status[BATS1] or status[YOU] = status[PITS1] or status[YOU] = status[PITS1] or status[YOU] = status[WUMPUS] then continue else exit end if end while return status end if if status[YOU] = status[WUMPUS] then puts(1, "Munch munch, gobble gobble. Wumpus ate you!\n") status[YOU] = -1 end if return status end function --------------------------------------------------------------------------------------------- function shoot_arrow(sequence status, sequence caves) --fires an arrow through a number of rooms --if you miss the wumpus, it wakes up, and moves to another room --if you hit it, the wumpus is dead. --------------------------------------------------------------------------------------------- object nr, ar, current_arrow_room integer nwr status[ARROWS] -= 1 current_arrow_room = status[YOU] puts(1, "\n") while 1 do nr = prompt_string("No. of rooms : ") nr = value(nr) nr = nr[2] if nr >= 1 and nr <= 5 then exit end if puts(1, "Between 1 and 5 rooms please.\n") end while for i = 1 to nr do while 1 do --? caves[current_arrow_room] --uncomment this for an easier game ar = prompt_string("Which room : ") ar = value(ar) ar = ar[2] if find(ar, caves[current_arrow_room]) = 0 then puts(1, "Arrows aren't that crooked - try another room!\n") continue end if exit end while current_arrow_room = ar --check for pesence of wumpus if current_arrow_room = status[WUMPUS] then status[WUMPUS] = -1 return status end if --check if you've shot back into your room if current_arrow_room = status[YOU] then puts(1, "Ouch, you shot yourself - luckily in the head, no damage!") exit end if end for --didn't get the Wumpus then, but woke it up nwr = rand(3) status[WUMPUS] = caves[status[WUMPUS]][nwr] if status[WUMPUS] = status[YOU] then puts(1, "Munch munch, gobble gobble. Wumpus ate you!\n") status[YOU] = -1 return status end if if status[ARROWS] = 0 then status[YOU] = -1 puts(1, "You ran out of arrows!\n") end if return status end function --------------------------------------------------------------------------------------------- procedure start_game(sequence status, sequence caves) --------------------------------------------------------------------------------------------- sequence response while 1 do show_where_you_are(status, caves) detect_hazards(status, caves) response = ask("Move or shoot (m/s)", "[ms]") if response[1] = 'm' then status = move_hunter(status, caves) status = detect_entered_hazards(status, caves) else status = shoot_arrow(status, caves) end if if status[YOU] = -1 then puts(1, "You're dead!\n") return end if if status[WUMPUS] = -1 then puts(1, "You heartless fiend - you killed a defenceless Wumpus!\n") return end if end while end procedure --------------------------------------------------------------------------------------------- procedure main() --------------------------------------------------------------------------------------------- sequence inp sequence caves sequence status inp = upper(prompt_string("Do you want instructions? (y/n)")) if inp[1] = 'Y' then instructions() end if while 1 do caves = initialise_caves() status = mkStatusList() start_game(status, caves) inp = upper(ask("Play again?", "[yn]")) if inp[1] = 'N' then exit end if end while end procedure main()
Players are allowed to write one function/prcedure, or modify one function/procedure. You are not allowed to employ global variables. Players can only add/modify one function/procedure each round (ie they must wait until the next round before adding/modifying a procedure/function). A round is deemed complete, and restarted, If I add/modify a procedure or function.
Since one obvious 'get out' would be to write the entire program in one function, this is not permitted. A procedure / function must be used wherever appropriate, and ANY OTHER PLAYER may cry foul if they consider that a function/procedure could have been used - I will then delete that post. For instance, I could have initialised the caves in main(), but have passed that off to a function (yes, it could get ridiculous, I will decide!)
There is no winner, it is purely for fun, as a minor diversion. I hope to encourage the newcomers to euphoria / programming with this, though it is open to all. Remember modifications can be made to show how something could be done differently / better, more efficiently.
I have left a function unwritten - as a lead in. Post your entries here, as a new post, the entire program.
Have fun
2. Re: Who's up for a little game?
- Posted by jaygade Jan 13, 2011
- 3105 views
What do you mean by "global variables" here?
Do you expect include files to be written, or do top-level variables not count as "global" since you've already used them yourself as static variables?
Yes, this brings back memories.
3. Re: Who's up for a little game?
- Posted by jaygade Jan 14, 2011
- 2993 views
function initialise_caves() -- Remember to swap row and column from the BASIC source in future references. return {{2,5,8}, {1, 3, 10}, {2, 4, 12}, {3, 5, 14}, {1, 4, 6}, {5, 7, 15}, {6, 8, 17}, {1, 7, 9}, {8, 10, 18}, {2, 9, 11}, {10, 12, 19}, {3, 11, 13}, {12, 14, 20}, {4, 13, 15}, {6, 14, 16}, {15, 17, 20}, {7, 16, 18}, {18, 9, 17}, {19, 11, 18}, {20, 13, 16, 19}} end function
4. Re: Who's up for a little game?
- Posted by jaygade Jan 14, 2011
- 3010 views
BTW, I remember checking these books out from the library back in the day. They were the bomb!
Edit: Oh, and I also actually remember Creative Computing magazine.
5. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 14, 2011
- 2983 views
What do you mean by "global variables" here?
Do you expect include files to be written, or do top-level variables not count as "global" since you've already used them yourself as static variables?
Yes, this brings back memories.
Uuummmm - only std includes, and no top level, within the above, program variables, ie, all declared variables, must reside within the functions / procedures, and must be explicitly passed between functions / procedures.
Jaygades function added.
6. Re: Who's up for a little game?
- Posted by bill Jan 14, 2011
- 2976 views
In other words, the hunter's state, the Wumpus's state etc., reside in variables like caves.
Perhaps they should be seperate files, after all there should be no global state.
This is a small change but more 'objecty'.
This is rather a push, but it would do a lot for me as far as these games go.
I really find it annoying that the story is lost in the code.
I want to review what has happened (or more innocently) I want to re-confirm what the instructions were.
I, the camera-man, has just been done the dirty by my dog. I mean, he wagged his tail. I fed him ny food, he killed slime moulds etc. for me: I rescued him when he was in danger.
And then I lost him,
I don't know, it happens every time! It could be ki-ki my kitten, comes back Ki-Ki who doesn't know me and is wild.
I'm only a cameraman(or wizard or knight) who wants to know better. If I start over the samr thing happens. I am disappointed.
Can you help?
7. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 14, 2011
- 2967 views
Hi
This is part of the problem - read the BASIC code, and get an idea of what to do, then implement a way of doing it
Chris
8. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 16, 2011
- 2945 views
Hi
I've added some constants (global, not variable), and initialised the 'things' in the game.
Now play can start!
Chris
9. Re: Who's up for a little game?
- Posted by coconut Jan 16, 2011
- 2909 views
This program certainly need a function like that
include std/regex.e as re function ask(sequence prompt, sequence filter) /* print prompt and wait for an answer filter is a regular expression to filter answer */ re:regex valid_answer=re:new(filter,CASELESS) sequence answer puts(1,prompt) while 1 do answer=gets(0) answer=answer[1..$-1] if sequence(re:find(valid_answer,answer)) then exit else puts(1,"\ninvalid answer, try again\n"&prompt) end if end while return answer end function
10. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 17, 2011
- 2810 views
This program certainly need a function like that
include std/regex.e as re function ask(sequence prompt, sequence filter) /* print prompt and wait for an answer filter is a regular expression to filter answer */ re:regex valid_answer=re:new(filter,CASELESS) sequence answer puts(1,prompt) while 1 do answer=gets(0) answer=answer[1..$-1] if sequence(re:find(valid_answer,answer)) then exit else puts(1,"\ninvalid answer, try again\n"&prompt) end if end while return answer end function
Hi
To do what?
Chris
11. Re: Who's up for a little game?
- Posted by bill Jan 17, 2011
- 2811 views
Re
hunter = {rand(20), 5} --{current_room, arrows} wumpus = {rand(20), 0} --{current_room, asleep or awake} pits = {rand(20), rand(20)} bats = {rand(20), rand(20)} --check hunter doesn't start in room with a wumpus, pits or bats while 1 label "crossover" do if hunter[ROOM] = wumpus[ROOM] then wumpus[ROOM] = rand(20) continue end if for i = 1 to 2 do if hunter[ROOM] = pits[i] then pits[i] = rand(20) continue end if if hunter[ROOM] = bats[i] then bats[i] = rand(20) continue end if if wumpus[ROOM] = bats[i] then bats[i] = rand(20) continue end if if wumpus[ROOM] = pits[i] then pits[i] = rand(20) continue end if for j = 1 to 2 do if bats[i] = pits[j] then pits[j] = rand(20) continue "crossover" end if end for end for exit end while
This is cleaner:
sequence status = {0,0,0,0,0,0} procedure mkStatusList() sequence list = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} integer r for i = 1 to 6 do r = rand_range(i,20) -- select a number between i and 20 inclusive status[i] = list[r] -- copy the value to status list[r] = list[i] -- removing list[r] from the list end for end procedure
Being object-like is not really in the spirit of the game
Using functions to get values is perhaps useful:
(and the original did use functions)
eg: function bat_nearby(integer room) return find(status[bat1],caves[room]) or find(status[bat2],caves[room]) end function or: procedure move_item(integer item, integer room) -- assert(find(item,{HUNTER,WUMPUS}),"fixed item") status[item] = room end procedure
Re arrows:
I think they could be a 7th status item making them consistent with the other items in the game.
Finally:
By my reading of the game..
The wumpus wakes if you fire an arrow or you enter his room. He then moves or doesn't move and eats you if you are in the room.
There is no test to see if he is awake or not so the only inference I can make is he then goes back to sleep. Therefore, the asleep or awake status flag is not needed.
A riskless winning strategy is easy to find if you know the set-up of the rooms. Allowing him to stay awake makes it harder only if you mess up the first time. After that you would only find him safely if he moved to a square next to you (3 in 19).
There is a good riskless strategy to follow even then.
It might be useful to change the rules slightly.
eg:
Give the rooms display numbers which are not the same as the play room numbers. This way a person cannot know the arrangement of rooms to fire arrows until he has been to adjacent rooms.
Allow the a probability of missing with an arrow. This should increase with distance.
One suggestion from the Wumpus2 page was to allow one-way tunnels.
Bill
12. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 17, 2011
- 2756 views
Suggestions adopted
The wumpus goes back to sleep after a move.
More in keeping with the BASIC, using status to indicate statuses of various 'things'.
Yes that randomisation solution is cleaner.
Arrows in status sequence.
Will put in the thing collision check later (hunter in bats room etc).
It may be useful to change the rules slightly, but not yet. I want to see where the recreation goes first. Interesting the cave initialisation function would be easily modified to change the room connection list - all that's needed would be a different list to say which rooms are connected to which. Also the map could be modified at run time, so that while all the tunnels connect in the same way, the room numbers are changed, so that games become dissimilar every time you play.
Chris
13. Re: Who's up for a little game?
- Posted by bill Jan 17, 2011
- 2776 views
Yes,
I agree about not changing the rules yet.
I have a couple of other suggestions for rule changes which could make a better game:
These are:
Allow the wumpus to hide in a pit. This is good strategy for him especially if we consider he can't be detected there because the draft is into the pit.
Another is to allow a setup like the bats and the pits around him. Then the game needs careful consideration because the wumpus's position can only be found by inference.
Some bugs (features) I've found:
1 The player cannot stand still, if the wumpus is moving about standing still is the only really safe policy - but it isn't allowed.
2 The restart same game feature fails to replace the wumpus if he has moved (and, probably if it is a restart the the wumpus has moved).
14. Re: Who's up for a little game?
- Posted by bill Jan 17, 2011
- 2763 views
And:
You don't need a collision check. The selection is selection without replacement - just like drawing tickets out of a hat.
Bill
15. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 17, 2011
- 2759 views
And:
You don't need a collision check. The selection is selection without replacement - just like drawing tickets out of a hat.
Bill
Not in initialisation, in game-turn loop
Chris
16. Re: Who's up for a little game?
- Posted by coconut Jan 17, 2011
- 2685 views
This program certainly need a function like that
include std/regex.e as re function ask(sequence prompt, sequence filter) /* print prompt and wait for an answer filter is a regular expression to filter answer */ re:regex valid_answer=re:new(filter,CASELESS) sequence answer puts(1,prompt) while 1 do answer=gets(0) answer=answer[1..$-1] if sequence(re:find(valid_answer,answer)) then exit else puts(1,"\ninvalid answer, try again\n"&prompt) end if end while return answer end function
Hi
To do what?
Chris
to prompt the player player_choice=ask("move or shoot?(m-s) ","[ms]")
or any other player query...
17. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 18, 2011
- 2617 views
Hi
Ah, ok of course. Just goes to show, would have done it differently myself.
Added.
Also added a couple more idea functions.
Chris
18. Re: Who's up for a little game?
- Posted by coconut Jan 18, 2011
- 2585 views
Hi
Ah, ok of course. Just goes to show, would have done it differently myself.
Added.
Also added a couple more idea functions.
Chris
It should be
response = ask("Move or shoot? (m/s) ","[ms]") -- if only "ms" it will search for string "ms" not for 'm' or 's'.
Jacques
20. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 19, 2011
- 2486 views
The hunter can now move about, and detect hazards in adjacent caves, but is at the moment immune to the hazards.
21. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 21, 2011
- 2230 views
Hunter no longer immune to hazards
22. Re: Who's up for a little game?
- Posted by bill Jan 21, 2011
- 2221 views
I have a criticism to make:
Not about any particular procedure but abot the general approach of
to room : 12
Points: 1 we need different prompts for each thing a player can do: getting instructions (1) moving (2) shooting (2) new game (2) quit (1) 2 it is not possible to ask for help, or to start a new game, or quit (except
23. Re: Who's up for a little game?
- Posted by bill Jan 21, 2011
- 2200 views
I have a criticism to make, not about any particular procedure but abot the general approach of:
> move or shoot (m/s)? m > to room? 12Points:
1 we need different prompts for each thing a player can do:
getting instructions (1) moving (2) shooting (2) new game (2) quit (1)
2 it is not possible to ask for help, or to start a new game, or quit (except by quitting the interpreter) while you are in the game loop.
3 responses to actions are scattered through the code.
4 the game is leading the player - do this or this, do this here, etc,. The player should be controlling what happens.
I suggest a command language - like the CLI.
> move 10 -- moves to room 10 if possible, the status report each round -- indicates whether the move was successful) > move 21 -- an error (no room 21) -- response -- > ? (laconic but explaining the error is overkill) -- > (ask again) > move -- another errorAppropriate commands would be:
move <room> shoot <room-list> help <commands | instructions> new replay quitA command is a space delimited list. All commands and word parameters can be abbrevated (m, mo, mov are all equivalent to move).
I will write a procedure to do this if you think it is a good idea and in the spirit of the game.
24. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 21, 2011
- 2213 views
Hi Bill
I know exactly where you're coming from, but the spirit of this excercise is to reproduce the Wumpus game in the atari archives. What your suggesting is something called feature creep, ie adding features that weren't in the original spec. You are more than welcome to do this, the game is nearly finished (all that's needed is an arrow shooting / wumpus hitting / moving routine), and then it can go off in whatever direction you want (hidden treasure anyone).
Sometimes I find the hardest thing about writing is NOT to add stuff!
Chris
25. Re: Who's up for a little game?
- Posted by bill Jan 22, 2011
- 2182 views
All of the things in the input language are things which are in the current game just scattered around through the code. We should not be rehashing Atari Basic style in Eu.
Replacing bits of the program with functions and procedures, threading them together getting rid of the gotos and gosubs is not necessarily making the game clearer. The input is a mess because it is all over the place. The error messages are scattered around. One has to read every line to know what the program does.
The project should be produce a model in Euphoria style
It is no great matter, I will submit some code. Probably in a couple of days. This will be my first Eu program.
26. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 22, 2011
- 2129 views
Hey, no problem, glad you're taking an interest, and that it's sparked some thought.
Look forward to seeing it.
Chris
27. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 22, 2011
- 2058 views
And so, my friends, the story of the hapless Wumpus, and our fearless hunter has come to an end. I release upon the world the completed translation of the BASIC Wumpus game. It is yours, to do with, to play with, to tease and taunt, to ridicule and praise as you will. My child has flown and left the Wumperine nest. Just like all our children,it may not be perfect in others eyes, but I have nurtured it, watched it grow, and now watch it, with trepidation, spread its fragile wings on the cruel digital wind.
I look forward to the offspring that may spring from the conjoining of the fledgling idea, and the fertile minds of others.
Bon voyage my baby.
Now a decent Senet player.
Chris
28. Re: Who's up for a little game?
- Posted by bill Jan 23, 2011
- 1966 views
Chris:
Please note: the graph of tunnels is wrong! - note caves 19 and 20.
29. Re: Who's up for a little game?
- Posted by ChrisB (moderator) Jan 23, 2011
- 2011 views
Hi, yes, I know, room 20 has 4 tunnels. Correct it then - copy and paste it onto Pastey (look to your right), and let everyone else know!
or go to http://euphoria.pastey.net/145225-1e8j and update away!
Have fun.
Chris