dMZX Forums: SpellWeavre Relearns MegaZeux - dMZX Forums

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

SpellWeavre Relearns MegaZeux small projects eventually releasable as demos

#1 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 01 May 2010 - 03:32 PM

I got a bug in my head to do some MegaZeuxing the other day, and lo and behold I discover that digitalmzx.net is still up and running! A bit on the quiet side, but doing its thang. And the latest versions of MegaZeux run natively on Windows and have up-to-date documentation! Kudos to all the development crew!

I'd like to learn how to do some of the more interesting things possible in 21st century MegaZeux, and that will take practice. Lesson learned from the past: don't plan out more than you think you can handle. And my free time is at a premium in these working-adult days, so "think small" is the motto. The idea is to do a couple of little projects that will help me learn my way around Robotic again, be feasible to declare "finished" on a timeline measured in months rather than years, and which could still be usable for a larger game in the future if I feel so inclined.

The Brainstorm/Goal Planning Phase

Project 1: Design a system for shuffling a deck of cards and dealing them out.

Topics to learn: MZMs, maybe sprites and/or strings.

Demo target: Not sure yet. I think programming a whole card game would be too ambitious, but I could do something like a simple RPG battle engine that uses cards instead of invisible dice. Or a system where you can draw cards and put them on the table or in a discard pile, with hot-seat players so you could play whatever card game you want (if for some bizarre reason you wanted to play a card game using a retro-styled computer program!).

The problem at hand: Writing an algorithm for shuffling the cards.

Current ideas: Maybe I don't need to shuffle the deck, so much as pick randomly from the remaining cards every time I need a draw. The inefficient way (especially as the deck gets nearly depleted) would be to roll a random number, and if it comes up on an already-taken card, reroll. A little better would be to take a random number from 1 to the number of cards remaining, and grab the card at that position, but I'm not yet sure how best to update the state of the deck after each draw. Or that process itself could be the shuffle... with each "draw" now appending a character to a string representing the deck, and when we get to the point of actually pulling cards, we grab the next character of the string and load the corresponding card.



Project 2: Design a conversation-tree system, like those seen in BioWare's cRPGs.

Topics to learn: File access, strings.

Demo target: A single playable conversation with several different outcomes. I'm thinking you've got two characters, one whose conversational tack is chosen by the player, with independent agendas. That'd give you four endings: both characters get what they want, neither does, and the two combinations of one character succeeding but the other not.

The problem at hand: Design a file format for the conversation tree, usable with MZX's file reading system, that's easy to scribble in away from MZX but which holds as much information as possible about the conversation--I'd like to limit the hard-coded Robotic stuff to reading and interpreting the file.

Here's my first thought as to what the format might look like. The block below represents a chunk of dialogue, beginning with a "bookmark" IDing the part of the conversation, and ending with the set of responses the player can choose from.

bookmark
*character*dialogue (repeatable)
*#number of responses
*response text*action code (repeat until number of responses reached)
*

first character of action code is a check digit:
D = destination. Following data is bookmark ID
Q = end conversation. Following data is returned as outcome to calling robot
S = store a result without ending the conversation. Following data is returned to calling robot (also needs a destination bookmark)

So an example would look like this:

1
*Joe*Blablabla
*Mac*Ow! My eyelid!
*#3
*Are you hurt?*D2
*MRGRY*S1D3
*I've had enough of this.*Q2
*

That'd be followed by bookmark 2, and so on. The conversation robot reads this, spitting out a bit of dialogue between Joe and Mac, followed by three conversation choices for Joe to say. Choosing "Are you hurt?" takes you to bookmark 2. Choosing "MRGRY" sends "1" back to the robot reading the file, whatever that means, and goes to bookmark 3. "I've had enough of this." ends the conversation, sending "2" back to the robot reading the file.

Any glaring flaws with that? I'm using the * terminator character for baby-steps purposes, so I can use the most basic FREAD functions; it should be simple enough to swap it out for a better delimiter once I feel up to coding that logic.

This post has been edited by SpellWeavre: 01 May 2010 - 03:33 PM

0

#2 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 01 May 2010 - 05:08 PM

Hey, cool beans, good luck in getting back into this.

View PostSpellWeavre, on 01 May 2010 - 11:32 AM, said:

I got a bug in my head to do some MegaZeuxing the other day, and lo and behold I discover that digitalmzx.net is still up and running! A bit on the quiet side, but doing its thang. And the latest versions of MegaZeux run natively on Windows and have up-to-date documentation! Kudos to all the development crew!

I'd like to learn how to do some of the more interesting things possible in 21st century MegaZeux, and that will take practice. Lesson learned from the past: don't plan out more than you think you can handle. And my free time is at a premium in these working-adult days, so "think small" is the motto. The idea is to do a couple of little projects that will help me learn my way around Robotic again, be feasible to declare "finished" on a timeline measured in months rather than years, and which could still be usable for a larger game in the future if I feel so inclined.

Project 1: Design a system for shuffling a deck of cards and dealing them out.


Q.V. Entry 49305, "Xin", from the Winter 2008 DoZ for some ideas on implementing this (grab the whole competition archive here). Also a totally shameless plug. Actually my code for that card engine was super terrible, so if you can figure out even a bit of it then props to you, but at least the visual implementation may give you some ideas. Also, sprites isn't a maybe for this application, it's all but a requirement. Any time you're using MZMs for artwork, you're probably using them in conjunction with sprites. MZMs are how you store data, sprites are how you display it.

