1 /* Pioneers - Implementation of the excellent Settlers of Catan board game.
2  *   Go buy a copy.
3  *
4  * Copyright (C) 1999 Dave Cole
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "config.h"
22 #include <math.h>
23 #include <ctype.h>
24 #include <string.h>
25 
26 #include <glib.h>
27 
28 #include "game.h"
29 #include "quoteinfo.h"
30 
quotelist_new(QuoteList ** list)31 void quotelist_new(QuoteList ** list)
32 {
33 	g_assert(*list == NULL);
34 	quotelist_free(list);
35 	*list = g_malloc0(sizeof(**list));
36 }
37 
quotelist_free(QuoteList ** list)38 void quotelist_free(QuoteList ** list)
39 {
40 	if (*list == NULL)
41 		return;		/* Already free */
42 	while ((*list)->quotes != NULL) {
43 		QuoteInfo *quote = (*list)->quotes->data;
44 		(*list)->quotes = g_list_remove((*list)->quotes, quote);
45 		g_free(quote);
46 	}
47 	g_free(*list);
48 	*list = NULL;
49 }
50 
sort_quotes(QuoteInfo * a,QuoteInfo * b)51 static gint sort_quotes(QuoteInfo * a, QuoteInfo * b)
52 {
53 	gint res;
54 
55 	res = a->is_domestic - b->is_domestic;
56 	if (res != 0)
57 		return res;
58 	if (a->is_domestic) {
59 		res = a->var.d.player_num - b->var.d.player_num;
60 		if (res != 0)
61 			return res;
62 		return a->var.d.quote_num - b->var.d.quote_num;
63 	}
64 	res = a->var.m.ratio - b->var.m.ratio;
65 	if (res != 0)
66 		return res;
67 	res = (gint) a->var.m.receive - (gint) b->var.m.receive;
68 	if (res != 0)
69 		return res;
70 	return (gint) a->var.m.supply - (gint) b->var.m.supply;
71 }
72 
quotelist_add_maritime(QuoteList * list,gint ratio,Resource supply,Resource receive)73 QuoteInfo *quotelist_add_maritime(QuoteList * list,
74 				  gint ratio, Resource supply,
75 				  Resource receive)
76 {
77 	QuoteInfo *quote;
78 
79 	quote = g_malloc0(sizeof(*quote));
80 	quote->is_domestic = FALSE;
81 	quote->var.m.ratio = ratio;
82 	quote->var.m.supply = supply;
83 	quote->var.m.receive = receive;
84 
85 	list->quotes = g_list_insert_sorted(list->quotes, quote,
86 					    (GCompareFunc) sort_quotes);
87 	quote->list = g_list_find(list->quotes, quote);
88 
89 	return quote;
90 }
91 
quotelist_add_domestic(QuoteList * list,gint player_num,gint quote_num,const gint * supply,const gint * receive)92 QuoteInfo *quotelist_add_domestic(QuoteList * list, gint player_num,
93 				  gint quote_num, const gint * supply,
94 				  const gint * receive)
95 {
96 	QuoteInfo *quote;
97 
98 	quote = g_malloc0(sizeof(*quote));
99 	quote->is_domestic = TRUE;
100 	quote->var.d.player_num = player_num;
101 	quote->var.d.quote_num = quote_num;
102 	memcpy(quote->var.d.supply, supply, sizeof(quote->var.d.supply));
103 	memcpy(quote->var.d.receive, receive,
104 	       sizeof(quote->var.d.receive));
105 
106 	list->quotes = g_list_insert_sorted(list->quotes, quote,
107 					    (GCompareFunc) sort_quotes);
108 	quote->list = g_list_find(list->quotes, quote);
109 
110 	return quote;
111 }
112 
quotelist_find_domestic(QuoteList * list,gint player_num,gint quote_num)113 QuoteInfo *quotelist_find_domestic(QuoteList * list, gint player_num,
114 				   gint quote_num)
115 {
116 	GList *scan;
117 
118 	for (scan = list->quotes; scan != NULL; scan = g_list_next(scan)) {
119 		QuoteInfo *quote = scan->data;
120 
121 		if (!quote->is_domestic)
122 			continue;
123 		if (quote->var.d.player_num != player_num)
124 			continue;
125 		if (quote->var.d.quote_num == quote_num || quote_num < 0)
126 			return quote;
127 	}
128 
129 	return NULL;
130 }
131 
quotelist_first(QuoteList * list)132 QuoteInfo *quotelist_first(QuoteList * list)
133 {
134 	if (list == NULL || list->quotes == NULL)
135 		return NULL;
136 	return list->quotes->data;
137 }
138 
quotelist_prev(const QuoteInfo * quote)139 QuoteInfo *quotelist_prev(const QuoteInfo * quote)
140 {
141 	GList *list = g_list_previous(quote->list);
142 
143 	if (list == NULL)
144 		return NULL;
145 	return list->data;
146 }
147 
quotelist_next(const QuoteInfo * quote)148 QuoteInfo *quotelist_next(const QuoteInfo * quote)
149 {
150 	GList *list = g_list_next(quote->list);
151 
152 	if (list == NULL)
153 		return NULL;
154 	return list->data;
155 }
156 
quotelist_is_player_first(const QuoteInfo * quote)157 gboolean quotelist_is_player_first(const QuoteInfo * quote)
158 {
159 	const QuoteInfo *prev = quotelist_prev(quote);
160 	return prev == NULL
161 	    || !prev->is_domestic
162 	    || prev->var.d.player_num != quote->var.d.player_num;
163 }
164 
quotelist_delete(QuoteList * list,QuoteInfo * quote)165 void quotelist_delete(QuoteList * list, QuoteInfo * quote)
166 {
167 	GList *scan;
168 
169 	for (scan = list->quotes; scan != NULL; scan = g_list_next(scan)) {
170 		if (scan->data == quote) {
171 			list->quotes =
172 			    g_list_remove_link(list->quotes, scan);
173 			g_list_free_1(scan);
174 			g_free(quote);
175 			return;
176 		}
177 	}
178 }
179