ID:173338
 
Quick (i hope) problem, I want to make a copy of a set of 'Cards' into a global list called 'Deck' and i thought this may work:

world
New()
..()
for (var/Atype in typesof(/obj/Cards))
var/TIMES = Atype:times
while(TIMES != 0)
Deck.Add(Atype)
TIMES -= 1

Atype:times is the number of that kind of card in the deck, when i compile and run i get the following runtime error:

runtime error: Cannot read /obj/Cards/Machine_Gun/Front (/obj/Cards/Machine_Gun/Front).times
proc name: New (/world/New)
usr: null
src:
call stack:
: New()

Now I understand how it means it cant read the obj's times var but how should I go about making it work?, Any pointers would be great..
Thanks in advance..

-Thorg
...What you want to make a <font color=blue>new</font> deck of card or a list....?
var/decklist = list()
world/new
tab>for(var/obj/cards/C in world)
tab>tab>if(C.ATYPE == whateva)
tab>tab>tab>decklist += list("[C.name]")

now I have know idea what the big pivture is so who knows if tyhats what you ment but that will check the world for cards and make a list of them and add em' to decklist..


But if you want a list of cards why not just make the list manually?
Hehe, pointers is your problem exactly! I had typed out a huge description, but this will be easier:
world
New()
..()
for(var/Atype in typesof(/obj/Cards)-/obj/Cards)
var/obj/Cards/X = new Atype()
for(var/TIMES = X.times,TIMES>0,TIMES--)
Deck.Add(Atype)
del(X)

If you're just wanting to add the type to the list, that will work, otherwise, relplace "Deck.Add(Atype)" with "Deck.Add(new Atype())".

Hopefully that does it for you!
Thorg wrote:
Quick (i hope) problem, I want to make a copy of a set of 'Cards' into a global list called 'Deck' and i thought this may work:

world
New()
..()
for (var/Atype in typesof(/obj/Cards))
var/TIMES = Atype:times

Since Atype is a type path (since you're looping through typesof()), not an actual object, this will fail spectacularly in exactly the way you've seen. Type paths don't have variables; the objects they instantiate do. Hence, you can't use path.var or (much worse) path:var.

while(TIMES != 0)
Deck.Add(Atype)
TIMES -= 1

Addendum: This time of loop is a lot safer with > instead of != just in case (for any weird reason) the number ends up with a small fractional component and thus skips over 0 entirely.

Atype:times is the number of that kind of card in the deck, when i compile and run i get the following runtime error:

runtime error: Cannot read /obj/Cards/Machine_Gun/Front (/obj/Cards/Machine_Gun/Front).times

See? You can't access a var belonging to a type path because a type path is not an object. This makes about as much sense as trying to access "Hi".len or 3.is_odd.

Now I understand how it means it cant read the obj's times var but how should I go about making it work?

It can't read the var because there's no object to read from. A type path is not an object.

Now the way to deal with this properly is one of the following:

  • Create an associative list of type paths and times, like this:
var/list/defaultdeck = list(\
/obj/Cards/green = 4,
/obj/Cards/brown = 8,
/obj/Cards/red = 5,
/obj/Cards/blue = 15)
Then loop through that list. Or,

  • If you're just creating the cards outright, give each card type a number of times to appear in the deck. When you create the first card of that type, read its times var. And don't use the colon operator to do that, because that's just ridiculous.
for(var/Atype in typesof(/obj/Cards)-/obj/Cards)  // I doubt you want /obj/Cards included
var/obj/Cards/C = new Atype()
Deck += C
var/times = C.times
while(--times > 0) Deck += new Atype()
This approach only makes sense if you want the list populated with actual objects, not type paths.

Now in Incursion, I use a method similar to the first because my deck is full of type paths that don't get instantiated until the card is drawn. And for reference, here's a little of the code I use for cards.
var/list/deck
var/list/discard

// this is just part of the card datum, not including some procs I use for display and play
card
var/name // full name of card var/icon='cards.dmi'
var/help // icon_state, short form of name
var/tasktype // task added to game task list when played

proc/ResetCards()
if(deck) deck.Cut()
else deck=new
if(discard) discard.Cut()
AddDeck()
proc/InitDeck()
deck=new
AddDeck()
proc/AddDeck()
var/list/L=new
var/cardtype
for(cardtype in typesof(/card)-/card) L[cardtype]=8
L[/card/redtape]=4
for(cardtype in L)
for(var/i=L[cardtype],i>0,--i)
deck+=cardtype

proc/DrawCard()
if(!deck) InitDeck()
if(!deck.len)
if(!discard || !discard.len)
Broadcast() << GameMsg("Opening another deck....")
AddDeck()
else
Broadcast() << GameMsg("Shuffling the discard pile....")
deck=discard
discard=null
.=pick(deck)
deck-=.

proc/Discard(cardtype)
if(!deck) InitDeck()
if(!discard) discard=new
discard+=cardtype

// for reclaiming ditched cards
proc/Undiscard(cardtype)
// by all rights, a ditched card should still be in the discard pile
// a new card for conquest is drawn after ditched cards are reclaimed (by optional house rule)
if(discard && discard.Remove(cardtype)) return
// these cases really shouldn't happen, but just in case
if(!deck) InitDeck() // this *really* shouldn't happen
if(deck.Remove(cardtype)) return
Broadcast() << GameMsg("Opening another deck....")
AddDeck()
deck-=cardtype
As you can see, I've got some common-sense fallbacks for weird cases that should never ever come up. Also note that the deck and discard lists aren't created until they're needed.

Lummox JR
In response to Lummox JR
Thanks, that fixed the problem.

-Thorg