3 #include "libs/binaryheap/binhl.h"
5 /* Define this to get lots of _printf's */
6 //#define DEBUG_MANA_POOLS
8 /* DYNAMIC POOLS are pools that are managed in real-time, i.e. pools that can
9 split into two and join together. STATIC POOLS are re-built each game turn
10 from the linked list information. DYNAMIC POOLS are buggy/don't work properly.
11 So I'm sticking with STATIC POOLS for now. They are easier to work with too. */
12 /* #define DYNAMIC_POOLS */
14 #ifdef DEBUG_MANA_POOLS
15 #define _printf(...) fprintf (stdout, __VA_ARGS__)
17 #define _printf(...) { }
23 extern unit_t units
[MAX_UNITS
];
24 extern pool_t pools
[MAX_POOLS
];
26 int create_pool(int id1
, int id2
, Uint8 stat
) {
28 pool_t
*pool
= &pools
[pid
];
30 unit_t
*u
= &units
[id1
];
31 unit_t
*u2
= &units
[id2
];
38 _printf("CREATED POOL!\n");
44 int is_unit_looped(unit_t
*start
, int stat
) {
46 for (i
= 0; i
< num_units
; i
++) units
[i
].block
= 0;
47 unit_t
*iter
= start
->link
;
49 if (iter
->link_stat
!= stat
) break;
50 if (iter
->block
== 1) break;
51 if (iter
== start
) return 1;
58 void rebuild_pools() {
61 int k
;for (k
= 0; k
< MAX_STAT
; k
++) {
65 binh_list uunits
= { 0 };
66 for (i
= 0; i
< num_units
; i
++) {
68 binhl_push(&uunits
, i
, units
[i
].ref_count
[k
]);
71 _printf("\n Rebuilding mana pools for [%d] (found %d units for it)\n", k
, uunits
.len
);
75 i
= binhl_pop(&uunits
);
76 unit_t
*u
= &units
[i
];
78 printf("Trying unit %s\n", u
->name
);
80 if (u
->pool
) { printf ("Already proc\n"); continue;}//already procesed
81 if (!u
->link
) { printf("no link\n"); continue;}
82 int stat
= u
->link_stat
;
84 if (stat
!= k
) {printf("Wrong stat! %d\n", stat
);continue;}
86 _printf("Following unit %s (count: %d)\n", u
->name
, u
->ref_count
[stat
]);
88 int pid
= create_pool(i
, 0, u
->link_stat
);
90 pool_t
*pool
= &pools
[pid
];
94 int making_open_chain
= !is_unit_looped(u
, stat
);
97 //pif (u->ref_count > 1) return;
99 _printf("Now unit %s\n", u
->name
);
101 if (u
== pool
->tail
) {_printf("1\n");break;}
104 if (making_open_chain
&& is_unit_looped(u
, stat
)) {_printf("2\n");break;}
108 _printf("Adding him to this pool\n");
109 //if (u->link->ref_count > 1) break;
111 if (u
->link_stat
!= stat
) {
113 if (u
->link
) u
->pool
= NULL
;
114 //binhl_push(&uunits, i, 0);
123 printf("Total pools: %d\n", num_pools
);
124 #ifdef DEBUG_MANA_POOLS
126 for (i
= 0; i
< num_pools
; i
++) {
127 pool_t
*pool
= &pools
[i
];
128 unit_t
*iter
= pool
->tail
;
130 _printf("Created pool %p(%d), head -- %s, tail -- %s\n", pool
, i
, (pool
->head
? pool
->head
->name
: "NULL"), (pool
->tail
? pool
->tail
->name
: "NULL"));
132 _printf("Member %d -- %s, linked to %p (%s) pool\n", j
, iter
->name
, iter
->pool
, iter
->pool
== pool
? "THIS" : "OTHER");
133 if (pool
->head
== iter
) break;
141 void add_link(int id1
, int id2
, Uint8 stat
) {
142 unit_t
*u
= &units
[id1
];
143 unit_t
*u2
= &units
[id2
];
151 u2
->ref_count
[stat
]++;
155 #ifdef DYNAMIC_MANA_POOLS
156 add_wtf(id1
, id2
, stat
);
162 void update_stats(int reset
)
166 for (i
= 0; i
< num_units
; i
++) {
168 for (j
= 0; j
< MAX_STAT
; j
++) {
169 units
[i
].rune_stat
[j
] = 0;
174 for (i
= 0; i
< num_units
; i
++) {
175 unit_t
*u
= &units
[i
];
176 for (j
= 0; j
< MAX_STAT
; j
++) {
177 u
->calc_stat
[j
] = u
->base_stat
[j
] + u
->rune_stat
[j
];
178 if (u
->calc_stat
[j
] > 99) u
->calc_stat
[j
] = 99;
184 #define IN_POOL(POOL, UNIT) ((UNIT)->pool == (POOL))
185 #define IS_LOOPED(POOL) ((POOL)->head->link == (POOL)->tail && (POOL)->head->link_stat == (POOL)->stat)
186 #define IS_ADJACENT(POOL) ((POOL)->head->pool != (POOL) && (POOL)->head->pool)
188 void collect_pools() {
193 binh_list kpools
= { 0 }; /* while iterating, collect "adjacent" pools in here */
195 _printf("Collecting energy: \n");
197 for (i
= 0; i
< num_pools
; i
++) {
198 pool_t
*pool
= &pools
[i
];
199 unit_t
*iter
= pool
->tail
;
201 int closed
= IS_LOOPED(pool
);
203 _printf("On unit: %s\n", iter
->name
);
204 if (!closed
&& iter
== pool
->head
) break; /* Do not collect from heads of open chains */
205 pool
->pool
+= iter
->base_stat
[pool
->stat
];
206 iter
->rune_stat
[pool
->stat
] -= iter
->base_stat
[pool
->stat
];
207 if (iter
->ref_count
[pool
->stat
] > rc
) rc
= iter
->ref_count
[pool
->stat
];
208 if (iter
== pool
->head
) break; /* We're now looping in a closed chain */
211 } while (iter
);// && iter->pool == pool);
213 _printf(" pool #%d [%s-%s (%d)] -- collected %d\n",i
, pool
->tail
->name
,pool
->head
->name
, rc
, pool
->pool
);
215 if (IS_ADJACENT(pool
)) binhl_push(&kpools
, i
, rc
);
221 binh_list kpools = { 0 };
223 for (i = 0; i < num_pools; i++) {
224 if (IS_ADJACENT(&pools[i]) binhl_push(&kpools, i, pools[i].tail->ref_count);
227 /* forward adjacent pools */
229 i
= binhl_pop(&kpools
);
231 pool_t
*pool
= &pools
[i
];
233 _printf("Forwarding pool #%d [%s-%s (%d)]\n", i
, pool
->tail
->name
, pool
->head
->name
, pool
->head
->ref_count
[pool
->stat
]);
235 if (pool
->head
->pool
== NULL
) {
236 _printf("Nowhere to forward! :((\n");
240 pool_t
*nextp
= pool
->head
->pool
;
241 nextp
->pool
+= pool
->pool
;
248 void distrib_pools() {
251 // binh_list kpools = { 0 };
252 //for (i = 0; i < num_pools; i++)
253 //binhl_push(&kpools, i, pools[i].tail->ref_count);
255 for (i
= 0; i
< num_pools
; i
++) {
256 // while(kpools.len) {
257 // i = binhl_pop(&kpools);
259 _printf("Distributing pool #%d\n",i
);
261 pool_t
*pool
= &pools
[i
];
263 if (IS_LOOPED(pool
)) { /* Closed chain */
266 binh_list uunits
= { 0 };
267 int num_total
= 0, num_bids
= 0;
268 int large_value
= num_units
* 10; /* using this to invert priority */
270 _printf("Distributing closed chain:\n");
272 unit_t
*iter
= pool
->tail
;
275 int priority
= iter
->stat_bid
[pool
->stat
] + iter
->pin
;
277 _printf("Examining %d=%s (priority: %d, sort: %d)\n", num_total
, iter
->name
, priority
, large_value
- priority
);
279 binhl_push(&uunits
, num_total
++, large_value
- priority
);
281 if (priority
) num_bids
++;
285 } while (iter
!= pool
->tail
);
287 if (num_bids
== 0) num_bids
= num_total
; /* zero bids == everyone */
289 _printf("Picked %d units (of %d) for distribution\n", num_bids
, num_total
);
291 /* Distribute among them */
292 Uint16 share
= pool
->pool
/ num_bids
;
293 Uint16 bonus
= pool
->pool
% num_bids
;
297 int j
= binhl_pop(&uunits
); /* "j" is "offset from tail" */
299 _printf("Need to give to %d=", j
);
301 for (iter
= pool
->tail
; j
> 0; j
--) /* grab a unit using "j" */
303 _printf("%s->", iter
->name
);
307 _printf("\nGiving %d to %s\n", share
, iter
->name
);
308 iter
->rune_stat
[pool
->stat
] += share
;
309 //iter->calc_stat[pool->stat] += share;
312 _printf("Giving extra %d to %s\n", bonus
, iter
->name
);
313 iter
->rune_stat
[pool
->stat
] += bonus
;
314 //iter->calc_stat[pool->stat] += bonus;
316 } else { /* Open chain */
318 /* Just give everything to pool's "head" */
319 pool
->head
->rune_stat
[pool
->stat
] += pool
->pool
;
320 //iter->calc_stat[pool->stat] += pool->pool;
332 void random_links() {
335 Uint8 u
= rand() % num_units
;
338 Uint8 u2
= rand() % num_units
;
354 void add_to_pool(pool_t
*pool
, int id1
, int id2
, Uint8 stat
) {
355 unit_t
*u
= &units
[id1
];
356 unit_t
*u2
= &units
[id2
];
358 if (pool
->head
->link
== u2
) {
359 _printf("Adding to the top\n");
360 //pool->head->pool = pool;
363 } else if (pool
->tail
== u2
) {
364 _printf("Adding to the tail\n");
368 _printf("Adding to the middle\n");
369 create_pool(id1
, id2
, stat
);
373 pool_t
* find_pool(int unit_id
, Uint8 stat
) {
374 unit_t
*iter
= &units
[unit_id
];
376 _printf("Searching for pool..%s\n", iter
->name
);
378 _printf("I have one!");
380 _printf("I don't have one!\n");
381 if (iter
->pool
)// && iter->pool->stat == stat)
383 _printf("Moving to %p\n",iter
->link
);
384 if (iter
->link_stat
== stat
)
390 for (i
=0; i
< num_pools
; i
++) {
391 if (pools
[i
].head
==&units
[unit_id
]
392 && pools
[i
].stat
== stat
) {
393 if (good
) return NULL
;
400 void add_wtf(int id1
, int id2
, Uint8 stat
) {
401 unit_t
*u
= &units
[id1
];
402 unit_t
*u2
= &units
[id2
];
405 pool
= find_pool(id1
, stat
);
408 create_pool(id1
, id2
, stat
);
410 add_to_pool(pool
, id1
, id2
, stat
);
414 unit_t
* find_prev(pool_t
*pool
, unit_t
*who
) {
415 unit_t
*iter
= pool
->tail
;
417 if (iter
->link
== who
) break;
422 pool_t
* clone_pool(pool_t
*pool
) {
424 memcpy(&pools
[pid
], pool
, sizeof(pool_t
));
428 void switch_pool(unit_t
*tail
, unit_t
*border
, pool_t
*new_pool
) {
430 pool_t
*pool
= tail
->pool
;
432 if (iter
->pool
== pool
) iter
->pool
= new_pool
;
433 if (iter
->link
== border
) break;
438 void remove_pool(pool_t
*pool
) {
440 switch_pool(pool
->tail
, pool
->head
, NULL
);
441 for (i
= 0; i
< num_pools
; i
++) {
442 if (&pools
[i
] == pool
) {
443 if (i
< num_pools
-1) {
444 memcpy(&pools
[i
], &pools
[num_pools
], sizeof(pool_t
));
451 void split_pool(pool_t
*pool
, unit_t
*u
) {
453 /* Before we even start the split, let's consider the
455 * o - x - o In this case, we just remove.
456 * o - o - x - o Do not create right hand pool, just CUT
457 * o - x - o - o Mutate left-hand pool
460 /* O - X - O / aka the Trigraph is easy to spot */
461 if (pool
->tail
->link
== u
&& u
->link
== pool
->head
)
463 _printf("It's just a trigraph!\n");
467 /* O - ? - ? - O / ok this is getty lame */
468 if (pool
->tail
->link
&& pool
->tail
->link
->link
&& pool
->tail
->link
->link
->link
== pool
->head
)
470 unit_t
*prev
= find_prev(pool
, u
);
471 if (u
->link
== pool
->head
) {
472 _printf("It's a riftized foragraph!\n");
475 if (pool
->tail
->link
== u
) {
476 _printf("It's a leftized foragrpah...!\n");
477 switch_pool(pool
->tail
, u
, NULL
);
478 pool
->tail
= u
->link
;
485 pool_t
*nextp
= clone_pool(pool
);
486 unit_t
*prev
= find_prev(pool
, u
);
489 nextp
->tail
= u
->link
;
491 if (nextp
->tail
== nextp
->head
) {
492 _printf("Pool is now empty, remove it!\n");
497 unit_t
*mark
= nextp
->tail
;
499 if (mark
->pool
== pool
)
501 if (mark
->link
->link_stat
== u
->link_stat
)/* ??? was mark->link for some reason ??? */
506 if (pool
->tail
== pool
->head
) {
507 _printf("Pool is now empty, remove it!\n");
512 pool_t
* find_Xpool(int unit_id
, Uint8 stat
) {
513 unit_t
*iter
= &units
[unit_id
];
516 _printf("%s links to ...", iter
->name
);
517 if (iter
->link
) _printf("%s ", iter
->link
->name
);
518 _printf(" and has connection to pool %p\n", iter
->pool
);
519 if (iter
->pool
&& iter
->pool
->stat
== stat
)
521 //if (iter->link_stat == stat)
527 for (i
=0; i
< num_pools
; i
++) {
528 if (pools
[i
].head
==&units
[unit_id
]
538 void remove_wtf(int id1
) {
539 unit_t
*u
= &units
[id1
];
542 pool
= find_pool(id1
, u
->link_stat
);
545 _printf("No pool found...\n");
546 pool
= find_Xpool(id1
, u
->link_stat
);
549 _printf("Still no pool!\n");
553 if (pool
->tail
== u
) {
554 _printf("Was at the very very end!\n");
555 pool
->tail
= pool
->tail
->link
;
556 _printf("Shrinking pool\n");
557 if (pool
->tail
== pool
->head
) {
558 _printf("Pool is now empty, remove it!\n");
560 return;//or continue;
563 else if (pool
->head
== u
) {
564 _printf("At the very head!\n");
565 _printf("Fidn me prev...");
567 unit_t
*prev
= find_prev(pool
, u
);
569 if (pool
->tail
== pool
->head
) {
570 _printf("Pool is now empty, remove it!\n");
572 return;//or continue;
578 _printf("HIS POOL %p!\n",pool
);