Mordaunt
Super Moderator
Posts: 1,237
Likes Given: 26
Likes Received: 55 in 43 posts
Joined: Mar 2012
Reputation: 35
|
Swindler's Memory Game
Found this while digging around my old server script pack.
Unaltered, seems to work fine still:
Code:
//[PLEVEL 1]
//memory
[FUNCTION memory]
// never give your players access strictly to the "memoryGame" function! That could be VERY bad, allowing them to call functions by passing them as arguments (as in: [PLEVEL 1] memoryGame)
memoryGame memoryGame_playerWon, memoryGame_playerLost
//memoryGame 50,memoryGame_playerWon, memoryGame_playerLost
//memoryGame 99
// these functions are called ON THE GAME ITEM, so CONT is the player
// if you RETURN 1, the item will NOT be automatically deleted nor will the dialog be closed (both would otherwise occur after the function finishes) Maybe you can come up with some kind of purpose for this... or tweak things to your liking
// the function calls also make it easy for one of these to be assosciated with a physical game board, or a quest, etc.
[FUNCTION memoryGame_playerWon]
CONT.SYSMESSAGE @1153 You've won!
[FUNCTION memoryGame_playerLost]
CONT.SYSMESSAGE @1153 You've lost.
[COMMENT memoryGame]
Author: Swindler (Chris Galpin)
A find and replace of these would render this script more readable,
but would also take up more memory. *shrugs*
I should probably just let it take more memory... but I haven't.
I guess I can deal with ambiguous property names at the moment.
MOREX: TAG.matches
MOREY: TAG.movesLeft
MOREZ: TAG.firstFlipped
MOREM: TAG.secondFlipped
Also, a good way to tweak the set of cards to your own liking is to comment out the if statement
that shows either the button or the gumppic to show just the gumppic, that way they're all face up
and you can see how various sets look, to minimize (or increase) player confusability to your own liking
since a lot of spell icons are really similar
[DEFNAME memoryGame]
memoryGame_backSide 01b91 // the gump id of the back of the cards
memoryGame_iconStart 01b7f // there are 24 different cards, starting at this gump id
memoryGame_backSideSubstitute 01b7f // if one of those 24 cards would be the same as backSide, use this instead for that card
memoryGame_maxFails 50 // how many fails the player is allowed before they lose
[ITEMDEF i_memoryGame]
ID=i_memory
TYPE=t_eq_script
NAME=Memory Game
ON=@Create
DISPID i_game_board // this is really nice for people doing a .edit or .xedit, use it in your own scripts!
ON=@Timer
IF <MOREX> == 24 // won
IF !<ISEMPTY <TAG.onWinFunction>>
IF <<TAG.onWinFunction>> != 1 // it's necessary to repeat code here because combining this with the line above can result in a "Can't resolve <>" error because Sphere doesn't short-circuit operators
TRYSRC <CONT.UID> DIALOGCLOSE d_memoryGame -1
REMOVE // I could remove the -1 above, and this REMOVE here, and it be handled on the ON 0 below, but I think the "call a button when closing via script" may be gone in newer versions of Sphere
ENDIF
ELSE
TRYSRC <CONT.UID> DIALOGCLOSE d_memoryGame -1
REMOVE
ENDIF
RETURN 1
ENDIF
// this down here is for a mismatch
MOREY -= 1 // decrement moves left
IF !<MOREY> // lost
IF !<ISEMPTY <TAG.onLoseFunction>>
IF <<TAG.onLoseFunction>> != 1
TRYSRC <CONT.UID> DIALOGCLOSE d_memoryGame -1
REMOVE
RETURN 1
ENDIF
ELSE
TRYSRC <CONT.UID> DIALOGCLOSE d_memoryGame -1 // this is as above
REMOVE
RETURN 1
ENDIF
ENDIF
TRY TAG.card<MOREM> <TAG.card<MOREM>> & ~020 // unflip &= might be implemented in some version...
TRY TAG.card<MOREZ> <TAG.card<MOREZ>> & ~020 // unflip
MOREZ // set no card flipped (first card.. don't need to unset second card morem)
TRYSRC <CONT.UID> DIALOG d_memoryGame
RETURN 1
[FUNCTION memoryGame]
NEW <FINDID.i_memoryGame>
IF <NEW.UID>
NEW.DIALOG d_memoryGame // lookie! It resumes right where it left off! (if there's a client crash) if the user closes it, the item is removed to help memory consumption (haha PUN!)
RETURN 0
ENDIF
NEWITEM i_memoryGame
IF <ISNUM <ARGV[0]>>
NEW.MOREY <ARGV[0]>
NEW.TAG.onWinFunction <ARGV[1]>
NEW.TAG.onLoseFunction <ARGV[2]>
ELSE
NEW.MOREY <DEF.memoryGame_maxFails>
NEW.TAG.onWinFunction <ARGV[0]>
NEW.TAG.onLoseFunction <ARGV[1]>
ENDIF
// this whole code section that randomizes the list using a container (linked list)
// is going to be replaced/updated as soon as I come up with something better... feel free to give me suggestions
OBJ <NEW.UID>
NEWITEM i_bag
OBJ.LINK <NEW.UID>
FOR 24
IF <LOCAL._FOR> == memoryGame_backSide - memoryGame_iconStart // evaluation order is right to left remember, so this is valid :P (death to paranthesis! :P) This actually helps remind me of when paranthesis *are* required and I wouldn't expect them to be (like the fact that 3 * 2 + 4 = 18 in Sphere, 10 elsewhere)
LOCAL._FOR memoryGame_backSideSubstitute - memoryGame_iconStart
ENDIF
NEWITEM i_deed // non stackable... this is a lame method, find something better :p
NEW.MOREZ <LOCAL._FOR>
NEW.CONT <OBJ.LINK>
NEWITEM i_deed
NEW.MOREZ <LOCAL._FOR>
NEW.CONT <OBJ.LINK>
ENDFOR
WHILE <OBJ.LINK.RESCOUNT> // here we randomly remove an item from the container, until they're all gone...
NEW <OBJ.LINK.FINDCONT.<EVAL {0 (<OBJ.LINK.RESCOUNT> - 1)}>.UID>
TRY OBJ.TAG.card<OBJ.LINK.RESCOUNT> <NEW.MOREZ>
NEW.REMOVE
ENDWHILE
OBJ.LINK.REMOVE
OBJ.LINK // wouldn't want "bad link" console errors :)
OBJ.CONT <UID>
OBJ.DIALOG d_memoryGame
[DIALOG d_memoryGame]
70,40
SRC.DIALOGCLOSE d_memoryGame -1 // sounds like in versions set not to fire a button press (0 default) when closing via script command this -1 isn't needed
resizepic 0 0 3600 659 520
dtext 160 15 481 6 * 8 Memory! <MOREX> Matches <MOREY> Moves Left
dorigin -65 35
FOR 6 // rows
LOCAL.row <LOCAL._FOR>
FOR 8 // columns
LOCAL.index ((<LOCAL.row> - 1) * 8) + <LOCAL._FOR>
IF <TAG.card<EVAL <LOCAL.index>>> & 020 // if the card is flipped
gumppic *80 +0 ((<TAG.card<EVAL <LOCAL.index>>> & ~020) + <DEF.memoryGame_iconStart>)
ELSE
button *80 +0 <DEF.memoryGame_backSide> <DEF.memoryGame_backSide> 1 0 <LOCAL.index>
ENDIF
ENDFOR
dorigin -65 *80
ENDFOR
[DIALOG d_memoryGame BUTTON]
ON 0
REMOVE // this is *NICE*... the item need not stick around when the player purposefully closes the dialog, so there won't be tons of permanent tags on players!
ON 1 48
IF <TIMER> > -1
DIALOG d_memoryGame
RETURN 0
ENDIF
TRY TAG.card<ARGN1> <TAG.card<ARGN1>> | 020 // flip the card
IF !<MOREZ> // no card flipped
MOREZ <ARGN1> // set first card flipped
ELIF <TAG.card<MOREZ>> == <TAG.card<ARGN1>> // match
MOREZ
MOREX += 1 // increment matches
IF <MOREX> == 24 // won
TIMER 1
ELSE
SRC.SYSMESSAGE @1153 Match!
ENDIF
ELSE // failed
MOREM <ARGN1> // set the second card here so the timer can flip it back over... only use of reference to second card
TIMERD 5
ENDIF
DIALOG d_memoryGame
[eof]
|
|
10-07-2013 02:52 AM |
|
|