Quote

Project 2: Design a conversation-tree system, like those seen in BioWare's cRPGs.

...

Any glaring flaws with that? I'm using the * terminator character for baby-steps purposes, so I can use the most basic FREAD functions; it should be simple enough to swap it out for a better delimiter once I feel up to coding that logic.[/size][/font]


I've worked on these in the past. First ideas: get away from using the * based freads as soon as you comfortably can. I find it really limiting at least. Also, I recommend marking bookmarks with a special character so that they're easier to find, instead of just a line starting with a number. Using a colon (a la ":label2") is the most obvious choice, but as far as indexing bookmarks goes I do think you'll find searching the file for a newline followed by a unique command symbol easier than searching for a newline followed by a number of arbitrary length. The second option isn't THAT much harder if you know what you're doing, but as you said, baby-steps.

Let us know when you run into trouble, I love to help out with this kind of stuff.

"Hey, who turned out the lights?"
To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#3 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 01 May 2010 - 10:49 PM

View PostWervyn, on 01 May 2010 - 12:08 PM, said:

Q.V. Entry 49305, "Xin", from the Winter 2008 DoZ for some ideas on implementing this (grab the whole competition archive here).

Neat, will do! I knew it was something that had been attempted before (I remember the Sivion demo including a card game mockup...), good to see there's something I can poke at right away ^.^

Quote

Also, sprites isn't a maybe for this application, it's all but a requirement. Any time you're using MZMs for artwork, you're probably using them in conjunction with sprites. MZMs are how you store data, sprites are how you display it.

I hadn't thought of it that way since I don't care about collisions and whatnot with cards, but that makes sense. A classic case of making sprites out to be more complicated than they are/have to be. Noted!

Quote

First ideas: get away from using the * based freads as soon as you comfortably can. I find it really limiting at least.

::nods:: Yeah, I expect that would be an early upgrade once I feel I have a handle on the process as a whole.

Quote

Also, I recommend marking bookmarks with a special character so that they're easier to find, instead of just a line starting with a number.

Oh, duh. I put in special initial characters several other places, but not in that most obvious place. Hah!

Quote

Let us know when you run into trouble, I love to help out with this kind of stuff.

Cool, thanks for the advice!
0

#4 User is offline   mzxgiant 

  • DigitalMZX Server Ninja & Code Monkey
  • Group: DigiStaff
  • Posts: 1,127
  • Joined: 02-January 01
  • Gender:Male
  • Location:Rochester, NY

Posted 02 May 2010 - 01:05 AM

Slightly off-topic, if you're looking for more MZXers, check out IRC. irc.esper.net #mzx

It's marginally less quiet. :confused:
0

#5 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 02 May 2010 - 03:44 AM

View Postmzxgiant, on 01 May 2010 - 08:05 PM, said:

Slightly off-topic, if you're looking for more MZXers, check out IRC. irc.esper.net #mzx

Also noted!

I don't expect I'll get a lot of opportunities to visit (see aforementioned low quantity of free time), but I will keep it in mind!
0

#6 User is offline   Old-Sckool 

  • megazeux breaker
  • PipPipPipPip
  • Group: Members
  • Posts: 649
  • Joined: 07-June 05
  • Gender:Male

Posted 03 May 2010 - 12:30 AM

Quote

The problem at hand: Writing an algorithm for shuffling the cards.

Current ideas: Maybe I don't need to shuffle the deck, so much as pick randomly from the remaining cards every time I need a draw. The inefficient way (especially as the deck gets nearly depleted) would be to roll a random number, and if it comes up on an already-taken card, reroll. A little better would be to take a random number from 1 to the number of cards remaining, and grab the card at that position, but I'm not yet sure how best to update the state of the deck after each draw. Or that process itself could be the shuffle... with each "draw" now appending a character to a string representing the deck, and when we get to the point of actually pulling cards, we grab the next character of the string and load the corresponding card.


I'd say the best way to go about doing it would be to simply have an unsorted "array" that contains all of the cards in the deck, since in many card games the order the cards have been shuffled in doesn't affect game strategy. You'd then generate a random number from 0 to the cards remaining -1 to grab the card at that position, then swap the last card into the vacant position and decrease the deck count.
<Nadir> mzxers don't make GAMES, usually
<phthalocyanine> they make experiences.
<Nadir> demos, more like
<Nadir> a glimpse into what could have been if mzx wasn't such a bore to work with
<Nadir> actually, i'm being unfair
<Nadir> i would have made mzx games if it was capable of running on more than 20 computers worldwide in 1998
<Nadir> >:D

<%Alice> functor
<%nooodl> i hear C++ has a thing called functors and they're completely different from Haskell functors...
<rorirover> the result is the most horrid thing in C++, it's basically black magic and it transforms any code you're writing into some eldritch monstrosity
0

#7 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 03 May 2010 - 01:13 AM

View PostOld-Sckool, on 02 May 2010 - 07:30 PM, said:

