SphereCommunity
Swindler's Memory Game - Printable Version

+- SphereCommunity (https://forum.spherecommunity.net)
+-- Forum: Sphere 0.56d (/Forum-Sphere-0-56d)
+--- Forum: Script Submissions (/Forum-Script-Submissions)
+--- Thread: Swindler's Memory Game (/Thread-Swindler-s-Memory-Game)



Swindler's Memory Game - Mordaunt - 10-07-2013 02:52 AM

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]



RE: Swindler's Memory Game - Rattlehead - 10-07-2013 06:12 AM

wow, this goes wayyyy back


RE: Swindler's Memory Game - Mordaunt - 10-07-2013 06:23 AM

yeah it does... Swindler used to have some nice scripts out.