/* ** Scan over keys equal to the partitioning element instead of ** stopping the scans when we encounter them. */ int partition(item_t *array,int left,int right) { item_t v=array[right]; int i,j; i=left-1; j=right; while(1){ while(compare_item(array[++i],v)<=0) if(i==right) break; while(compare_item(array[--j],v)>=0){ if(j==left) break; } if(i>=j) break; swap_item(&array[i],&array[j]); } swap_item(&array[i],&array[right]); return(i); }
void min_heapify(int heapsize, int i) { int min = i; int left = LEFT_CLD(i); int right = RIGHT_CLD(i); if(left<heapsize && compare_item(queue+min, queue+left)>0) min = left; if(right<heapsize && compare_item(queue+min, queue+right)>0) min = right; if(min != i) { swap(i, min); min_heapify(heapsize, min); } }
static pqueue_link_t do_pqueue_construct(item_t *array,int left,int right) { pqueue_link_t r; int middle=(left+right)/2; item_t max_item; r=malloc(sizeof(*r)); r->left=NULL; r->right=NULL; if(right==left){ r->item=array[left]; return(r); } r->left=do_pqueue_construct(array,left,middle); r->right=do_pqueue_construct(array,middle+1,right); copy_item(&max_item,&r->left->item); if(compare_item(r->right->item,max_item)>0){ copy_item(&max_item,&r->right->item); } copy_item(&r->item,&max_item); return(r); }
void merge(item_t *a,int left,int middle,int right) { int n=right-left+1; item_t *aux=malloc(n*sizeof(*aux)); int i,j,k; for(k=0,i=left; i<=middle; i++) { aux[k++]=a[i]; } for(i=right; i>middle; i--) { aux[k++]=a[i]; } for(i=0,j=n-1,k=left; k<=right; k++) { /* ** When aux[i]==aux[j], considering the aux[i] first can ** make the merge stable. */ if(compare_item(aux[i],aux[j])<=0) { a[k]=aux[i++]; } else { a[k]=aux[j--]; } } free(aux); }
/* ** This heap_select function selects the kth largest element from ** the array. The idea is building a priority queue of size k at ** the right end of the array. Then do N-k replace_the_minimum (insert ** followed by delete_the_minimum) operations, so the k largest of the ** N elements of the array will be left in the heap-based priority queue. ** (You can prove this idea by yourself.) So the smallest element in ** the priority queue is the kth largest element of the whole array, that ** is, heap[1] in the minimum-oriented heap. */ item_t heap_select(item_t *array,int left,int right,int k) { item_t *heap=array+right-k; int i; /* ** Construct a heap-based priority queue of size k. */ for(i=k/2;i>=1;i--){ heapify_top_down_min(heap,i,k); } /* ** Do N-k replace_the_minimum operations, while N==right-left+1. */ for(i=right-k;i>=left;i--){ if(compare_item(array[i],heap[1])<=0){ continue; } swap_item(&array[i],&heap[1]); heapify_top_down_min(heap,1,k); } return(heap[1]); }
/* ** To restore the heap condition when a node's priority is decreased, we ** move down the heap, exchanging the node at position k with the largest ** of that node's two children if necessary and stopping when the node at ** k is not smaller then either child or the bottom is reached. Note that ** if n is even and k is n/2, then the node at k has only one child -- this ** case must be treated properly. */ void heapify_top_down(item_t *heap,int k,int n) { int j; while(2*k<=n){ j=2*k; if(j+1<=n && compare_item(heap[j+1],heap[j])>0){ j++; } if(compare_item(heap[k],heap[j])>=0){ break; } swap_item(&heap[k],&heap[j]); k=j; } }
int partition_three_way(item_t *array,int left,int right) { int i,j,k,l,p,q; item_t v=array[right]; if(right-left+1 <= 1){ return; } i=left; j=right-1; p=left-1; q=right; while(1){ for(;compare_item(array[i],v)<0;i++) ; for(;compare_item(array[j],v)>0;j--) if(j==left) break; if(i>=j) break; swap_item(&array[i],&array[j]); if(compare_item(array[i],v)==0){ swap_item(&array[i++],&array[++p]); } if(compare_item(array[j],v)==0){ swap_item(&array[j--],&array[--q]); } } if(i==j && compare_item(array[i],v)==0){ swap_item(&array[i++],&array[++p]); } for(k=left;k<=p;k++,j--){ swap_item(&array[k],&array[j]); } for(l=j,k=right;k>=q;k--,i++){ swap_item(&array[k],&array[i]); } return(l); }
int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) { struct item_data *data; int i; nullpo_retr(1, sd); nullpo_retr(1, stor); nullpo_retr(1, item_data); if(item_data->nameid <= 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time || item_data->bound ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if( sd->state.secure_items ) { clif_displaymessage(sd->fd, "You can't store items on Guild Storage. Blocked with @security"); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_GUILD_STORAGE;i++){ if(compare_item(&stor->items[i], item_data)) { if(stor->items[i].amount+amount > MAX_AMOUNT) return 1; stor->items[i].amount+=amount; clif_storageitemadded(sd,&stor->items[i],i,amount); stor->dirty = 1; if(log_config.enable_logs&0x1000) log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, 0); return 0; } } } //Add item for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++); if(i>=MAX_GUILD_STORAGE) return 1; memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->items[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updateguildstorageamount(sd,stor->storage_amount); stor->dirty = 1; if(log_config.enable_logs&0x1000) log_pick_pc(sd, "G", item_data->nameid, -amount, item_data, item_data->serial ); return 0; }
/** * Attempt to add an item in guild storage, then refresh it * @param sd : player attempting to open the guild_storage * @param stor : guild_storage * @param item_data : item to add * @param amount : number of item to add * @return 0 : success, 1 : fail */ char guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount) { struct item_data *data; int i; nullpo_retr(1, sd); nullpo_retr(1, stor); nullpo_retr(1, item_data); if(item_data->nameid == 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if( data->stack.guildstorage && amount > data->stack.amount ) {// item stack limitation return 1; } if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(sd,264)); return 1; } if( (item_data->bound == BOUND_ACCOUNT || item_data->bound > BOUND_GUILD) && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,294)); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_GUILD_STORAGE;i++){ if(compare_item(&stor->items[i], item_data)) { if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount+=amount; clif_storageitemadded(sd,&stor->items[i],i,amount); stor->dirty = 1; return 0; } } } //Add item for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++); if(i>=MAX_GUILD_STORAGE) return 1; memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->items[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); stor->dirty = 1; return 0; }
/** * Make a player add an item to his storage * @param sd : player * @param item_data : item to add * @param amount : quantity of items * @return 0:success, 1:failed */ static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount) { struct storage_data* stor = &sd->status.storage; struct item_data *data; int i; if( item_data->nameid == 0 || amount <= 0 ) return 1; data = itemdb_search(item_data->nameid); if( data->stack.storage && amount > data->stack.amount ) {// item stack limitation return 1; } if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(sd,264)); return 1; } if( (item_data->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) { clif_displaymessage(sd->fd, msg_txt(sd,294)); return 1; } if( itemdb_isstackable2(data) ) {//Stackable for( i = 0; i < sd->storage_size; i++ ) { if( compare_item(&stor->items[i], item_data) ) {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount += amount; clif_storageitemadded(sd,&stor->items[i],i,amount); return 0; } } } // find free slot ARR_FIND( 0, sd->storage_size, i, stor->items[i].nameid == 0 ); if( i >= sd->storage_size ) return 1; // add item to slot memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd, stor->storage_amount, sd->storage_size); return 0; }
void insertion_sort(item_t *array,int left,int right) { int i,j; item_t temp; for(i=left+1; i<=right; i++) if(compare_item(array[i],array[left]) < 0) swap_item(&array[i],&array[left]); for(i=left+2; i<=right; i++) { temp=array[i]; for(j=i-1; compare_item(array[j],temp) > 0; j--) { array[j+1]=array[j]; } array[j+1]=temp; } }
/* ** An abstract in-place merge that uses extra space equal to ** the size of the smaller of the two arrays to be merged. */ void merge(item_t *a,int left,int middle,int right) { int m=middle-left+1; int n=right-middle; item_t *aux; int i,j,k; /* ** Dynamically allocate the auxiliary array whose size is ** equal to the size of the smaller of the two subfiles. ** Then copy the smaller subfile to the array aux in reverse ** order, move another subfile backward to the end of the array a. */ if(m<=n){ aux=malloc(m*sizeof(*aux)); for(k=0;k<m;k++){ aux[k]=a[middle-k]; } i=m-1; j=middle+1; }else{ aux=malloc(n*sizeof(*aux)); for(k=0;k<n;k++){ aux[k]=a[right-k]; } for(j=right,k=middle;k>=left;k--){ a[j--]=a[k]; } i=n-1; j=right+1-m; } /* ** Merge the two subfiles, leaving the result in array a. */ for(k=left;k<=right;k++){ if(i==-1){ a[k]=a[j++]; continue; } if(j==right+1){ a[k]=aux[i--]; continue; } if(compare_item(aux[i],a[j])<0){ a[k]=aux[i--]; }else{ a[k]=a[j++]; } } free(aux); }
/* ** The Floyd's improvement of heapify_top_down. The main idea is avoiding ** the check for whether the element has reached its position, simply ** promoting the larger of the two children until the bottom is reached, ** then moving back up the heap to the proper position. */ void heapify_top_down(item_t *heap,int k,int n) { int i,j; while(3*k-1<=n){ j=3*k-1; i=j+2; if(j+1<=n && (count_comp++,compare_item(heap[j+1],heap[j]))>0){ j++; } if(i<=n && (count_comp++,compare_item(heap[i],heap[j]))>0){ j=i; } swap_item(&heap[k],&heap[j]); k=j; } heapify_bottom_up(heap,k); }
/*========================================== * Internal add-item function. *------------------------------------------*/ static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount, int flag) { struct storage_data* stor = &sd->status.storage; struct item_data *data; int i; if( item_data->nameid <= 0 || amount <= 0 ) return 1; data = itemdb_search(item_data->nameid); if( !itemdb_canstore(item_data, pc_isGM(sd)) ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if( itemdb_isstackable2(data) ) {//Stackable for( i = 0; i < MAX_STORAGE; i++ ) { if( compare_item(&stor->items[i], item_data) ) {// existing items found, stack them if( amount > MAX_AMOUNT - stor->items[i].amount ) return 1; stor->items[i].amount += amount; if( flag ) clif_storageitemadded(sd,&stor->items[i],i,amount); if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, 0); return 0; } } } // find free slot ARR_FIND( 0, MAX_STORAGE, i, stor->items[i].nameid == 0 ); if( i >= MAX_STORAGE ) return 1; // add item to slot memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; if( flag ) { clif_storageitemadded(sd,&stor->items[i],i,amount); clif_updatestorageamount(sd,stor->storage_amount); } if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data, item_data->serial ); return 0; }
void up_heapify(int from) { int cld, pt; cld = from; pt = PARENT(cld); while(cld>0 && compare_item(queue+cld, queue+pt)<0) { swap(cld, pt); cld = pt; pt = PARENT(cld); } }
item_t pqueue_del_max(void) { int i,max; for(max=0,i=1;i<N;i++){ if(compare_item(pq[i],pq[max])>0){ max=i; } } swap_item(&pq[max],&pq[N-1]); return(pq[--N]); }
/* ** This function joins two equal-size 2-power heaps into one. We need to change ** only a few links to combine two equal-sized 2-power heaps into onde 2-power ** heap that is twice the size of the original size. This pair_2_power_heap procedure ** is one key to the efficiency of the binomial queue algorithm. */ pqueue_link_t pair_2_power_heap(pqueue_link_t roota,pqueue_link_t rootb) { if(compare_item(roota->item,rootb->item)>0) { rootb->right=roota->left; roota->left=rootb; return(roota); } else { roota->right=rootb->left; rootb->left=roota; return(rootb); } }
int check_sorted_array(item_t *array,int left,int right) { int i; for(i=left;i<right;i++){ if(compare_item(array[i],array[i+1])>0) break; } if(i==right) return(1); return(0); }
/* ** Partition function without using a break statement. */ int partition(item_t *array,int left,int right) { item_t v=array[right]; int i,j; for(i=left;compare_item(array[i],v)<0;i++) ; for(j=right-1;j>=left && compare_item(array[j],v)>0;j--) ; while(i<j){ swap_item(&array[i],&array[j]); for(;compare_item(array[i],v)<0;i++) ; for(;j>=left && compare_item(array[j],v)>0;j--) ; } swap_item(&array[i],&array[right]); return(i); }
/*========================================== * Internal add-item function. *------------------------------------------ */ static int storage_additem(struct map_session_data *sd,struct storage *stor,struct item *item_data,int amount) { struct item_data *data; int i; if (sd->state.finalsave) return 1; if(item_data->nameid <= 0 || amount <= 0) return 1; data = itemdb_search(item_data->nameid); if (!itemdb_canstore(item_data, pc_isGM(sd))) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; } if(itemdb_isstackable2(data)){ //Stackable for(i=0;i<MAX_STORAGE;i++){ if( compare_item (&stor->storage_[i], item_data)) { if(amount > MAX_AMOUNT - stor->storage_[i].amount) return 1; stor->storage_[i].amount+=amount; clif_storageitemadded(sd,stor,i,amount); stor->dirty = 1; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); return 0; } } } //Add item for(i=0;i<MAX_STORAGE && stor->storage_[i].nameid;i++); if(i>=MAX_STORAGE) return 1; memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); stor->storage_[i].amount=amount; stor->storage_amount++; clif_storageitemadded(sd,stor,i,amount); clif_updatestorageamount(sd,stor); stor->dirty = 1; if(log_config.enable_logs&0x800) log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); return 0; }
void sort_array(item_t *array,int left,int right) { int i,j; item_t temp; for(i=left+1;i<=right;i++){ temp=array[i]; for(j=i-1;j>=left && compare_item(array[j],temp)>0;j--){ array[j+1]=array[j]; } array[j+1]=temp; } }
static pqueue_link_t do_pqueue_del_max(pqueue_link_t r) { item_t max_item; pqueue_link_t t; if(r->left==NULL && r->right==NULL){ free(r); return(NULL); } if(compare_item(r->left->item,r->item)==0){ r->left=do_pqueue_del_max(r->left); if(r->left==NULL){ t=r->right; free(r); return(t); } }else{ r->right=do_pqueue_del_max(r->right); if(r->right==NULL){ t=r->left; free(r); return(t); } } copy_item(&max_item,&r->left->item); if(compare_item(r->right->item,max_item)>0){ copy_item(&max_item,&r->right->item); } copy_item(&r->item,&max_item); return(r); }
void selection_sort(item_t *array,int left,int right) { int i,j; int min; for(i=left;i<right;i++){ min=i; for(j=i+1;j<=right;j++){ if(compare_item(array[j],array[min]) < 0){ min=j; } } swap_item(&array[i],&array[min]); } }
void merge(item_t *a,int left,int middle,int right) { int m=middle-left+1; int n=right-middle; item_t *aux; int i,j,k; if(m<=n){ aux=malloc(m*sizeof(*aux)); for(k=0;k<m;k++){ aux[k]=a[middle-k]; } i=m-1; j=middle+1; }else{ aux=malloc(n*sizeof(*aux)); for(k=0;k<n;k++){ aux[k]=a[right-k]; } for(j=right,k=middle;k>=left;k--){ a[j--]=a[k]; } i=n-1; j=right+1-m; } for(k=left;k<=right;k++){ if(i==-1){ a[k]=a[j++]; continue; } if(j==right+1){ a[k]=aux[i--]; continue; } if(compare_item(aux[i],a[j])<0){ a[k]=aux[i--]; }else{ a[k]=a[j++]; } } free(aux); }
void merge_ab(item_t *c,item_t *a,int m,item_t *b,int n) { int i,j,k; for(i=0,j=0,k=0;k<m+n;k++){ if(i==m){ c[k]=b[j++]; continue; } if(j==n){ c[k]=a[i++]; continue; } if(compare_item(a[i],b[j])<0){ c[k]=a[i++]; }else{ c[k]=b[j++]; } } }
/** * Attempt to add an item in guild storage, then refresh i * @param stor : guild_storage * @param item : item to add * @param amount : number of item to add * @return True : success, False : fail */ bool gstorage_additem2(struct guild_storage *stor, struct item* item, int amount) { struct item_data *id; int i; nullpo_retr(false, stor); nullpo_retr(false, item); if (item->nameid == 0 || amount <= 0 || !(id = itemdb_exists(item->nameid))) return false; if (item->expire_time) return false; if (itemdb_isstackable2(id)) { //Stackable for (i = 0; i < MAX_GUILD_STORAGE; i++) { if (compare_item(&stor->items[i], item)) { //Set the amount, make it fit with max amount amount = min(amount, ((id->stack.guildstorage) ? id->stack.amount : MAX_AMOUNT) - stor->items[i].amount); if (amount != item->amount) ShowWarning("gstorage_additem2: Stack limit reached! Altered amount of item \""CL_WHITE"%s"CL_RESET"\" (%d). '"CL_WHITE"%d"CL_RESET"' -> '"CL_WHITE"%d"CL_RESET"'.\n", id->name, id->nameid, item->amount, amount); stor->items[i].amount += amount; stor->dirty = true; return true; } } } //Add the item for (i = 0; i < MAX_GUILD_STORAGE && stor->items[i].nameid; i++); if (i >= MAX_GUILD_STORAGE) return false; memcpy(&stor->items[i], item, sizeof(stor->items[0])); stor->items[i].amount = amount; stor->storage_amount++; stor->dirty = true; return true; }
link_t merge_list(link_t heada,link_t headb) { link_t c,t; link_t head=malloc(sizeof(*head)); c=head; c->next=NULL; while(heada!=NULL && headb!=NULL){ if(compare_item(heada->item,headb->item)<=0){ t=heada; heada=t->next; t->next=NULL; c->next=t; c=t; }else{ t=headb; headb=t->next; t->next=NULL; c->next=t; c=t; } } if(heada==NULL){ c->next=headb; }else{ c->next=heada; } t=head; head=head->next; free(t); return(head); }
void heapify_bottom_up(item_t *heap,int k) { for(;k>1 && compare_item(heap[k],heap[(k+1)/3])>0;k=(k+1)/3){ swap_item(&heap[k],&heap[(k+1)/3]); } }
static void heapify_bottom_up(item_t *heap,int k) { for(;k>1 && compare_item(heap[k],heap[k/2])>0;k=k/2){ swap_item(&heap[k],&heap[k/2]); } }
/* ** The implementation of top-down quicksort of linked list pointed to ** by head. First take out the first node from the list head, save as ** current. Partition the whole file into two sublists, one sublist save ** the elements smaller than current->item, pointed to by head1. Another ** sublist head2, holds the elements larger than or equal to current->item. ** Call recursively quicksort_list to sort each of the two sublists. Then ** merge them with current to make the whole list sorted. */ link_t quicksort_list(link_t head) { link_t head1,tail1; link_t head2,tail2; link_t current,t; if(head==NULL || head->next==NULL){ return(head); } current=head; head=head->next; current->next=NULL; /* ** Partition the list into two subfiles. */ head1=tail1=NULL; head2=tail2=NULL; while(head!=NULL){ t=head; head=head->next; t->next=NULL; if(compare_item(t->item,current->item)<0){ if(tail1==NULL){ head1=tail1=t; }else{ tail1->next=t; tail1=t; } }else{ if(tail2==NULL){ head2=tail2=t; }else{ tail2->next=t; tail2=t; } } } head1=quicksort_list(head1); head2=quicksort_list(head2); /* ** This is a point you may ignore. After the recursive quicksort_list ** call above, the pointer tail1 may not point to the tail of the sublist ** head1. So you should traverse the sublist head1 to make sure tail1 points ** to its tail. */ for(tail1=head1;tail1!=NULL && tail1->next!=NULL;tail1=tail1->next); ; /* ** Merge the two subfiles head1, head2 with current. */ if(tail1 != NULL){ tail1->next=current; current->next=head2; head=head1; }else{ current->next=head2; head=current; } return(head); }