 Okay so I had planned on doing this quite a while ago. I ran into a large number of computer problems basically with both of my computers, my big server and my workstation both having problems and it hasn't been a fun time but doing this now. So what we're going to be doing today is a writing a card game. Just a simple high-low one but it will show off how to structure projects in Ida because the way things are organized are actually rather different. You know a lot of common languages have a concept of namespaces and then classes within them whereas Ida has just packages and it's not more limited but it sounds more limited and it helps to show off how this organization happens. Now also unlike the previous project, the RPN calculator, this one is actually going to be put up on GitHub so if you're looking to do additional things with it like say write your own card game or even just add features to it you will be able to tribute to this project. So let's begin. Now I'm going to need to look up where one specific package is because there's a lot of them and I don't remember where all of them are. Okay now well I'll have to null this out but this should compile. If you're not familiar with my development methods I tend to do very small increments so just enough to get one thing working compile test that it actually works and then add another small thing. Pile test that works and so on. So even though this isn't going to do anything we're going to begin here and then I'll start to explain what is going on. It does compile. Okay so inside of the numerics tree is a few packages involving random number generation and one such one that we actually using here is the discrete random package. What this is is just generates a random number within the range of whatever discrete type you pass it you instantiate it with. In our case the integer. So this works with any integer modular or enumeration. There isn't a specific one for each of those. The discrete generator works with any of them. So what the way it is right now it's not going to be that useful and let me show off why. That is way too big of a number to use for card purposes. So let's do this. What's it called? Well we actually have two options here. Essentially I'm going to numerically represent all the different faces that a card can have. So your standard 2345678910 but then also the Jack, Queen, King and your Ace card. There's two options with that because depending on the game an Ace may be a 1 or may be a 13. In my case just for the sake of better representing how Ada does new types or subtyping I'm going to have it be 2 through 13 so that I can show off in practice how a few of the attributes that the numeric types have work and why they're nice to have. So now if we pass the face type into here instead and I'm actually gonna set up a build task. It's gonna annoy me. Wonderful. Now you just run high low again and you see that we actually get a number in between the range that we specified. It's going to be one other problem however and that if we run this multiple times we always get a 10. Now it's not like this isn't doing true isn't randomly generating numbers. If we put a number of these there you can see that we get a just a bunch of numbers that are all within this range. So what's going on? Why was it a 10 every time? And in fact it's the exact same order every time. Basically this has to do with pseudo random number generation unless you have some kind of hardware numbered generator that is guaranteed well guaranteed to be random. What they really mean there is that there's a high level of entropy that causes to be very unpredictable. It's still probably gonna follow some sort of pattern just the more complex it is the better really. If you don't have that you're gonna have to rely on software random number generation tools and a lot of them are not programmed with a high degree of randomness due to entropy. The ones used in cryptography obviously are going to be but for something like this it's it's not. So we could import a random number generator package or we could introduce some entropy ourselves. And that's going to be the approach I'm gonna take here. Let me look up what this function was called because I forget. Okay yeah so it's reset which seems like a weird thing to do that the moment it's called but there's an additional parameter that we can throw over here which I'm going to do by integer. Let me introduce another package. I believe it's just date. We'll find out. Date is undefined. It's not date. I'm thinking of a different programming language I think. Oh yeah I am. It's it's called clock. Not block clock. And I'm actually not sure if I can just cast that to an integer. I cannot cast that to an integer. So it's two seconds. I think two seconds is undefined. It's not two seconds. That's why it's just seconds. What do we got going on here? Oh boy okay let me... there we go. So one reason I leave all this stuff in this because I want to make it clear that no matter how long you've been programming no matter how experienced you are you're gonna forget silly little things like this and it's good to see that you know they still happen that this isn't something that just happens when you're new. I mean it's gonna happen less of course. I can I've almost memorized the layout of certain packages. I've just been doing this for so long but you're gonna forget things like this. You're gonna make silly stupid mistakes and it's alright. Knowing the means to fix them is what really makes for a good program or not that you can memorize the entire system libraries. Don't don't do that by the way. They change. Don't don't commit that stuff to memory. So now if we run this and say we get a five, we get a nine, we get a ten, we get a nine. So we're actually getting a different number a different face value. There's a little bit of an issue in that if you run this fast enough you may notice that you get reoccurring numbers just because it's waiting for the seconds to change enough but as long as well in a real card game it's not going somebody's not going to be doing things that quickly. So this is this has introduced enough entropy for us to get a reliably varying card game. So now while this is great and all this alone many of these numbers is not a full card game. We also need a suit type as well as a generator for the suit. Remember I said we can use the exact same discrete random package but let's actually have a different name for the old one. Base generator sounds weird but I'm leaving it. So now we're going to have to introduce a qualifier here. So let's do FG is base and SG is suit generator. So I'm gonna want to repeat this. Have a random FG image and space along with a random SG. So we have two parts, 10 of hearts, 11 of spades, 10 of hearts, 7 of spades and why are you the same? Okay so we are getting it just coincidence. So while this is working while we're getting random cards and could write out the rest of the logic here let's actually have a full representation for a card instead of these two separate components and just if you can model something you generally should you know we're not on some embedded system like some one of those really tiny handheld toys from the 90s where you got to save as much space as possible. We don't need to do that to make our lives a little bit easier. No good statement yet let's just represent the thing here. I do need to do the that's fine. We don't need to hide it. Oh Jesus I forget that that's a thing there we go. We don't need this to be private it's fine if these the two fields we're going to add are publicly visible just because this isn't particularly complicated goad and it's fine. It's fine. So this won't need a body at least yet but let's also add well well yeah let's let's add in the deck. We will write the game in after but if you notice yeah it happened here when I was doing that. We got a 10 of hearts and then another 10 of hearts and obviously that you can't draw the same card out of the deck twice once it's out it's out so having an actual deck model will you know prevent that from happening but also we have two generators here and if we have a deck created there is going to be a way to pull a card out of the deck at random essentially shuffling the deck with only one generator so that simplifies our code as well which should be useful because if you're trying to follow along it's better if there are two different generators going on so let's do that we get a now we're going to need oh yeah we're gonna need to include the cards as well so draw is going to return a card and we're going to need that'll provide the index through the deck and I'm going to have to do I keep forgetting about that I think I have to disable the snippets I wrote for myself forget the snippets exist oh boy it wrote them and I forget the snippets exist dog I'll explain what's actually going on here in a second so I'm going to have a jump cut as I write these all out because it's going to be a bit tedious I have to write out every single card that exists we'll pick up when it's done no you don't need to see me type out all these okay so I've got this all written out and you may have noticed the problem I was making without really realizing it a little stupid so this would be 1 through 13 or 2 through 14 let a bit of a mistake so I've just got to add in the the the 14s the aces in this case alright yeah so what's going on here is that we have the package deck which essentially is just a single tin of the deck itself so this is not an object you need to create an instance of it's just the the deck there's a single operation draw essentially because with the random number generator in place you would not actually need to there would be no need to have a shuffle operation it is going to be shuffled behavior anyways and then we just have a bunch of stuff that actually makes it work the index type is you is going to be used by the draw to draw a random index from here that's why we'll be able to reduce the number of random number generators from 2 down to 1 deck card is just a simple wrapper around the actual card that adds this little in deck obviously this isn't the best approach to this but again just small increments I'll show up a little bit saner way of doing this and then we have the the array of cards because that's what a deck is that actually provides the so you can see that all the cards are there and then because it defaults to it being in the deck then setting the others to the default values will of course have them in the deck so we'll mean to write up the draw and I think I forgot to I did we'll give it a bit saner name that's not a type that's a package mad yeah use that actually man and what I call that index generator it's not perfect yet but again trying to do small increments index generator not declared in random in that does that know that would just be generator 49 I wrote space instead of spade yep oh I know why cuz what we actually have to do is be because this is just generating a number this is generating some random number between 1 and 52 which represents the one of the cards in the deck I actually have to get it from the backing then that should complain about it being a deck card rather than just the standard card and that is correct then we can get the actual added compiles so now let's go back into here I had to clean this out because I did some stupid running this but we're still gonna need the added textile and we can just do this draw so I'll get the card and then we have to do so let's do this think that should do it compilation unit expected wait what oh so you'll notice we reintroduced the same problem and that just has to do with how we're not actually calling reset on this generator now I have two options here we can call reset on it each time before we draw that would be quite tedious rather would you probably just want to have the deck shuffled to begin with if we do a package initializer we can get that just call reset generator and we'll need to we'll need to reintroduce this package or what was it integer seconds and then clock so now we should have a sufficiently random and we do okay so now let's actually clean up this a bit you'll find just the way I tend to develop things I focus much more on the underlying stuff and then just build up we could write out the game at this point it's totally viable to write out the game at this point and it would work there's gonna be one minor issue that I'll get to you may even pick up on it and that these cards are technically still left in the deck right now but I like to clean up the things first so that I mostly so that I don't forget about them but also just kind of drives me nuts when the back end code is cluttery so if we change this to being a tagged record then what we can then do is take the deck card and say it is a new card with and then just the extension so then with that in mind we can actually get rid of basically all of this think that's enough we'll see if it complains on line 23 and it does not so I will go through and change all of these to fit the new syntax and now that that is done let's build this right and now it's rightfully going to complain that there is no actual and that is because I should I think unless I'm mixing up my languages it should convert that's just fine okay so we're going to have two options we can return a class wide type don't don't do that for this returning a class wide type would allow us to return a deck card and you really don't need to return the in-deck value because if you have drawn the card it's obviously not in the deck anyway so what we're going to do instead it would just I mean it would be looked at as a view conversion it's just they're all just conversions and added but we're going to reduce it down to the parent type cloud just card so we are quite literally disposing of the in-deck field as we don't we don't need it anymore and you can see that this does still work and cleaned up the code a little bit now this is much easier to read through this doesn't have the weird thing going on with the actual and it's cleaner code it's a good thing so now as I mentioned there's a little bit of an issue in that the deck is the card is technically not being removed from the deck so that has to be implemented now if we have what results now this can't be that has to be an index type and we have random generator so we're going to have to do a few things one is that the backing result so that we get the card we're gonna have to change the in-deck to false we are also going to need to check if the randomly generated one has already been retrieved to think that you do it I think no because we removed we remove the assignment okay at the very least this doesn't complain about anything so what I'm trying to do here is we get a we get the random card you know treating the deck as if it's shuffled we're essentially we're drawing from the top this is just a completely different mechanic going on under the hood where it's actually just drawing a random card from somewhere within the deck but yeah it's essentially shuffled back drop from the top because we're not using stack or queue or anything else where the card would literally be removed we're just identifying that the card has been removed through this field so if the randomly selected card happens to be one that is already marked as being removed go through generate a new number and then test if that new number is also removed so essentially keep looking for a new card until you find one that has not been removed then market is even being removed and return that card obviously this is not the most efficient solution however this is the easiest one to implement it's going to run into some performance problems as you progress through the game again but the whole incremental approach we have the ideal model essentially for the for the deck and the card at this point changing how things work under the hood can be done later without actually changing how the the model the programming interface changes now we can actually write out this game well no let's actually I did build that right and build it anyways now it is going to return potentially the same card just between these runs because we're spawning up a whole new program and that means a whole new deck that has all of the cards in it again if we were to run this multiple times you should not actually see the card at all the same card at all but let's let's actually get these out now so we need H voice again I'll explain what I'm doing in just a second once I see if I'm on the right track here let's ignore the choice for now and then just print back out well nope no don't do that okay and you know I just have it run in the background so obviously in this instance we'd guess higher and cave it sees that we actually entered in each and some other key entirely so obviously we don't want to recognize have it recognize some random key but it does get the input in an appropriate way just pressing the single character the single key was enough I didn't have to press that and then enter which then saves us from the possibility of them typing multiple letters and then enter which don't I don't want to set things up that way so with that in mind let's do for I think I can do a case on that so so what we're going to have to do is if the input is not valid go back up here which yeah I know some people aren't gonna like this but whatever oh also because we want to see what the choice is just to make sure that it's being set properly so we test higher entered higher lower entered lower and some random key it asks again okay good good oh god okay obviously there's some minor formatting things there's also a little bit of an input issue and let's fix that I'll leave that there that's fine it's colored anyways so let's actually put the new line immediately after you quit option so when Q or Q just return now we should actually be able to quit and the formatting should be a bit better oh I got a testy um still does that so that's because oh yeah that's because of that so we need we need another new line now you'll also notice that when I select it doesn't draw another card for me that I guess again it rather just quits the program and this should make sense given that after the entered statement there's nothing left it doesn't move back around so let's actually encapsulate this entire thing and now one more thing is that currently it's just asking for the input it's not actually doing anything with it so what we also need to do is make a choice and then set full card to a new card I'm thinking of how to structure this well actually we can do a sacrificial draw it'll reduce the game down to just 51 cards but that that would be the easiest way of doing it I'm trying to have this so it's not flawless when it's uploaded to github that way there's things that if anybody wants they can actually do uh so if we do a new card uh actually we just need the old card deck so okay I do need this though we're gonna do our comparison here here no and you know here's mine so we want to see if well the way high low works it's on whether the face value is higher or lower so if we have a new card well we need another statement so if new card is greater uh new card's face is greater than the old card's face oh of course I I need to also check for the the choice the choice means that that was silly so if choice equals higher and then the new card's face is greater than the old card's face and we can also have else if choice equals oh no wait that's that's the sharp syntax we do just that but yeah also choice equals lower and then new card's face is less than old card's face and we're also right uh so five gets higher seven gets higher that was wrong higher lower so we have the working game uh the only thing I want to do from this point is just an image function unfortunately you can't override the image attribute I really wish you could uh because it would make things more consistent but um we're going to need an image function which sort of operates the same way but takes the card and prints it out but does a little bit of thinking when it prints it out now we're going to need a card so yeah I don't need to include anything so maybe reference before has a value oh that's interesting that the compiler doesn't realize that then because this and part of the reason why this exists is to prevent the choice from actually being referenced before it's assigned um because during the first draw it's going to do the sacrificial old card just so that it can shut up uh grab the new card it's the first draw so it's going to set the first draw to false and then just skip over this where it's going to print out the draw and then ask for your choice the second time around it goes through it does the whole old card thing or no it's going to skip the old card thing because we've got the loop here but it's going to get a new card it's going to see that it's not the first draw and then actually go through and assess the choice so it's interested the NAT compiler needs some better flow analysis but either way I mean we could disable that warning it's it's not going to reference choice before it's been assigned it just will not happen um but it looks like that compiled uh which it's good again small little incremental improvements but we can just go and I call that image function to get the output with cards now now obviously we want to handle a few special conditions here so when the card is 11 then we're actually going to return a uh let's actually at the hub but still we're going to return a jack of and then whatever the suit is so you can see that that works um just for the sake of orthogonality I'm going to capitalize these entirely just because I meant like that but you can see we have a working hylo game and just shy of 20 lines of actual code the rest of this is essentially just a library that can be reused for other card games so like I had said I'm going to be publishing this up on github I'll have a link down in the video description for where I put this up there um hopefully this has helped you out I've definitely shown a bit about package organization and different approaches to things obviously this code needs some needs some work still but that's kind of the point here I went through and showed the most straightforward ways to do this and then just built on top of that not necessarily showing the absolute best approach to this because I can promise you if I did the absolute best approach to this you're going to be like what the heck is actually going on because it involves a stack and pointer manipulations and stuff that's an advanced subject yeah hopefully this has helped you out if it has consider thumbs up liking video also consider subscribing I try to produce at least one of these videos a week although the computer problems I've been having had gotten in the way have a good one