Thursday 25 February 2016

BlackJack: 3 in one gaming assessment




Assessment 2: 3 in one gaming


Sprites:

Deck (spr_deck)
Contains all of the cards sprites.
Deal Button (spr_dealbutton)
Used to deal the cards.

Twist (spr_twist_button)
Used to allow the player to spawn a card.
Stick (spr_stick_button)
Allows the player to pass the turn.
Restart (spr_restart) 
The restart button was there so that I could restart the game to check if everything was working each time I played. 

Objects:

Controller (controller)
Player (obj_player)

AI1 (obj_AI1)
AI2 (obj_AI2)
Dealer (obj_dealer)
Deck (obj_deck)
Twist (obj_twist)
Stick (obj_stick)

Controller:
(Create Event):
Contains and initialises all of the global variables which are used in game. It also contains code for the ini file. The ini file code is:

ini_open("scores.sav")   (Doesn't create it, gets it ready)


if !(ini_key_exists("player", "wins")) then {              
     ini_write_real("player", "wins", 0)
}

ini_close()

If there isn't "player" and "wins" there then create it in the ini file "scores.sav" and the ini_close, closes the file it has been written/checked its been written.




(Step Event):
In the step event of the controller contains code which checks whether all the players have hit more than 21. When it checks through each if statement, its checking to see whether the player is over 21, and if they are, the global.turn changes to 1000. The reason behind why it changes to 1000 because is so it is a value which I know I won't use to activate anything important. The global.turnTo is a variable which is used to change who's turn it is. When it changes integer, that when it is the next person/AI turn.

(Draw Event):
The code within the draw event is just repeated code. The main mechanism behind it is, if the variable "finish"is 0, which is the state where the game is in play, then it checks to see whether the value of their cards added up is over 21. If they are over 21, (which in the step event, if they are over 21 it switches to 1000) then it activates the else statement and displays the word "bust".
This code is repeated for all of the AIs as they use similar coding.

Further down is the code in which displays whether the players have won or the dealer has won. The code is repeated for the AIs as they use similar code. So the first part of the code is checking whether the game has finished, if it is equal to 1 then the game has finished. Then it checks whether the playervalue is NOT 1000 and the player cards value is  more or equal to the dealers card value or dealers value is equal to 1000 then the player wins and it displays the words "You won!". Additionally, it opens the ini file, reads the current amount of wins, then the next part which is "if global.save = 0 then...." this section checks whether a new score needs to be saved and then adds 1 if the player has won. Within this global.saved if statement, it will read the ini file and display the current amount of wins when you have won. The else statement checks whether the cards value in hand = 1000 or the playervalue is less than the dealers then it will say the player has lost.
The dealer code for this is different. The wins don't get saved when the dealer wins. What happens is, when the dealer value is not a 1000 (a value which is used generically) it displays the current card value in the dealers hand, else when the dealer value is 1000 then the total display changes to "bust".




(press F key Event)
This event comes into play when the player wants to access full screen mode. The screenstate is setting acts as an on and off switch for when activating the full screen mode.







obj_player:
There is not much code in the player object as a lot of the mechanisms for the player have already been predefined in the controller object.

(Create Event): (similar coding for all AI/Dealer)

Depth = -global.player_card_xpos - this piece of code defines where the placement of the cards of going.

global.player_card_xpos += 80 - This adds 80 pixels onto where the previous card has been displayed and then places a new a card.

image_speed = 0 - We want the card to not cycle through all the image index so we have it set to 0.

image_index = ds_list_find_value(global.deck,0) - Sets the image index to the values in the ds list.

cardValue = ds_list_find_value(global.deck,0) - Finds the value chosen for that card.

ds_list_delete(global.deck,0) - Removes the selected card from the ds_list deck.




obj_dealer:
(Create Event):
Similar code to player, just different variables used.





(Alarm 0):
There are only two lines of code within this event.

global.turn = 3 - This line of code is a variable change so it can activate another persons turn.

show_debug_message("Alarm countdown works333") - This allows me to see if the alarm has worked by showing a debug a message.





(Step Event):
The step event contains 3 if statements (one nested).

if global.turnTo = 3 then {
    show_debug_message("Alarm works3333")
    alarm[0] = 100
    global.turnTo = 1000
}

This first section above is checking whether the turnTo variable is 3. Once it is 3, the alarm will activate and then the turnTo variable is set to the common number of 1000, one we don't use to activate anything.

if global.turn = 3 then {
    if global.DealerValue < 17 then {
        instance_create(global.dealer_card_xpos, 145, obj_dealer)
        global.turn = 1000
        global.turnTo = 3
    }

    if global.DealerValue >= 17 then {
        global.turn = 1000
        global.turnTo = 1000
        global.finish = 1
    }
}


This second section checks whether the variable "turn" has changed to 3 (in which is has because of the alarm event) activates the nested if statement. The nested if statement checks whether the dealers overall cards in hand are less than 17 then it will automatically produce another card for the dealer.
If it is more than 17, the dealer is not allowed anymore cards.



obj_AI1/obj_AI2:
(Create Event):
The create event uses similar code to the dealer and player object, the only difference is the variables used. 






(Alarm Event):
The alarm event uses similar code to the dealer and player object alarm events, the only difference is what the variables are equal to.





(Step Event):
The step event is the event which holds the probability code.  I am going to break this code into sections and explain what this does.

if global.turn = 1 then {
    if global.AI1Value = 21 then {
        global.turn = 1000
        global.turnTo = 2
        exit

    }

This small section defines whether the AI has definitely hit 21 or not. If they have definitely got 21 then the turns have to increment by one. 

if global.AI1Value < 16 then {
        instance_create(global.AI1_card_xpos, 457.5, obj_AI1)
        show_debug_message("AI1 Value less than 16 therefore card")
        global.turn = 1000
        global.turnTo = 1

  

This section is the first third of the probability code used. This is checking whether the cards in hand for AI1 is less than 16, if so a card will definitely spawn in for them and add on to the current overall value. (The turn and turnTo variables are there just to make sure the turn doesn't change). 

} else if global.AI1Value >= 16 then {
        if irandom(global.AI1Value - 16) = 0 then {
            instance_create(global.AI1_card_xpos, 457.5, obj_AI1)
            show_debug_message("AI1 Value greater than 16 therefore probs card")
            global.turn = 1000
            global.turnTo = 1

            exit

This is the second third of the probability code used. If the current cards in hand for AI1 add up to more than 16 or is 16 then an if statement is carried out. The irandom is used so that it picks a random number between whatever the current value in hand is - 16 and 0. For example, if the AI1 cards add up to 18, then it run through the code, minus 16 from 18 (which leaves 2) and picks the number 2, 1 or 0. If the number is 0 then it will spawn in another card, keep the turn as 1 (which allows it to take another go) and runs through the code again.

  } else {
            global.turn = 1000
            global.turnTo = 2
            show_debug_message("AI1 Value greater than 16 therefore probs no card")
            exit
        }
    }
}

This is the last third of the probability code used. If the irandom number chosen is not 0 then the turn goes to the next player and a debug message is shown, allowing me to check that the turn has definitely been passed on.




obj_deck:
(Create event):

global.deck = ds_list_create()
for(k = 0; k < 52; k += 1) {
    ds_list_add(global.deck, k)
}
randomize()
ds_list_shuffle(global.deck)

The "randomize" code randomises the random seed every time, so that when the deck shuffles, it will not have the same shuffle every time.
This section of code create the ds_list which is used for deck.
What the ds_list looks like right now is:

index: 0 1 2 3 4 5 6 7 8 9 10 ...
value: 1 2 3 4 5 6 7 8 9 10 11...

The index is the location, where the values are stored.

global.deckValue = ds_list_create()
for(k = 2; k < 11; k += 1) {
    ds_list_add(global.deckValue, k)
}
ds_list_add(global.deckValue, 10)
ds_list_add(global.deckValue, 10)
ds_list_add(global.deckValue, 10)
ds_list_add(global.deckValue, 1)

The section of code is where i add the values to the card deck. Where "k" is equal 2 and is less than 11, this is where the value will align with the index numbers. The increment of 1 makes sure that the values will definitely go up by one.  It will look a little like this;

index: 0 1 2 3 4 5 6 7 8
value: 2 3 4 5 6 7 8 9 10

The ds_list_add section adds the numbers 10 3 times and 1 for the Jack, Queen, King and Ace after the value numbers 2-10. So now the value will look like:

index: 0 1 2 3 4 5 6 7   8   9  10 11 12 13
value: 2 3 4 5 6 7 8 9 10 10 10 10 1

This now covers a whole suit of cards. This first suit of cards is most likely spades as that is the first suit seen in the image index. This section of code is repeated another 3 times for the other 3 suits.




(Left button event):

if mouse_check_button_pressed(mb_left) && global.dealDone = 0 {
// Deal button event

instance_create(global.dealer_card_xpos, 145, obj_dealer)
instance_create(global.dealer_card_xpos, 145, obj_dealer)
instance_create(global.player_card_xpos, 745, obj_player)
instance_create(global.player_card_xpos, 745, obj_player)
instance_create(global.AI1_card_xpos, 457.5, obj_AI1)
instance_create(global.AI1_card_xpos, 457.5, obj_AI1)
instance_create(global.AI2_card_xpos, 457.5, obj_AI2)
instance_create(global.AI2_card_xpos, 457.5, obj_AI2)
global.turn = 0
global.dealDone = 1
exit
}

if mouse_check_button_pressed(mb_left) && global.dealDone = 1 {
game_restart()
exit
}

This code is fairly simple, what happens is when the player left clicks on the card deal sprite, it will instantly deal the cards to the desired positions. Then the turn is set to 0 which means the first player can take their turn and dealDone is a variable used to make sure that the deal has been successful.
The bottom if statement checks whether the left button has been pressed over the sprite and checks if the deal was successful and then the game will restart.



obj_twist:
(Left button event):

if mouse_check_button_pressed(mb_left) {
    switch(global.turn) {
    case 0:
        instance_create(global.player_card_xpos, 745, obj_player)
    break
    case 1:
    show_message("You must wait for Player 1 to end their turn")
    break
    case 2:
    show_message("You must wait for Player 2 to end their turn")
    break
    }
}

When the left button is pressed, the player is able to add another card to their hand of cards to get close to the objective of the game, getting "blackjack"/21. If the player becomes bust or tries to use the twist button whilst it is someone else turns, a message will pop up dependent on which global.turn it is on. If the turn is on 0 then the player is still able to take their turn.



obj_stick:
(Left button event):

if mouse_check_button_pressed(mb_left) {
    switch(global.turn) {
    case 0:
        global.turnTo = 1
        global.turn = 1000
    break
    case 1:
    show_message("You must wait for Player 1 to end their turn")
    break
    case 2:
    show_message("You must wait for Player 2 to end their turn")
    break
    }
}

The code used for the stick button is very similar to the twist button. The code uses a switch statement instead of a bunch of if statements as it is easier and tidier to use. If the turn is on 0 and the player clicks on "stick" then the turnTo is activated and activates code for the AI player and your turn is over.



Sound:
I only have one sound for this game which is used for when the cards have been dealt. This sound lasts for a few seconds. The only reason why I only have one sound is because I have mainly been focusing on the coding for the game to make sure that everything works in harmony with one another. The sound code will be shown in a testing video (done by me) showing what sound I chose and showing it working.

Management:


Testing: 

Luke Anderson: The game was good with the dealing and the AI but I was able to restart the game when ever I want.

{The image below displays him typing up his thoughts on the game into my blogger.}




{The image below displays his game play when he pressed the deal button (back of card)}



{The image below displays his game play, after he has taken his turn and the AI's have taken their turn}


The reason behind why it says he has won "3" times is because that is how many times he has won on this computer.

Morgan Proffitt:

https://www.youtube.com/watch?v=GyccyeSxVM0&feature=youtu.be





Me:

https://www.youtube.com/watch?v=hr4fJiuUgRI&feature=youtu.be