Sorry guys - I intended to come back on this one earlier, but managed to get diverted (again).
I might as still well throw in my own 2¢ on this (although my conclusion pretty much echoes what’s been said). Exploring the pros and cons of different techniques can be a useful process, since it often helps to convince us about the best way forward in a given situation (rather than merely accepting a particular method as the “best” way or “a really bad idea”. When embarking on a project, it’s also useful to outline the entire process before committing to a general approach. Consideration of what may be required later in a script can help to avoid the frustration of painting oneself into a corner.
As we’ve seen, it’s a perfectly possible to actually script the creation of records based on a predetermined labelling scheme. Here’s another variation:
to |deal the cards| from d to p
set t to ""
set tid to text item delimiters
set text item delimiters to "\", \""
tell (count d) div p to repeat with i from it to it * p by it
set t to t & ", player_" & i div it & ":{\"" & d's items (i - it + 1) thru i & "\"}"
end repeat
set text item delimiters to tid
run script "{" & t's text 3 thru end & "}"
end |deal the cards|
set |top of the deck| to {"five", "Queen", "Ace", "eight", "two", "King"}
set |the players| to choose from list {1, 2, 3, 4, 5, 6} with prompt "How many players?"
if |the players| is false then return
|deal the cards| to |the players| from the |top of the deck|
The difficulty arises in accessing a record, mainly because its labels are not defined at compile time - so the script won’t really know in advance what they are - or, consequently, how to refer to them. You’d need to come up with some referencing method (which will probably be index-based, anyway). Given consistent labelling and the ability to count items, a referencing of sorts can be achieved - which is where a few tricks, including the so-called “hack” to which Adam referred earlier, might be utilised:
on |quoted text| from v
try
{v}'s v
on error v
set d to text item delimiters
set text item delimiters to "{"
set v to v's text from text item 2 to end
set text item delimiters to "}"
set v to v's text beginning thru text item -2
set text item delimiters to d
v
end try
end |quoted text|
set |hands dealt| to {player_2:{"Ace", "eight"}, player_1:{"five", "Queen"}, player_3:{"two", "King"}}
set player_number to 2
run script (|quoted text| from |hands dealt|) & "'s player_" & player_number
--> {"Ace", "eight"}
Note that the variable |hands dealt|, shown above, is a record in which the labels don’t appear in sequence - and this is where such extraction methods can be helpful in obtaining the correct values. However, dynamic labelling almost invariably produces records with labels in a predetermined sequence. If you’re sure that the original sequence will remain intact, then the extraction of values can be greatly simplified:
set |hands dealt| to {player_1:{"five", "Queen"}, player_2:{"Ace", "eight"}, player_3:{"two", "King"}}
item 2 of (|hands dealt| as list)
--> {"Ace", "eight"}
But then again, if values are to be obtained by index, it’s usually much cleaner to just use a list directly:
set |hands dealt| to {{"five", "Queen"}, {"Ace", "eight"}, {"two", "King"}}
item 2 of |hands dealt|
--> {"Ace", "eight"}
So, while records can be very useful in certain situations, I’m not entirely convinced that this would be one of them. (I’m obviously viewing this fairly superficially - and the devil may well be in your detail…)
I just dug out an old card game routine that I cobbled together a while back, which is based entirely on list manipulation. In case it might help, I’ve included part of it here - up to the point where the hands are dealt and sorted. (Even this truncated version is a bit lengthy, but the game play sections of the original were just too long to include here.)
The script attempts to emulate pretty much what happens in a regular card game, using only vanilla AppleScript. A fresh deck is taken and shuffled. A user-defined amount of cards is then dealt to a number of players (also user-defined). Each hand is then sorted by value (2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A) within each suit (hearts, clubs, diamonds, spades). This “shortened” version ends by simply displaying the cards in each hand. (And not a record in sight…)
script get_deck
set d to {}
repeat with s in «data utxt2661266326622660» as Unicode text
repeat with c in {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"}
set d's end to c & s
end repeat
end repeat
d
end script
script get_index
tell {}
repeat with i from 1 to 52
set end to i
end repeat
it
end tell
end script
property full_deck : run get_deck
property index_list : run get_index
property every_player : 4
property each_hand : 13
property empty_hands : {}
property variable_hands : false
property hand_variance : ""
to shuffle_(current_deck)
script o
property d : current_deck
property l : my index_list's items
end script
repeat with i from 1 to 52
tell some number of o's l
set o's l's item it to false
set o's d's item i to my full_deck's item it
end tell
end repeat
end shuffle_
to count_(p)
repeat
tell (display dialog "How many players?" default answer p) to try
tell text returned as integer to if it > 0 and it < 53 then return it
end try
end repeat
end count_
to count_cards of h for p
set l to {}
set m to 52 div p
repeat with n from 1 to m
set l's end to n
end repeat
if m < h then set h to m
if 52 mod p > 0 then tell "Deal all cards"
set l's end to it
if variable_hands then set h to it
end tell
tell (choose from list l with prompt "How many cards for each player?" default items h)
if it is false then error number -128
set variable_hands to it contains "Deal all cards"
if variable_hands then tell 52
set each_hand to it div p
set hand_variance to "/" & each_hand + 1
return it
end tell
set each_hand to it
set hand_variance to ""
it * p
end tell
end count_cards
to count_hands for p
tell {}
repeat p times
set end to {}
end repeat
it
end tell
end count_hands
to deal_cards from d to p thru c
copy empty_hands to h
tell h
repeat with i from 0 to c - 1
set item (i mod p + 1)'s end to d's item (i + 1)
end repeat
it
end tell
end deal_cards
to sort_cards from d for p
copy empty_hands to h
script o
property l : d
property r : h
end script
considering case
repeat with n from 1 to 52
tell my full_deck's item n to repeat with i from 1 to p
if it is in o's l's item i then
set o's r's item i's end to it
exit repeat
end if
end repeat
end repeat
end considering
h
end sort_cards
to show_cards of l for p given d:d, g:g, c:c, h:h
set tid to text item delimiters
set text item delimiters to ", "
repeat with i from 1 to p
set l's item i to "Player " & i & return & l's item i
end repeat
set text item delimiters to return & return
tell l to set l to beginning & ({""} & rest)
set text item delimiters to tid
tell button returned of (display dialog "Game " & g & " ¢ Deal " & d & h & return & ¬
return & l buttons {"End Play", "New Game.", "New Deal."} default button 3)
if it is "End Play" then error number -128
if it is "New Game." then return my (new_game given game_number:g + 1)
end tell
end show_cards
on new_game given game_number:g
set every_player to count_(every_player)
set total_cards to count_cards of each_hand for every_player
set empty_hands to count_hands for every_player
tell every_player to set hand_info to " ¢ Cards: " & total_cards & " (" & it & ¬
{" hands of " & each_hand & hand_variance, " hand"}'s item (1 div it + 1) & ")"
set current_deck to my full_deck's items
set deal_number to 1
repeat
shuffle_(current_deck)
set every_hand to deal_cards to every_player from current_deck thru total_cards
set every_hand to sort_cards from every_hand for every_player
show_cards of every_hand for every_player given g:g, d:deal_number, c:total_cards, h:hand_info
set deal_number to deal_number + 1
end repeat
end new_game
new_game given game_number:1