I'd say the best way to go about doing it would be to simply have an unsorted "array" that contains all of the cards in the deck, since in many card games the order the cards have been shuffled in doesn't affect game strategy. You'd then generate a random number from 0 to the cards remaining -1 to grab the card at that position, then swap the last card into the vacant position and decrease the deck count.

Ooh?

Okay, let's see if I understand you correctly. If I have a deck of 9 cards, I start with a string that reads simply

123456789

To draw a card, I take a random number from 0 to 8, since there are 9 cards left. Suppose it comes up 6, meaning I take card "7"--that goes to the player's hand or whatever it is we're doing with it. Then we rearrange the string so that it looks like

12345698

...with a deck size of 8?

This sounds like a great plan, and I feel like the light bulb is about to come on for me, but--

First off, did I read you right about "swap the last card into the vacant position"? What's the advantage of that versus removing the taken card and leaving it at that (12345689)?

Secondly, I'm sure this will be immediately evident once I start trying to code this, but why 0 to n-1 instead of 1 to n?
0

#8 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 03 May 2010 - 01:49 AM

You read him right. The taken card leaves an empty space in the array that you have to do something with, otherwise your array looks like 0123456*89 after you take card 7 out of it. The next time your RNG rolls a 7, what do you do? So, instead of moving slot 8 into slot 7, and slot 9 into slot 8 to shorten up the list, you can just move slot 9 directly to slot 7 and save a bunch of time. This works because the order of the deck doesn't matter at all, the draw is random anyway.

About 0-indexed arrays, they're just BETTAR in general. Most programmers use them instead of 1-indexed arrays, so if you use them to you won't have any embarrassing integration errors because all your stuff is off by one. But seriously, it's conceptually cleaner to iterate over a list from i = 0 while i < n, for people who are used to C style languages. MZX, sets loopcount to 0 when you do a loop start, so it makes sense there as well (although MZX's terrible loop structure means you're always looping "for n - 1" in this case, not that using a 1-indexed array would fix that issue). It also generally makes more sense to think of negative indexes as indexed from the end of the list, in programming languages like Python. That is, list[-1] = list[n-1]. With a 1-indexed array, you'd have to start at 0 for the same effect, which is not nearly as clear.

"Better living through better programming."
To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#9 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,936
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 03 May 2010 - 02:02 AM

Quote

You read him right. The taken card leaves an empty space in the array that you have to do something with, otherwise your array looks like 0123456*89 after you take card 7 out of it. The next time your RNG rolls a 7, what do you do? So, instead of moving slot 8 into slot 7, and slot 9 into slot 8 to shorten up the list, you can just move slot 9 directly to slot 7 and save a bunch of time. This works because the order of the deck doesn't matter at all, the draw is random anyway.


well, spellweavre was talking about using a string, in which you could just use # + notation to do it in one command anyway
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
0

#10 User is offline   Old-Sckool 

  • megazeux breaker
  • PipPipPipPip
  • Group: Members
  • Posts: 649
  • Joined: 07-June 05
  • Gender:Male

Posted 03 May 2010 - 02:57 AM

Hrmm, i just realized that $str+ can be used to shift all of the elements over... If your using strings as makeshift arrays, I'd imagine that it wouldn't be significantly slower than just grabbing the last element and swapping it in (unless you had something like a million char string). I'm more use to creating arrays through nesting (ex. set "value('index')" 4), where just shifting a group of elements over would be incredibly expensive.

Here's how it would sorta look like in MZX.

. "--Initialize variables--"
. "The "deck array", as a string"
set "$str" to "0123456789"
. "The deck count. "
set "length" to "('$str.length')"

. "the draw routine"
set "rand" to random 0 to "('length'-1)"
write overlay c0f "&$str&" at 0 1
. "decreasing the length now means we don't have to offset to the last element later."
dec "length" by 1
. "the magic code"
set "$str+('rand')" to "$str+('rand'+1)"
write overlay c0f "&$str#('length')&   Random value: &rand&" at 0 3 

This post has been edited by Old-Sckool: 03 May 2010 - 02:58 AM

<Nadir> mzxers don't make GAMES, usually
<phthalocyanine> they make experiences.
<Nadir> demos, more like
<Nadir> a glimpse into what could have been if mzx wasn't such a bore to work with
<Nadir> actually, i'm being unfair
<Nadir> i would have made mzx games if it was capable of running on more than 20 computers worldwide in 1998
<Nadir> >:D

<%Alice> functor
<%nooodl> i hear C++ has a thing called functors and they're completely different from Haskell functors...
<rorirover> the result is the most horrid thing in C++, it's basically black magic and it transforms any code you're writing into some eldritch monstrosity
0

#11 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 03 May 2010 - 03:14 AM

View PostLancer-X, on 02 May 2010 - 09:02 PM, said:

well, spellweavre was talking about using a string, in which you could just use # + notation to do it in one command anyway

Oh! Yeah! Up until this point in the conversation, I'd been mentally substituting "string" for "array" whenever it was mentioned, because I didn't think MegaZeux had arrays.

An array in MZX would be... a series of numbered counters, which you access by doing some manner of interpolation hand-jive? "deckcard1" to "deckcard52" and when you draw a card you pick up "deckcard&draw&" (or whatever the proper syntax for that would be)?

