1 #include <stdlib.h>
2 
3 #include "types.h"
4 #include "util.h"
5 
6 #include "Bill.h"
7 #include "Computer.h"
8 #include "Game.h"
9 #include "Horde.h"
10 #include "Network.h"
11 #include "UI.h"
12 
13 static Bill *alive, *strays;
14 static int counters[HORDE_COUNTER_MAX + 1];
15 
16 #define MAX_BILLS 100		/* max Bills per level */
17 
18 #define UNLINK(bill, list)						\
19 	do {							\
20 		if ((bill)->next != NULL)			\
21 			(bill)->next->prev = (bill)->prev;	\
22 		if ((bill)->prev != NULL)			\
23 			(bill)->prev->next = (bill)->next;	\
24 		else if ((bill) == list)			\
25 			(list) = (bill)->next;			\
26 		(bill)->prev = NULL;				\
27 		(bill)->next = NULL;				\
28 	} while (0)
29 
30 #define PREPEND(bill, list)					\
31 	do {							\
32 		(bill)->next = (list);				\
33 		if ((list) != NULL)				\
34 			(list)->prev = (bill);			\
35 		(list) = (bill);				\
36 	} while (0)
37 
38 static int
on(unsigned int lev)39 on(unsigned int lev) {
40 	int perlevel = (int)((8 + 3 * lev) * Game_scale(2));
41 	return MIN(perlevel, MAX_BILLS);
42 }
43 
44 static int
max_at_once(unsigned int lev)45 max_at_once(unsigned int lev) {
46 	return MIN(2 + lev / 4, 12);
47 }
48 
49 static int
between(unsigned int lev)50 between(unsigned int lev) {
51 	return MAX(14 - lev / 3, 10);
52 }
53 
54 /*  Launches Bills whenever called  */
55 static void
launch(int max)56 launch(int max) {
57 	Bill *bill;
58 	int n;
59 	int off_screen = counters[HORDE_COUNTER_OFF];
60 
61 	if (max == 0 || off_screen == 0)
62 		return;
63 	n = RAND(1, MIN(max, off_screen));
64 	for (; n > 0; n--) {
65 		Bill_enter(&bill);
66 		PREPEND(bill, alive);
67 	}
68 }
69 
70 void
Horde_setup()71 Horde_setup() {
72 	Bill *bill;
73 	while (alive != NULL) {
74 		bill = alive;
75 		UNLINK(bill, alive);
76 		free(bill);
77 	}
78 	while (strays != NULL) {
79 		bill = strays;
80 		UNLINK(bill, strays);
81 		free(bill);
82 	}
83 	counters[HORDE_COUNTER_OFF] = on(Game_level());
84 	counters[HORDE_COUNTER_ON] = 0;
85 }
86 
87 void
Horde_update(int iteration)88 Horde_update(int iteration) {
89 	Bill *bill, *next;
90 	int level = Game_level();
91 	if (iteration % between(level) == 0)
92 		launch(max_at_once(level));
93 	for (bill = alive; bill != NULL; bill = next) {
94 		next = bill->next;
95 		Bill_update(bill);
96 	}
97 }
98 
99 void
Horde_draw()100 Horde_draw() {
101 	Bill *bill;
102 
103 	for (bill = strays; bill != NULL; bill = bill->next)
104 		Bill_draw(bill);
105 	for (bill = alive; bill != NULL; bill = bill->next)
106 		Bill_draw(bill);
107 }
108 
109 void
Horde_move_bill(Bill * bill)110 Horde_move_bill(Bill *bill) {
111 	UNLINK(bill, alive);
112 	PREPEND(bill, strays);
113 }
114 
115 void
Horde_remove_bill(Bill * bill)116 Horde_remove_bill(Bill *bill) {
117 	if (bill->state == BILL_STATE_STRAY)
118 		UNLINK(bill, strays);
119 	else
120 		UNLINK(bill, alive);
121 	Network_clear_stray(bill);
122 	free(bill);
123 }
124 
125 void
Horde_add_bill(Bill * bill)126 Horde_add_bill(Bill *bill) {
127 	if (bill->state == BILL_STATE_STRAY)
128 		PREPEND(bill, strays);
129 	else
130 		PREPEND(bill, alive);
131 }
132 
133 Bill *
Horde_clicked_stray(int x,int y)134 Horde_clicked_stray(int x, int y) {
135 	Bill *bill;
136 
137 	for (bill = strays; bill != NULL; bill = bill->next) {
138 		if (!Bill_clickedstray(bill, x, y))
139 			continue;
140 		UNLINK(bill, strays);
141 		return bill;
142 	}
143 	return NULL;
144 }
145 
146 int
Horde_process_click(int x,int y)147 Horde_process_click(int x, int y) {
148 	Bill *bill;
149 	int counter = 0;
150 
151 	for (bill = alive; bill != NULL; bill = bill->next) {
152 		if (bill->state == BILL_STATE_DYING ||
153 		    !Bill_clicked(bill, x, y))
154 			continue;
155 		if (bill->state == BILL_STATE_AT) {
156 			Computer *comp;
157 			comp = Network_get_computer(bill->target_c);
158 			comp->busy = 0;
159 			comp->stray = bill;
160 		}
161 		Bill_set_dying(bill);
162        		counter++;
163 	}
164 	return counter;
165 }
166 
167 void
Horde_inc_counter(int counter,int val)168 Horde_inc_counter(int counter, int val) {
169 	counters[counter] += val;
170 }
171 
172 int
Horde_get_counter(int counter)173 Horde_get_counter(int counter) {
174 	return counters[counter];
175 }
176