1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 #ifdef AI_MODULES
19 #include <ltdl.h>
20 #endif
21
22 /* utility */
23 #include "support.h"
24
25 /* common */
26 #include "ai.h"
27 #include "player.h"
28
29 /* server/advisors */
30 #include "autosettlers.h"
31
32 /* ai/classic */
33 #include "classicai.h"
34
35 #include "aiiface.h"
36
37 #ifdef AI_MOD_STATIC_THREADED
38 bool fc_ai_threaded_setup(struct ai_type *ai);
39 #endif
40
41 #ifdef AI_MOD_STATIC_STUB
42 bool fc_ai_stub_setup(struct ai_type *ai);
43 #endif
44
45 static struct ai_type *default_ai = NULL;
46
47 #ifdef AI_MODULES
48 /**************************************************************************
49 Return string describing module loading error. Never returns NULL.
50 **************************************************************************/
fc_module_error(void)51 static const char *fc_module_error(void)
52 {
53 static char def_err[] = "Unknown error";
54 const char *errtxt = lt_dlerror();
55
56 if (errtxt == NULL) {
57 return def_err;
58 }
59
60 return errtxt;
61 }
62
63 /**************************************************************************
64 Load ai module from file.
65 **************************************************************************/
load_ai_module(const char * modname)66 bool load_ai_module(const char *modname)
67 {
68 struct ai_type *ai = ai_type_alloc();
69 bool setup_success;
70 lt_dlhandle handle;
71 bool (*setup_func)(struct ai_type *ai);
72 const char *(*capstr_func)(void);
73 const char *capstr;
74 char buffer[2048];
75 char filename[1024];
76
77 if (ai == NULL) {
78 return FALSE;
79 }
80
81 init_ai(ai);
82
83 fc_snprintf(filename, sizeof(filename), "fc_ai_%s", modname);
84 fc_snprintf(buffer, sizeof(buffer), "%s", filename);
85 handle = lt_dlopenext(buffer);
86 if (handle == NULL) {
87 log_error(_("Cannot open AI module %s (%s)"), filename, fc_module_error());
88 return FALSE;
89 }
90
91 fc_snprintf(buffer, sizeof(buffer), "%s_capstr", filename);
92 capstr_func = lt_dlsym(handle, buffer);
93 if (capstr_func == NULL) {
94 log_error(_("Cannot find capstr function from ai module %s (%s)"),
95 filename, fc_module_error());
96 return FALSE;
97 }
98
99 capstr = capstr_func();
100 if (strcmp(FC_AI_MOD_CAPSTR, capstr)) {
101 log_error(_("Incompatible ai module %s:"), filename);
102 log_error(_(" Module options: %s"), capstr);
103 log_error(_(" Supported options: %s"), FC_AI_MOD_CAPSTR);
104
105 return FALSE;
106 }
107
108 fc_snprintf(buffer, sizeof(buffer), "%s_setup", filename);
109 setup_func = lt_dlsym(handle, buffer);
110 if (setup_func == NULL) {
111 log_error(_("Cannot find setup function from ai module %s (%s)"),
112 filename, fc_module_error());
113 return FALSE;
114 }
115 setup_success = setup_func(ai);
116
117 if (!setup_success) {
118 log_error(_("Setup of ai module %s failed."), filename);
119 return FALSE;
120 }
121
122 return TRUE;
123 }
124 #endif /* AI_MODULES */
125
126 /**************************************************************************
127 Initialize ai stuff
128 **************************************************************************/
ai_init(void)129 void ai_init(void)
130 {
131 bool failure = FALSE;
132 #if !defined(AI_MODULES) || defined(AI_MOD_STATIC_CLASSIC) || defined(AI_MOD_STATIC_THREADED) || defined(AI_MOD_STATIC_STUB)
133 /* First !defined(AI_MODULES) case is for default ai support. */
134 struct ai_type *ai;
135 #endif
136
137 #ifdef AI_MODULES
138 if (lt_dlinit()) {
139 failure = TRUE;
140 }
141 if (!failure) {
142
143 #ifdef DEBUG
144 /* First search ai modules under directory ai/<module> under
145 current directory. This allows us to run freeciv without
146 installing it. */
147 const char *moduledirs[] = { "classic", "threaded", "stub", NULL };
148 int i;
149
150 for (i = 0; moduledirs[i] != NULL ; i++) {
151 char buf[2048];
152
153 fc_snprintf(buf, sizeof(buf), "ai/%s", moduledirs[i]);
154 lt_dladdsearchdir(buf);
155 }
156 #endif /* DEBUG */
157
158 /* Then search ai modules from their installation directory. */
159 lt_dladdsearchdir(AI_MODULEDIR);
160 }
161 #endif /* AI_MODULES */
162
163 #ifdef AI_MOD_STATIC_CLASSIC
164 ai = ai_type_alloc();
165 if (ai != NULL) {
166 init_ai(ai);
167 if (!fc_ai_classic_setup(ai)) {
168 log_error(_("Failed to setup \"%s\" AI module"), "classic");
169 ai_type_dealloc();
170 }
171 }
172 #endif /* AI_MOD_STATIC_CLASSIC */
173
174 #ifdef AI_MOD_STATIC_THREADED
175 ai = ai_type_alloc();
176 if (ai != NULL) {
177 init_ai(ai);
178 if (!fc_ai_threaded_setup(ai)) {
179 log_error(_("Failed to setup \"%s\" AI module"), "threaded");
180 ai_type_dealloc();
181 }
182 }
183 #endif /* AI_MOD_STATIC_THREADED */
184
185 #ifdef AI_MOD_STATIC_STUB
186 ai = ai_type_alloc();
187 if (ai != NULL) {
188 init_ai(ai);
189 if (!fc_ai_stub_setup(ai)) {
190 log_error(_("Failed to setup \"%s\" AI module"), "stub");
191 ai_type_dealloc();
192 }
193 }
194 #endif /* AI_MOD_STATIC_STUB */
195
196 default_ai = ai_type_by_name(AI_MOD_DEFAULT);
197 #ifdef AI_MODULES
198 if (default_ai == NULL) {
199 /* Wasn't among statically linked. Try to load dynamic module. */
200 if (!failure && !load_ai_module(AI_MOD_DEFAULT)) {
201 failure = TRUE;
202 }
203 if (!failure) {
204 default_ai = ai_type_by_name(AI_MOD_DEFAULT);
205 }
206 }
207 #endif /* AI_MODULES */
208 if (default_ai == NULL || failure) {
209 log_error(_("Failed to setup default AI module \"%s\", cannot continue."),
210 AI_MOD_DEFAULT);
211 exit(EXIT_FAILURE);
212 }
213 }
214
215 /**************************************************************************
216 Call incident function of victim.
217 **************************************************************************/
call_incident(enum incident_type type,struct player * violator,struct player * victim)218 void call_incident(enum incident_type type, struct player *violator,
219 struct player *victim)
220 {
221 CALL_PLR_AI_FUNC(incident, victim, type, violator, victim);
222 }
223
224 /****************************************************************************
225 Call ai refresh() callback for all players.
226 ****************************************************************************/
call_ai_refresh(void)227 void call_ai_refresh(void)
228 {
229 players_iterate(pplayer) {
230 CALL_PLR_AI_FUNC(refresh, pplayer, pplayer);
231 } players_iterate_end;
232 }
233
234 /**************************************************************************
235 Return name of default ai type.
236 **************************************************************************/
default_ai_type_name(void)237 const char *default_ai_type_name(void)
238 {
239 return default_ai->name;
240 }
241