That sounds harder to work with than strings, though I'm sure it's something I'll want to get the hang of eventually. I rather like the tidiness of having a compact little set of strings, one representing the deck, one representing the discard pile, one the player's hand, and so forth, moving bytes about between them. But maybe it wouldn't be so tidy in practice? ^.^;

EDIT: And there Old-Sckool pretty much said all that already. With example code to boot! I should refresh the page or otherwise pay more attention before replying...

This post has been edited by SpellWeavre: 03 May 2010 - 03:17 AM

0

#12 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 04 May 2010 - 01:20 AM

Hooray! I am so damn tickled. The following code appears to work:

. "Initialize the deck: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
end
: "keyd"
. "local = card position to be drawn from"
set "local" to random 0 to "(&$deck.length&-1)"
. "add the drawn card to the hand"
set "$hand+&$hand.length&" to "$deck+&local"
. "remove the drawn card from the deck"
set "$deck+&local&" to "$deck+('local'+1)#('$deck.length'-'local')"
set "$deck" to "$deck#('$deck.length'-1)"
. "display deck and hand"
write overlay c07 "Deck: &$deck& " at 1 1
write overlay c07 "Hand: &$hand&" at 1 2
end

When I press "d", a random letter from my double-alphabet vanishes from the "Deck" row and appears in the "Hand" row. Yay! Next up: probably cobbling together some MZMs and making it display things that look like cards (though I'm horrible at graphics, so they'll be pretty weaksauce cards, heh).

One question: are '' and && equivalent? I saw one notation in some examples and the other elsewhere. If they do work the same, is there a preferred convention for which to use?

(hrm, looks like the board parses away some of the character combinations in the code... well... it works anyway ;P)

This post has been edited by SpellWeavre: 04 May 2010 - 01:47 AM

0

#13 User is offline   Old-Sckool 

  • megazeux breaker
  • PipPipPipPip
  • Group: Members
  • Posts: 649
  • Joined: 07-June 05
  • Gender:Male

Posted 04 May 2010 - 02:59 AM

View PostSpellWeavre, on 03 May 2010 - 09:20 PM, said:

Hooray! I am so damn tickled. The following code appears to work:

. "Initialize the deck: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
end
: "keyd"
. "local = card position to be drawn from"
set "local" to random 0 to "(&$deck.length&-1)"
. "add the drawn card to the hand"
set "$hand+&$hand.length&" to "$deck+&local"
. "remove the drawn card from the deck"
set "$deck+&local&" to "$deck+('local'+1)#('$deck.length'-'local')"
set "$deck" to "$deck#('$deck.length'-1)"
. "display deck and hand"
write overlay c07 "Deck: &$deck& " at 1 1
write overlay c07 "Hand: &$hand&" at 1 2
end

...

(hrm, looks like the board parses away some of the character combinations in the code... well... it works anyway ;P)


Hrm, that's bizarre, did you mean to type
set "$hand+&$hand.length&" to "$deck+&local&#1" 

because when I copied your code in, the selected card and every card after it gets appended to the hand.

Also, you could always just append to the end of $hand with the inc command like so

inc "$hand" "$deck+('local')#1


Quote

One question: are '' and && equivalent? I saw one notation in some examples and the other elsewhere. If they do work the same, is there a preferred convention for which to use?


In many cases they're interchangeable. However, The only case I can think of where you can only use && is if you want to nest a string value into a variable name to reference a different variable, like so...
set "$string" to "A"
set "$Question&$string&" to "First Question"
. "$QuestionA equals "First Question"


I generally wrap '' around integer variables (because I feel it looks cleaner) and && around string variables or nested strings.
<Nadir> mzxers don't make GAMES, usually
<phthalocyanine> they make experiences.
<Nadir> demos, more like
<Nadir> a glimpse into what could have been if mzx wasn't such a bore to work with
<Nadir> actually, i'm being unfair
<Nadir> i would have made mzx games if it was capable of running on more than 20 computers worldwide in 1998
<Nadir> >:D

<%Alice> functor
<%nooodl> i hear C++ has a thing called functors and they're completely different from Haskell functors...
<rorirover> the result is the most horrid thing in C++, it's basically black magic and it transforms any code you're writing into some eldritch monstrosity
0

#14 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 04 May 2010 - 06:15 AM

View PostOld-Sckool, on 03 May 2010 - 10:59 PM, said:

Hrm, that's bizarre, did you mean to type
set "$hand+&$hand.length&" to "$deck+&local&#1" 

because when I copied your code in, the selected card and every card after it gets appended to the hand.


Yeah, that actually is what he typed, and then the board converted '&#1' into a unicode entity (). Doesn't happen inside code boxes.

Anyway, Old-Sckool basically covered anything I was going to explain here, and this is a good start. I'd do some things differently if I were writing it but they all amount to style changes. That and I still like O(1) array removal.

"Time to go dig out Cryptonomicon again..."
To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#15 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 04 May 2010 - 12:38 PM

Code box... oh! So that's how you do that. ^.^; The real thing's below.

