// юзается исключительно в act.wizards.cpp в имм командах "advance" и "set exp". void gain_exp_regardless(CHAR_DATA * ch, int gain) { int is_altered = FALSE; int num_levels = 0; ch->set_exp(ch->get_exp() + gain); if (!IS_NPC(ch)) { if (gain > 0) { while (GET_LEVEL(ch) < LVL_IMPL && GET_EXP(ch) >= level_exp(ch, GET_LEVEL(ch) + 1)) { ch->set_level(ch->get_level() + 1); num_levels++; sprintf(buf, "%sВы достигли следующего уровня!%s\r\n", CCWHT(ch, C_NRM), CCNRM(ch, C_NRM)); send_to_char(buf, ch); advance_level(ch); is_altered = TRUE; } if (is_altered) { sprintf(buf, "%s advanced %d level%s to level %d.", GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch)); mudlog(buf, BRF, LVL_IMPL, SYSLOG, TRUE); } } else if (gain < 0) { // Pereplut: глупый участок кода. // gain = MAX(-max_exp_loss_pc(ch), gain); // Cap max exp lost per death // GET_EXP(ch) += gain; // if (GET_EXP(ch) < 0) // GET_EXP(ch) = 0; while (GET_LEVEL(ch) > 1 && GET_EXP(ch) < level_exp(ch, GET_LEVEL(ch))) { ch->set_level(ch->get_level() - 1); num_levels++; sprintf(buf, "%sВы потеряли уровень!%s\r\n", CCIRED(ch, C_NRM), CCNRM(ch, C_NRM)); send_to_char(buf, ch); decrease_level(ch); is_altered = TRUE; } if (is_altered) { sprintf(buf, "%s decreases %d level%s to level %d.", GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch)); mudlog(buf, BRF, LVL_IMPL, SYSLOG, TRUE); } } } }
/* * delete_ - recursively delete X in T. * * if X is right at T, right(T) = deleted right(T). * if X is left at T, left(T) = deleted lett(T). * * if X is T, change X and its successor/predecessor * and goto childs. * * after delete, re-balance AA tree. * */ FREE delete_(void* X, FREE T) { FREE P = T; if(!T) return T; else if ((FSIZE(X) > FSIZE(T)) || ((FSIZE(X) == FSIZE(T)) && X > T)) { right(T) = delete_(X, right(T)); } else if (X != T) { left(T) = delete_(X, left(T)); } else { if (!left(T) && !right(T)) { if(!parent(T)) { address_tree = NULL; } else if (left(parent(T)) == T) { left(parent(T)) = NULL; } else { right(parent(T)) = NULL; } return NULL; }else if (!left(T)) { P = change_successor(T); right(P) = delete_(X, right(P)); }else { P = change_predecessor(T); left(P) = delete_(X, left(P)); } } T = P; T = decrease_level(T); T = skew(T); right(T) = skew(right(T)); if(right(T)){ right(right(T)) = skew(right(right(T))); } T = split(T); right(T) = split(right(T)); return T; }
static int bstree_node_remove( bstree bst, unsigned int *node, KEYTYPE key, VALUETYPE *value){ unsigned int swap_node; VALUETYPE tmp; if( *node == NODE_NULL ){ return BSTREE_FAILURE; } if( key == bst->array[*node].key){ *value = bst->array[*node].value; status = BSTREE_SUCCESS; if( bst->array[*node].left == NODE_NULL && bst->array[*node].right == NODE_NULL ){ *node = NODE_NULL; bst->size--; if( ((double) bst->size / (double) bst->array_size) < 0.25 && bst->array_size > MINSIZE ){ if( bstree_shrink( bst) == BSTREE_MEM_ERROR){ return BSTREE_MEM_ERROR; } } return BSTREE_SUCCESS; } if( bst->array[*node].left == NODE_NULL ){ swap_node = successor( bst, *node); bst->array[*node].key = bst->array[swap_node].key; bst->array[*node].value = bst->array[swap_node].value; bstree_node_remove( bst, bst->array[*node].right, bst->array[swap_node].key, &tmp); }else{ swap_node = predecessor( bst, *node); bst->array[*node].key = bst->array[swap_node].key; bst->array[*node].value = bst->array[swap_node].value; bstree_node_remove( bst, bst->array[*node].left, bst->array[swap_node].key, &tmp); } }else if( COMP( key, bst->array[*node].key) < 0 ){ status = bstree_node_remove( bst, &(bst->array[node].left), key, value); }else{ status = bstree_node_insert( bst, &(bst->array[node].right), key, value); } decrease_level( bst, *node); skew( bst, node); if( bst->array[*node].right != NODE_NULL ){ skew( bst, &(bst->array[*node].right)); skew( bst, &(bst->array[bst->array[*node].right].right)); } split( bst, node); split( bst, &(bst->array[*node].right)); return status; }
/// AA tree remove the node static onion_dict_node *onion_dict_node_remove(const onion_dict *d, onion_dict_node *node, const char *key){ if (!node) return NULL; int cmp=d->cmp(key, node->data.key); if (cmp<0){ node->left=onion_dict_node_remove(d, node->left, key); //ONION_DEBUG("%p[%s]->left=%p[%s]",node, node->data.key, node->left, node->left ? node->left->data.key : "NULL"); } else if (cmp>0){ node->right=onion_dict_node_remove(d, node->right, key); //ONION_DEBUG("%p[%s]->right=%p[%s]",node, node->data.key, node->right, node->right ? node->right->data.key : "NULL"); } else{ // Real remove //ONION_DEBUG("Remove here %p", node); onion_dict_node_data_free(&node->data); if (node->left==NULL && node->right==NULL){ onion_low_free(node); return NULL; } if (node->left==NULL){ onion_dict_node *t=node->right; // Get next key node while (t->left) t=t->left; //ONION_DEBUG("Set data from %p[%s] to %p[already deleted %s]",t,t->data.key, node, key); memcpy(&node->data, &t->data, sizeof(onion_dict_node_data)); t->data.flags=0; // No double free later, please node->right=onion_dict_node_remove(d, node->right, t->data.key); //ONION_DEBUG("%p[%s]->right=%p[%s]",node, node->data.key, node->right, node->right ? node->right->data.key : "NULL"); } else{ onion_dict_node *t=node->left; // Get prev key node while (t->right) t=t->right; memcpy(&node->data, &t->data, sizeof(onion_dict_node_data)); t->data.flags=0; // No double free later, please node->left=onion_dict_node_remove(d, node->left, t->data.key); //ONION_DEBUG("%p[%s]->left=%p[%s]",node, node->data.key, node->left, node->left ? node->left->data.key : "NULL"); } } decrease_level(node); node=skew(node); if (node->right){ node->right=skew(node->right); if (node->right->right) node->right->right=skew(node->right->right); } node=split(node); if (node->right) node->right=split(node->right); return node; }
void gain_exp(CHAR_DATA * ch, int gain) { int is_altered = FALSE; int num_levels = 0; char buf[128]; if (IS_NPC(ch)) { ch->set_exp(ch->get_exp() + gain); return; } else { ch->dps_add_exp(gain); ZoneExpStat::add(zone_table[world[IN_ROOM(ch)]->zone].number, gain); } if (!IS_NPC(ch) && ((GET_LEVEL(ch) < 1 || GET_LEVEL(ch) >= LVL_IMMORT))) return; if (gain > 0 && GET_LEVEL(ch) < LVL_IMMORT) { gain = MIN(max_exp_gain_pc(ch), gain); // put a cap on the max gain per kill ch->set_exp(ch->get_exp() + gain); if (GET_EXP(ch) >= level_exp(ch, LVL_IMMORT)) { if (!GET_GOD_FLAG(ch, GF_REMORT) && GET_REMORT(ch) < MAX_REMORT) { if (Remort::can_remort_now(ch)) { send_to_char(ch, "%sПоздравляем, вы получили право на перевоплощение!%s\r\n", CCIGRN(ch, C_NRM), CCNRM(ch, C_NRM)); } else { send_to_char(ch, "%sПоздравляем, вы набрали максимальное количество опыта!\r\n" "%s%s\r\n", CCIGRN(ch, C_NRM), Remort::WHERE_TO_REMORT_STR.c_str(), CCNRM(ch, C_NRM)); } SET_GOD_FLAG(ch, GF_REMORT); } } ch->set_exp(MIN(GET_EXP(ch), level_exp(ch, LVL_IMMORT) - 1)); while (GET_LEVEL(ch) < LVL_IMMORT && GET_EXP(ch) >= level_exp(ch, GET_LEVEL(ch) + 1)) { ch->set_level(ch->get_level() + 1); num_levels++; sprintf(buf, "%sВы достигли следующего уровня!%s\r\n", CCWHT(ch, C_NRM), CCNRM(ch, C_NRM)); send_to_char(buf, ch); advance_level(ch); is_altered = TRUE; } if (is_altered) { sprintf(buf, "%s advanced %d level%s to level %d.", GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch)); mudlog(buf, BRF, LVL_IMPL, SYSLOG, TRUE); } } else if (gain < 0 && GET_LEVEL(ch) < LVL_IMMORT) { gain = MAX(-max_exp_loss_pc(ch), gain); // Cap max exp lost per death ch->set_exp(ch->get_exp() + gain); while (GET_LEVEL(ch) > 1 && GET_EXP(ch) < level_exp(ch, GET_LEVEL(ch))) { ch->set_level(ch->get_level() - 1); num_levels++; sprintf(buf, "%sВы потеряли уровень. Вам должно быть стыдно!%s\r\n", CCIRED(ch, C_NRM), CCNRM(ch, C_NRM)); send_to_char(buf, ch); decrease_level(ch); is_altered = TRUE; } if (is_altered) { sprintf(buf, "%s decreases %d level%s to level %d.", GET_NAME(ch), num_levels, num_levels == 1 ? "" : "s", GET_LEVEL(ch)); mudlog(buf, BRF, LVL_IMPL, SYSLOG, TRUE); } } if ((GET_EXP(ch) < level_exp(ch, LVL_IMMORT) - 1) && GET_GOD_FLAG(ch, GF_REMORT) && gain && (GET_LEVEL(ch) < LVL_IMMORT)) { if (Remort::can_remort_now(ch)) { send_to_char(ch, "%sВы потеряли право на перевоплощение!%s\r\n", CCIRED(ch, C_NRM), CCNRM(ch, C_NRM)); } CLR_GOD_FLAG(ch, GF_REMORT); } char_stat::add_class_exp(GET_CLASS(ch), gain); update_clan_exp(ch, gain); }