Permanent* MTGPlayer_playCard(MTGPlayer* player,int cardIndex, char* err) { MTGCard* card = (MTGCard*)player->hand->entries[cardIndex]; if (card == cd.IllusoryAngel && !player->hasCastSpell) { sprintf(err, "Can play IllusoryAngel only if you have casted another spell"); return NULL; } if (card->subtypes.is_convoke) { if (player->canConvoke) { if (player == player1) { memset(player->convokeMana, 0, 6*sizeof(int)); selectConvoke(player,cardIndex); player->canConvoke = !player->canConvoke; sprintf(err,"Select creatures to convoke"); return NULL; } else { AI_selectConvoke(player, cardIndex); } } else if (player == player1) player->canConvoke = !player->canConvoke; } if (player == player1 && !MTGPlayer_payMana(player, card->manaCost)) { memset(player->convokeMana, 0, 6*sizeof(int)); sprintf(err,"Not enough mana to play %s (%d/%d)",card->name,player->mana[0],card->cmc); return NULL; } else if (player == player2 && !AI_payMana(card->manaCost)) { memset(player->convokeMana, 0, 6*sizeof(int)); return NULL; } memset(player->convokeMana, 0, 6*sizeof(int)); if (card->subtypes.is_land && player->playedLand) { sprintf(err,"You can only play one Land per turn"); return NULL; } //create permanent Permanent* permanent = NewPermanent(card,player); //apply card effects if (card->subtypes.is_land) { player->playedLand = true; AppendToList(player->lands, permanent); } else AppendToList(stack, permanent); //remove card from hand RemoveListIndex(player->hand,cardIndex); return permanent; }
HOT PyrObject *PyrGC::New(size_t inNumBytes, long inFlags, long inFormat, bool inCollect) { PyrObject *obj = NULL; if (inFlags & obj_permanent) { return NewPermanent(inNumBytes, inFlags, inFormat); } #ifdef GC_SANITYCHECK SanityCheck(); #endif // obtain size info int32 alignedSize = (inNumBytes + kAlignMask) & ~kAlignMask; // 16 byte align int32 numSlots = alignedSize / sizeof(PyrSlot); numSlots = numSlots < 1 ? 1 : numSlots; int32 sizeclass = LOG2CEIL(numSlots); sizeclass = sc_min(sizeclass, kNumGCSizeClasses-1); int32 credit = 1L << sizeclass; mAllocTotal += credit; mNumAllocs++; mNumToScan += credit; obj = Allocate(inNumBytes, sizeclass, inCollect); obj->obj_format = inFormat; obj->obj_flags = inFlags & 255; obj->size = 0; obj->classptr = class_object; obj->gc_color = mWhiteColor; #ifdef GC_SANITYCHECK SanityCheck(); #endif return obj; }
PyrObject *PyrGC::New(size_t inNumBytes, long inFlags, long inFormat, bool inCollect) { PyrObject *obj = NULL; if (inFlags & obj_permanent) { return NewPermanent(inNumBytes, inFlags, inFormat); } #if SANITYCHECK SanityCheck(); #endif // obtain size info int32 alignedSize = (inNumBytes + kAlignMask) & ~kAlignMask; // 16 byte align int32 numSlots = alignedSize / sizeof(PyrSlot); numSlots = numSlots < 1 ? 1 : numSlots; int32 sizeclass = LOG2CEIL(numSlots); sizeclass = sc_min(sizeclass, kNumGCSizeClasses-1); int32 credit = 1L << sizeclass; mAllocTotal += credit; mNumAllocs++; mNumToScan += credit; if (inCollect && mNumToScan >= kScanThreshold) { Collect(); } GCSet *gcs = mSets + sizeclass; obj = (PyrObject*)gcs->mFree; if (!IsMarker(obj)) { // from free list gcs->mFree = obj->next; } else { if (sizeclass > kMaxPoolSet) { SweepBigObjects(); int32 allocSize = sizeof(PyrObjectHdr) + (sizeof(PyrSlot) << sizeclass); obj = (PyrObject*)mPool->Alloc(allocSize); } else { int32 allocSize = sizeof(PyrObjectHdr) + (sizeof(PyrSlot) << sizeclass); obj = (PyrObject*)mNewPool.Alloc(allocSize); } if (!obj) { post("alloc failed. size = %d\n", inNumBytes); MEMFAILED; } DLInsertAfter(&gcs->mWhite, obj); } obj->obj_sizeclass = sizeclass; obj->obj_format = inFormat; obj->obj_flags = inFlags & 255; obj->size = 0; obj->classptr = class_object; obj->gc_color = mWhiteColor; #if SANITYCHECK SanityCheck(); #endif return obj; }