. "Initialize the deck: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
end
: "keyd"
. "local = card position to be drawn from"
set "local" to random 0 to "(&$deck.length&-1)"
. "add the drawn card to the hand"
set "$hand+&$hand.length&" to "$deck+&local&#1"
. "remove the drawn card from the deck"
set "$deck+&local&" to "$deck+('local'+1)#('$deck.length'-'local')"
set "$deck" to "$deck#('$deck.length'-1)"
. "display deck and hand"
write overlay c07 "Deck: &$deck& " at 1 1
write overlay c07 "Hand: &$hand&" at 1 2
end

I hadn't noticed the "inc" usage before, thanks! So before I move on, this is my to-do:

1) handle the deck's running out of cards. Just a sanity quit, for now.
2) use "inc" instead of "set" for adding a card to the end
3) use OldSckool's "magic code" from a couple posts back, instead of the terribly awkward thing I came up with, to remove a card
4) clean up my random usage of '' vs. &&

I will end up having to do an array-like setup (was my earlier natter about counters what you mean by that?) to define what the cards actually are--"cardAvalue", "cardAsuit", that sort of thing. I just find this string-manipulation hokey-pokey too fun ;P

This post has been edited by SpellWeavre: 04 May 2010 - 12:39 PM

0

#16 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 04 May 2010 - 01:05 PM

Okay, the above is done.

. "Initialize the deck: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
end
: "keyd"
. "make sure we still have a card to draw"
if "$deck.length" < 1 then "deckedout"
. "local = card position to be drawn from"
set "local" to random 0 to "('$deck.length'-1)"
. "add the drawn card to the hand"
inc "$hand" by "$deck+('local')#1"
. "remove the drawn card from the deck"
set "$deck+('local')" to "$deck+('local'+1)"
dec "$deck" by 1
. "display deck and hand"
write overlay c07 "Deck: &$deck& " at 1 1
write overlay c07 "Hand: &$hand&" at 1 2
end
: "deckedout"
* "No cards left to draw!"
end

The only problem with my remove-a-card line vs. OldSckool's was that I put an unnecessary clip length in there, forgetting that without a clip length specified, it goes to the end of the string--we otherwise did exactly the same thing. Thanks to that, and to the use of "inc" and "dec" where appropriate, it's much more readable!

Next up: bodging together 52 crappy MZMs and having them show up as sprites instead of the current raw string format.

This post has been edited by SpellWeavre: 04 May 2010 - 01:06 PM

0

#17 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 04 May 2010 - 02:51 PM

View PostSpellWeavre, on 04 May 2010 - 09:05 AM, said:

The only problem with my remove-a-card line vs. OldSckool's was that I put an unnecessary clip length in there, forgetting that without a clip length specified, it goes to the end of the string--we otherwise did exactly the same thing. Thanks to that, and to the use of "inc" and "dec" where appropriate, it's much more readable!

Next up: bodging together 52 crappy MZMs and having them show up as sprites instead of the current raw string format.


I'm going to suggest bodging together one MZM with 52 cards in it. Instead of having 2ofSpd.mzm and JofHrt.mzm, and having to load and place those individually for each card you draw, just have one cards.mzm, load it to storage space or the vlayer, and reference sprites from it accordingly. I get the idea that you were planning to have sprites statically linked to a reference area and load individual card MZMs into that area when each sprite is attached to a new card. Instead, I'd find it easier to manage if each sprite were assigned the number of the card that was drawn for it, and that number set offsets into a global reference area. Basically, you have cards in an MZM like this:
+--+--+--+--+--+--+--+--+--+--+--+--+--+
|A |2 |3 |4 |5 |6 |7 |8 |9 |10|J |Q |K |
|)%|)%|)%|)%|)%|)%|)%|)%|)%|)%|)%|)%|)%|
+--+--+--+--+--+--+--+--+--+--+--+--+--+
|A |2 |3 |4 |5 |6 |7 |8 |9 |10|J |Q |K |
|<>|<>|<>|<>|<>|<>|<>|<>|<>|<>|<>|<>|<>|
+--+--+--+--+--+--+--+--+--+--+--+--+--+
|A |2 |3 |4 |5 |6 |7 |8 |9 |10|J |Q |K |
|<3|<3|<3|<3|<3|<3|<3|<3|<3|<3|<3|<3|<3|
+--+--+--+--+--+--+--+--+--+--+--+--+--+
|A |2 |3 |4 |5 |6 |7 |8 |9 |10|J |Q |K |
|)>|)>|)>|)>|)>|)>|)>|)>|)>|)>|)>|)>|)>|
+--+--+--+--+--+--+--+--+--+--+--+--+--+

Imagine that's on the vlayer at card_x, card_y, and individual cards are 'card_w'x'card_h' in size. So whenever you draw a card, say it gets put into a counter called newcard, and the next sprite to load is in nextspr or something.
set "spr_&nextspr&_refx" to "('newcard'%13*'card_w' + 'card_x')"
set "spr_&nextspr&_refy" to "('newcard'/13*'card_h' + 'card_y')"
set "spr_&nextspr&_width" to "card_w"
set "spr_&nextspr&_height" to "card_h"
put c?? Sprite "nextspr" at WHEREVER


Note that this is another great reason to use 0-indexed arrays and ranges. With a 1-indexed range for the cards, to make this math work you'd have to subtract 1 from the index anyway to find the right offset. Also keep in mind the idea of storing commonly reused numbers in variables, instead of hard-coding them in. This is good practice in any language, and allows you to change how things work on the fly without having to edit every piece of the code just because you changed a number.

