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