Name: Anonymous 2011-10-28 11:28
How do I override functions used in structs in c?
Function pointers?
Function pointers?
void (*anusify[])(void) = {hard, soft, smooth, …, rough};
void perfromanus(const int anus_index)
{
/* Call the function specified by jump_index */
anusify[anus_index]();
}
Interface EntityAble {
int getHealth();
void recieveDamage(int damage);
void attack(EntityAble target);
};
struct entity_interface {
int (*get_health)(struct entity_interface** self);
void (*recieve_damage)(struct entity_interface** self, int damage);
void (*attack)(struct entity_interface** self, entity_interface* target);
void (*rest)(struct entity_interface** self);
};
struct entity_base {
struct entity_interface* v_table;
int health;
};
int entity_base_get_health(struct entity_interface** self) {
return ((struct entity_base_class*)self)->health;
}
void entity_base_recieve_damage(struct entity_interface** self, int damage) {
((struct entity_base_class*)self)->health -= damage;
}
struct wizard {
struct entity_base;
int mana;
double magic_damage_multiplyer;
};
int wizard_calculate_amount_of_mana_to_use(struct wizard* self, struct entity_interface** target) {
int other_health = target->get_health(target);
int ideal_amount_of_mana = (int)((double)other_health/self->magic_damage_multiplyer);
int maximum_amount_of_mana_to_use = self->mana/2;
int mana_to_use = ideal_amount_of_mana > maximum_amount_of_mana ? maximum_amount_of_mana : ideal_amount_of_mana;
return mana_to_use;
}
void wizard_attack(struct entity_interface** self, struct entity_interface** target) {
struct wizard* self_wizard = (struct wizard*)self;
int mana_to_use = wizard_calculate_amount_of_mana_to_use(self, target);
int damage_to_deal = (int)((double)mana_to_use*self_wizard->magic_damage_multiplyer);
self_wizard->mana -= mana_to_use;
target->recieve_damage(target, damage_to_deal);
}
void wizard_rest(struct entity_interface** self) {
struct wizard* self_wizard = (struct wizard*)self;
self_wizard->entity_base.health++;
self_wizard->mana += 7;
}
struct wolf_class {
struct entity_interface super;
int bite_cost; // bite_cost > scratch_cost
int scratch_cost;
};
struct wolf {
struct entity_base_class entity_base_class;
int stamina;
int bite_damage;
int scratch_damage;
double stamina_damage_absorbtion_factor;
};
void wolf_recieve_damage(struct entity_interface** self, int damage) {
struct wolf* self_wolf = (struct wolf*)self;
int stamina_reduction = (int)((double)damage*stamina_damage_absorbtion_factor);
int health_reduction = damage - stamina_reduction;
self_wolf->stamina -= stamina_reduction;
entity_base_recieve_damage(self, health_reduction);
}
void wolf_attack(struct entity_interface** self, struct entity_interface** other) {
struct wolf* self_wolf = (struct wolf*)self;
int attack_damage;
int attack_cost;
int other_health = (*other)->get_health(other);
if(self_wolf->stamina < (struct wolf_class*)(self_wolf->entity_base.v_table)->scratch_cost) {
// You don't have enough stamina to do an attack.
return;
}
if(other_health < self_wolf->scratch_damage ||
self_wolf->stamina < (struct wolf_class*)(self_wolf->entity_base.v_table)->bite_cost ||
(random() % 6 == 0)) {
attack_damage = self->wolf->scratch_damage;
attack_cost = (struct wolf_class*)(self->entity_base.v_table)->scratch_cost;
} else {
attack_damage = self->wolf->bite_damage;
attack_cost = (struct wolf_class*)(self->entity_base.v_table)->bite_cost;
}
self_wolf->stamina -= attack_cost;
(*other)->recieve_damage(other, attack_damage);
}
void wolf_rest(struct entity_interface** self) {
struct wolf* self_wolf = (struct wolf*)self;
self_wolf->entity_base.health += 4;
self_wolf->stamina += 11;
}
static struct entity_interface wizard_class = {
entity_base_get_health,
entity_base_recieve_damage,
wizard_attack,
wizard_rest
};
static struct wolf_class wolf_class {
{entity_base_get_health,
wolf_recieve_damage,
wolf_attack},
10, // scratch cost
20 // bite cost
};
void wizard_init(struct wizard* self, int health, int mana, double magic_damage_multiplyer) {
self->entity_base.v_table = &wizard_class;
self->entity_base.health = health;
self->mana = mana;
self->magic_damage_multiplyer = magic_damage_multiplyer;
}
void wolf_init(struct wolf* self, int health, int stamina, int scratch_damage, int bite_damage) {
self->entity_base.v_table = (struct entity_interface*)&wolf_class;
self->entity_base.health = health;
self->stamina = stamina;
self->scratch_damage = scratch_damage;
self->bite_damage = bite_damage;
}
// A generic function taking an argument that implements
// the interface..
int is_alive(struct entity_interface** self) {
return (*self)->get_health(self) > 0;
}
void main() {
struct wizard wizard;
struct wolf wolf;
wizard_init(&wizard, 100, 50, .7);
wolf_init(&wolf, 100, 200, 10, 18);
for(;;) {
if(!is_alive((struct entity_interface**)&wizard)) {
printf("the wizard died.\n");
break;
}
// wizard_attack(&wizard, &wolf); // This call would avoid the v table look up overhead.
(*((struct entity_interface**)&wizard))->attack(&wizard, &wolf); // Using the v table.
if(!is_alive((struct entity_interface**)&wolf)) {
printf("the wolf died.\n");
break;
}
(*((struct entity_interface**)&wolf))->attack((struct entity_interface**)&wolf, (struct entity_interface**)&wizard);
}
}