"Fade into blue, fade into black."
To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#18 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 04 May 2010 - 11:20 PM

View PostWervyn, on 04 May 2010 - 09:51 AM, said:

I get the idea that you were planning to have sprites statically linked to a reference area and load individual card MZMs into that area when each sprite is attached to a new card. Instead, I'd find it easier to manage if each sprite were assigned the number of the card that was drawn for it, and that number set offsets into a global reference area. Basically, you have cards in an MZM like this:

Ah, cool! You attribute to planning what is probably better chalked up to ignorance, as I haven't even cracked the book on how sprites work yet. One MZM per sprite is just what my brain came up with based on your pointing me in the direction of MZM-sprite interaction. Your design looks quite nice, though, so I'll run with that!
0

#19 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 05 May 2010 - 11:33 AM

I've drawn my crappy deck of cards. MZM and character set attached.

Next up: learn sprite initialization and placement so as to follow Wervyn's advice above.

Attached File(s)


0

#20 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 05 May 2010 - 03:40 PM

Updated. Facecard art is still up to you, but this should look a lot more like a standard deck of cards, and the proportions are corrected.

I've also written a lengthy tutorial on sprites, although a lot of it doesn't apply to what you're doing, and there are some other tricks you might want to use that aren't in it. For instance, the game is probably best managed by an engine robot and a display robot, with the engine robot deciding the underlying mechanics of the game (what are the rules, what should go where data-wise) and the display robot figuring out how to draw it (i.e. drawing sprites for each visible card). This probably means some sort of sprite dispatcher that picks an unused sprite, initializes it, and places it.

Doing this kind of dispatch isn't hard, the biggest thing to figure out is how to quickly find an unused ID. I generally manage this by designating a range of sprites (here, you should never need more than 52), with an offset like card_sprites that locates the start of this list, and a card_max = 52 to limit the number of sprites of that type that can ever be in play at once. Then, each time you initialize a sprite, inc "cards" or something by 1. Every time a sprite goes away, dec "cards" by 1, and (here's the key) append its ID to a string called "$idclaim", using set "$idclaim.&$idclaim.length&" to "deleted_sprite_id". Now, when you're creating a sprite, you check this string list. If the length of the string is positive, set "new_sprite_id" to "$idclaim.('$idclaim.length'-1)" and dec "$idclaim" by 1. That is, grab the last freed-up ID from the list. If the string is empty, just let the ID be "('card_sprites'+'cards')", unless cards is greater than or equal to 52. Finally, either way if you created a new sprite, increase "cards" by 1.

Now for your case, since you're dealing with not only a finite number of cards but what is actually a unique group of cards, you could really just assign the sprite ID based on the number of the card drawn. That'll be much easier to understand at this stage, and will work just fine. I only mention the other method because if you do get into more complicated stuff where each element you need a sprite for is not necessarily unique, it'll be good to know how to deal with it.

"Or you could work in the finite field GF(2^8)."

Attached File(s)


To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#21 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 05 May 2010 - 10:58 PM

Wow, sweet! Thanks much for the artistic assist there. I'll use that set, no question!
0

#22 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,936
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 06 May 2010 - 03:27 AM

View PostWervyn, on 06 May 2010 - 01:40 AM, said:

Doing this kind of dispatch isn't hard, the biggest thing to figure out is how to quickly find an unused ID. I generally manage this by designating a range of sprites (here, you should never need more than 52), with an offset like card_sprites that locates the start of this list, and a card_max = 52 to limit the number of sprites of that type that can ever be in play at once. Then, each time you initialize a sprite, inc "cards" or something by 1. Every time a sprite goes away, dec "cards" by 1, and (here's the key) append its ID to a string called "$idclaim", using set "$idclaim.&$idclaim.length&" to "deleted_sprite_id". Now, when you're creating a sprite, you check this string list. If the length of the string is positive, set "new_sprite_id" to "$idclaim.('$idclaim.length'-1)" and dec "$idclaim" by 1. That is, grab the last freed-up ID from the list. If the string is empty, just let the ID be "('card_sprites'+'cards')", unless cards is greater than or equal to 52. Finally, either way if you created a new sprite, increase "cards" by 1.


Alternatively, you know, you've only got 52 cards and you probably aren't doing much else! You COULD just loop through them.

Or just scramble the initial set of 52 and draw from the end..
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
0

#23 User is offline   Wervyn 

  • I can see you
  • Group: DigiStaff
  • Posts: 1,855
  • Joined: 24-December 00
  • Gender:Male
  • Location:Caras Galadhon

Posted 06 May 2010 - 10:42 AM

View PostLancer-X, on 05 May 2010 - 11:27 PM, said:

Alternatively, you know, you've only got 52 cards and you probably aren't doing much else! You COULD just loop through them.

Or just scramble the initial set of 52 and draw from the end..


View PostWervyn, on 05 May 2010 - 11:40 AM, said:

Now for your case, since you're dealing with not only a finite number of cards but what is actually a unique group of cards, you could really just assign the sprite ID based on the number of the card drawn. That'll be much easier to understand at this stage, and will work just fine. I only mention the other method because if you do get into more complicated stuff where each element you need a sprite for is not necessarily unique, it'll be good to know how to deal with it.


"Thing. That I said. Is funny."
To lie is to change the truth.
..Ignorance is to be unaware of the truth.
....Incompetence is to be unable to grasp the truth.
......And escape is to run away from the truth.
It is useless to run, since the truth is right next to you.

-Wervyn
0

#24 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,936
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 06 May 2010 - 02:25 PM

Ah, now I see what you're getting at. In that case I'd probably just reallocate sprites each 'round' of changes, simply because it's slightly less fiddly that way.
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
0

#25 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 07 May 2010 - 03:03 AM

All right, so I'm trying to make a routine to assign the values to all the cards. Something weird is happening, though: I'm getting the values 1-13 assigned correctly to each card?_value counter, but card?_suit gets its value in some way that differs from one runtime to the next! Where's my bug?

. "Initialize the deck string: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
. "Assign card data to each string character"
. "local = search position as we move through the deck assigning values"
set "local" to 0
: "cardvalues"
. "local2 = which suit we're working on"
inc "local2" by 1
loop start
. "assign the cards their suits and values"
set "card&$deck+('local')#1&_suit" to "local2"
set "card&$deck+('local')#1&_value" to "('loopcount'+1)"
inc "local" by 1
loop for 12
if "local2" < 4 then "cardvalues"
. "put the deck graphics on the vlayer for later use as sprites"
set "deck_x" to 0
set "deck_y" to 2
put "@Deck2.mzm" Image_file p02 at "deck_x" "deck_y"
end

This post has been edited by SpellWeavre: 07 May 2010 - 03:04 AM

0

#26 User is offline   Dr Lancer-X 

  • 電波、届いた?
  • Group: DigiStaff
  • Posts: 8,936
  • Joined: 20-March 02
  • Location:ur mom nmiaow

Posted 07 May 2010 - 03:31 AM

View PostSpellWeavre, on 07 May 2010 - 01:03 PM, said:

All right, so I'm trying to make a routine to assign the values to all the cards. Something weird is happening, though: I'm getting the values 1-13 assigned correctly to each card?_value counter, but card?_suit gets its value in some way that differs from one runtime to the next! Where's my bug?


Your problem is that counter names are case-insensitive, so carda_suit is the same as cardA_suit.
Posted Image
<Malwyn> Yes, yes. Don't worry I'd rather masturbate with broken glass than ask you for help again. :(
0

#27 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 07 May 2010 - 11:22 AM

View PostLancer-X, on 06 May 2010 - 10:31 PM, said:

Your problem is that counter names are case-insensitive, so carda_suit is the same as cardA_suit.

Ahhhhh. MZX further encourages me to try an array instead of my oh-so-clever string manipulation thing. ^.^; Thank you, that fixed it!
0

#28 User is offline   SpellWeavre 

  • Member
  • Pip
  • Group: Members
  • Posts: 43
  • Joined: 01-September 00
  • Gender:Male
  • Location:Madison, WI

Posted 07 May 2010 - 12:31 PM

Is it possible to initialize all the sprites up-front, then PUT them when an individual sprite is needed? I'm trying to do that, but it's doing goofy things to me. The thing sometimes shows a unique card, but otherwise it tends to put the Ace of Diamonds somewhere... (There's also a problem of the sprites not stacking on top of each other the way I'd want, but that's a less pressing issue.)

. "Initialize the deck string: 52 cards"
set "$deck" to "abcdefghijklmnopqrstuvwxyz1234567890ÐÑÒÓÔÕÖ×ØÏ˜™š›œ"
. "put the deck graphics on the vlayer"
set "deck_x" to 0
set "deck_y" to 2
put "@Deck2.mzm" Image_file p02 at "deck_x" "deck_y"
set "card_width" to 10
set "card_height" to 9
. "Assign card data to each string character, and a sprite to each card"
. "local = search position as we move through the deck"
set "local" to 0
: "cardsetup"
. "local2 = which suit we're working on"
inc "local2" by 1
loop start
. "assign the card its suit, value, and absolute ID"
set "card&$deck+('local')#1&_suit" to "local2"
set "card&$deck+('local')#1&_value" to "('loopcount'+1)"
set "card&$deck+('local')#1&_ID" to "('local'+1)"
. "set up a sprite for the card"
set "spr&local&_vlayer" to 1
set "spr&local&_refx" to "('card_width'*'loopcount'+'deck_x')"
set "spr&local&_refy" to "('card_height'*'local2'+'deck_y')"
set "spr&local&_width" to "card_width"
set "spr&local&_height" to "card_height"
inc "local" by 1
loop for 12
if "local2" < 4 then "cardsetup"
end
: "keyd"
. "make sure we still have a card to draw"
if "$deck.length" < 1 then "deckedout"
. "local = card position to be drawn from"
set "local" to random 0 to "('$deck.length'-1)"
. "add the drawn card to the hand"
inc "$hand" by "$deck+('local')#1"
. "remove the drawn card from the deck"
set "$deck+('local')" to "$deck+('local'+1)"
dec "$deck" by 1
. "display new card"
put c?? Sprite "card&$hand+('$hand.length'-1)#1&_ID" at "('$hand.length'*2)" 0
end
: "deckedout"
* "No cards left to draw!"
end

If this just isn't wise, I'll try the prior suggestions of initializing the next sprite in sequence at the time the card is drawn, but it seems like this would be convenient if it's possible (in which case I must have some other bug).

This post has been edited by SpellWeavre: 07 May 2010 - 12:39 PM

0

#29 User is offline   Old-Sckool 

  • megazeux breaker
  • PipPipPipPip
  • Group: Members
  • Posts: 649
  • Joined: 07-June 05
  • Gender:Male

Posted 07 May 2010 - 02:21 PM

View PostSpellWeavre, on 07 May 2010 - 08:31 AM, said:

Is it possible to initialize all the sprites up-front, then PUT them when an individual sprite is needed? I'm trying to do that, but it's doing goofy things to me. The thing sometimes shows a unique card, but otherwise it tends to put the Ace of Diamonds somewhere... (There's also a problem of the sprites not stacking on top of each other the way I'd want, but that's a less pressing issue.)

...

If this just isn't wise, I'll try the prior suggestions of initializing the next sprite in sequence at the time the card is drawn, but it seems like this would be convenient if it's possible (in which case I must have some other bug).


If I'm remembering the way you created the card mzm correctly, the Ace of Diamonds would act as a "null" output since it's placed at (0,0). What might be happening is that you're trying to grab the card that's just out of the range. I decided to make a simple solitare game myself, and I encountered a similar issue where I wasn't always dealing the right number of cards to the stacks. But I can't seem to tell right now what's wrong with your code (I'm running late to class).

The sprite stacking issue is perhaps a bigger issue that should be addressed before you do anything else if you want to do sprites right. The order that sprites are drawn is based on either their sprite number (Default) where the sprite with the smallest number is drawn first, or their Y position (there's a counter that changes this, don't remember what it's called but it's documented) where the sprite with the smallest Y position is drawn first.
<Nadir> mzxers don't make GAMES, usually
<phthalocyanine> they make experiences.
<Nadir> demos, more like
<Nadir> a glimpse into what could have been if mzx wasn't such a bore to work with
<Nadir> actually, i'm being unfair
<Nadir> i would have made mzx games if it was capable of running on more than 20 computers worldwide in 1998
<Nadir> >:D

<%Alice> functor
<%nooodl> i hear C++ has a thing called functors and they're completely different from Haskell functors...
<rorirover> the result is the most horrid thing in C++, it's basically black magic and it transforms any code you're writing into some eldritch monstrosity
0

#30 User is offline   Old-Sckool 

  • megazeux breaker
  • PipPipPipPip
  • Group: Members
  • Posts: 649
  • Joined: 07-June 05
  • Gender:Male

Posted 07 May 2010 - 05:55 PM

You've made two two mistakes with your cardsetup code. By incrementing local2 before your first passthrough, your setting the suit values to 1-4 instead of 0-3.
: "cardsetup"
. "local2 = which suit we're working on"
inc "local2" by 1
loop start
. "assign the card its suit, value, and absolute ID"
set "card&$deck+('local')#1&_suit" to "local2"

...

loop for 12
if "local2" < 4 then "cardsetup"


Your also giving each card the wrong ID number by setting ID to local + 1

set "card&$deck+('local')#1&_ID" to "('local'+1)"
. "set up a sprite for the card"
set "spr&local&_vlayer" to 1


Lastly, I'm just going to point out that you can also use the modulus (%) operator to easily cycle through or create a two dimensional array without having to use counter variables. All it basically does is gives you back the remainder from the division of the two numbers (ex. 5%8 = 5, 13%6 = 1). So anyways, if you're trying to loop through all of the elements in a 13 by 4 array, you could say that X is ('loopcount'%13), and Y is ('loopcount'/13) and stop the loop once loopcount is 52.

You could rewrite cardsetup like this

: "cardsetup"
loop start
. "assign the card its suit, value, and absolute ID"
set "card&$deck+('loopcount')#1&_suit" to "('loopcount'/13)"
set "card&$deck+('loopcount')#1&_value" to "('loopcount'%13+1)"
set "card&$deck+('loopcount')#1&_ID" to "('loopcount')"
. "set up a sprite for the card"
set "spr&loopcount&_vlayer" to 1
set "spr&loopcount&_refx" to "('card_width'*('loopcount'%13)+'deck_x')"
set "spr&loopcount&_refy" to "('card_height'*('loopcount'/13)+'deck_y')"
set "spr&loopcount&_width" to "card_width"
set "spr&loopcount&_height" to "card_height"
loop for "(52-1)"


It can be adapted to arrays with more than two dimensions, but it gets messy fast.
<Nadir> mzxers don't make GAMES, usually
<phthalocyanine> they make experiences.
<Nadir> demos, more like
<Nadir> a glimpse into what could have been if mzx wasn't such a bore to work with
<Nadir> actually, i'm being unfair
<Nadir> i would have made mzx games if it was capable of running on more than 20 computers worldwide in 1998
<Nadir> >:D

<%Alice> functor
<%nooodl> i hear C++ has a thing called functors and they're completely different from Haskell functors...
<rorirover> the result is the most horrid thing in C++, it's basically black magic and it transforms any code you're writing into some eldritch monstrosity
0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

5 User(s) are reading this topic
0 members, 5 guests, 0 anonymous users