1/*****************************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
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/*****************************************************************************
15  ADVERTISEMENT: do not attempt to change the name of the API functions.
16  They may be in use in Lua scripts in savefiles, so once released, the
17  name and signature cannot change shape even in new major versions of
18  Freeciv, until the relevant save format version can no longer be loaded.
19  If you really like to change a function name, be sure to keep also the
20  old one running.
21*****************************************************************************/
22
23$#ifdef HAVE_CONFIG_H
24$#include <fc_config.h>
25$#endif
26
27/* common/scriptcore */
28$#include "api_common_utilities.h"
29$#include "api_game_effects.h"
30$#include "api_game_find.h"
31$#include "api_game_methods.h"
32$#include "luascript_types.h"
33
34/* Classes. */
35struct Player {
36  const char *name;
37  Nation_Type *nation;
38  bool ai_controlled;
39  bool is_alive;
40};
41
42struct City {
43  const char *name;
44  Player *owner;
45  Player *original;
46
47  const int id;
48};
49
50struct Connection {
51  const int id;
52};
53
54struct Unit {
55  Unit_Type *utype;
56  Player *owner;
57
58  /* This used to be @ homecity_id, but it does not work with toluaxx. */
59  int homecity;
60
61  const int id;
62};
63
64struct Tile {
65  Terrain *terrain;
66
67  const int index @ id;
68};
69
70struct Government {
71  const int item_number @ id;
72};
73
74struct Nation_Type {
75  const int item_number @ id;
76};
77
78struct Building_Type {
79  int build_cost;
80
81  const int item_number @ id;
82};
83
84struct Unit_Type {
85  int build_cost;
86
87  const int item_number @ id;
88};
89
90struct Tech_Type {
91  const int item_number @ id;
92};
93
94struct Terrain {
95  const int item_number @ id;
96};
97
98struct Disaster {
99  const int id;
100};
101
102struct Achievement {
103  const int id;
104};
105
106struct Action {
107  const int id;
108};
109
110struct Unit_List_Link {
111};
112
113struct City_List_Link {
114};
115
116/* Module Game */
117module game {
118  int api_methods_game_turn
119    @ turn (lua_State *L);
120}
121
122/* Module Player. */
123module Player {
124  module properties {
125    int api_methods_player_number
126      @ id (lua_State *L, Player *self);
127  }
128
129  int api_methods_player_num_cities
130    @ num_cities (lua_State *L, Player *self);
131  int api_methods_player_num_units
132    @ num_units (lua_State *L, Player *self);
133  bool api_methods_player_has_wonder
134    @ has_wonder (lua_State *L, Player *self, Building_Type *building);
135  int api_methods_player_gold
136    @ gold (lua_State *L, Player *self);
137  bool api_methods_player_knows_tech
138    @ knows_tech (lua_State *L, Player *self, Tech_Type *ptech);
139  bool api_methods_player_shares_research
140    @ shares_research (lua_State *L, Player *self, Player *other);
141  const char *api_methods_research_rule_name
142    @ research_rule_name (lua_State *L, Player *self);
143  const char *api_methods_research_name_translation
144    @ research_name_translation (lua_State *L, Player *self);
145
146  int api_methods_player_culture_get
147    @ culture(lua_State *L, Player *self);
148}
149
150module methods_private {
151  lua_Object api_methods_private_list_players
152    @ list_players (lua_State *L);
153  module Player {
154    Unit_List_Link *api_methods_private_player_unit_list_head
155      @ unit_list_head (lua_State *L, Player *self);
156    City_List_Link *api_methods_private_player_city_list_head
157      @ city_list_head (lua_State *L, Player *self);
158  }
159}
160
161$[
162
163-- Player methods
164function Player:is_human()
165  return not self.ai_controlled
166end
167
168function Player:exists()
169  return true
170end
171
172$]
173
174/* Module City. */
175module City {
176  module properties {
177    int api_methods_city_size_get
178      @ size(lua_State *L, City *self);
179    Tile *api_methods_city_tile_get
180      @ tile(lua_State *L, City *self);
181  }
182
183  bool api_methods_city_has_building
184    @ has_building(lua_State *L, City *self, Building_Type *building);
185  int api_methods_city_map_sq_radius
186    @ map_sq_radius(lua_State *L, City *self);
187  int api_methods_city_inspire_partisans
188    @ inspire_partisans(lua_State *L, City *self, Player *inspirer);
189
190  int api_methods_city_culture_get
191    @ culture(lua_State *L, City *self);
192
193  bool api_methods_is_city_happy
194    @ is_happy(lua_State *L, City *self);
195  bool api_methods_is_city_unhappy
196    @ is_unhappy(lua_State *L, City *self);
197  bool api_methods_is_city_celebrating
198    @ is_celebrating(lua_State *L, City *self);
199  bool api_methods_is_gov_center
200    @ is_gov_center(lua_State *L, City *self);
201  bool api_methods_is_capital
202    @ is_capital(lua_State *L, City *self);
203}
204
205$[
206
207-- City methods.
208function City:exists()
209  return true
210end
211
212$]
213
214/* Module Unit. */
215module Unit {
216  module properties {
217    Tile *api_methods_unit_tile_get
218      @ tile(lua_State *L, Unit *self);
219  }
220
221  Unit *api_methods_unit_transporter
222    @ transporter (lua_State *L, Unit *self);
223  bool api_methods_unit_city_can_be_built_here
224    @ is_on_possible_city_tile (lua_State *L, Unit *self);
225  Direction *api_methods_unit_orientation_get
226    @ facing(lua_State *L, Unit *self);
227}
228
229module methods_private {
230  module Unit {
231    Unit_List_Link *api_methods_private_unit_cargo_list_head
232      @ cargo_list_head (lua_State *L, Unit *self);
233  }
234}
235
236$[
237
238-- Unit methods.
239function Unit:exists()
240  return true
241end
242
243function Unit:get_homecity()
244  return find.city(self.owner, self.homecity)
245end
246$]
247
248/* Module Tile. */
249module Tile {
250  module properties {
251    int api_methods_tile_nat_x
252      @ nat_x (lua_State *L, Tile *self);
253    int api_methods_tile_nat_y
254      @ nat_y (lua_State *L, Tile *self);
255    int api_methods_tile_map_x
256      @ x (lua_State *L, Tile *self);
257    int api_methods_tile_map_y
258      @ y (lua_State *L, Tile *self);
259  }
260
261  City *api_methods_tile_city
262    @ city (lua_State *L, Tile *self);
263  bool api_methods_tile_city_exists_within_max_city_map
264    @ city_exists_within_max_city_map (lua_State *L, Tile *self, bool center);
265  bool api_methods_tile_has_extra
266    @ has_extra(lua_State *L, Tile *self, const char *name);
267  bool api_methods_tile_has_base
268    @ has_base(lua_State *L, Tile *self, const char *name);
269  bool api_methods_tile_has_road
270    @ has_road(lua_State *L, Tile *self, const char *name);
271  int api_methods_tile_num_units
272    @ num_units (lua_State *L, Tile *self);
273  int api_methods_tile_sq_distance
274    @ sq_distance (lua_State *L, Tile *self, Tile *other);
275}
276
277$[
278
279-- ***************************************************************************
280-- Deprecated. New one is Tile:city_exists_within_max_city_map().
281-- ***************************************************************************
282function Tile:city_exists_within_city_radius(center)
283  log.deprecation_warning("city_exists_within_city_radius()", "city_exists_within_max_city_map()",
284                          "2.3");
285  return self:city_exists_within_max_city_map(center)
286end
287
288$]
289
290module methods_private {
291  module Tile {
292    int api_methods_private_tile_next_outward_index
293      @ next_outward_index (lua_State *L, Tile *pcenter, int tindex,
294                            int max_dist);
295    Tile *api_methods_private_tile_for_outward_index
296      @ tile_for_outward_index (lua_State *L, Tile *pcenter, int tindex);
297    Unit_List_Link *api_methods_private_tile_unit_list_head
298      @ unit_list_head (lua_State *L, Tile *self);
299  }
300}
301
302/* Module Government. */
303module Government {
304  const char *api_methods_government_rule_name
305    @ rule_name (lua_State *L, Government *self);
306  const char *api_methods_government_name_translation
307    @ name_translation (lua_State *L, Government *self);
308}
309
310/* Module Nation_Type. */
311module Nation_Type {
312  const char *api_methods_nation_type_rule_name
313    @ rule_name (lua_State *L, Nation_Type *self);
314  const char *api_methods_nation_type_name_translation
315    @ name_translation (lua_State *L, Nation_Type *self);
316  const char *api_methods_nation_type_plural_translation
317    @ plural_translation (lua_State *L, Nation_Type *self);
318}
319
320/* Module Building_Type. */
321module Building_Type {
322  bool api_methods_building_type_is_wonder
323    @ is_wonder (lua_State *L, Building_Type *self);
324  bool api_methods_building_type_is_great_wonder
325    @ is_great_wonder (lua_State *L, Building_Type *self);
326  bool api_methods_building_type_is_small_wonder
327    @ is_small_wonder (lua_State *L, Building_Type *self);
328  bool api_methods_building_type_is_improvement
329    @ is_improvement (lua_State *L, Building_Type *self);
330  const char *api_methods_building_type_rule_name
331    @ rule_name (lua_State *L, Building_Type *self);
332  const char *api_methods_building_type_name_translation
333    @ name_translation (lua_State *L, Building_Type *self);
334}
335
336$[
337
338-- Building_Type methods.
339function Building_Type:build_shield_cost()
340  return self.build_cost
341end
342
343$]
344
345/* Module Unit_Type. */
346module Unit_Type {
347  bool api_methods_unit_type_has_flag
348    @ has_flag (lua_State *L, Unit_Type *self, const char *flag);
349  bool api_methods_unit_type_has_role
350    @ has_role (lua_State *L, Unit_Type *self, const char *role);
351  const char *api_methods_unit_type_rule_name
352    @ rule_name (lua_State *L, Unit_Type *self);
353  const char *api_methods_unit_type_name_translation
354    @ name_translation (lua_State *L, Unit_Type *self);
355  bool api_methods_unit_type_can_exist_at_tile
356    @ can_exist_at_tile(lua_State *L, Unit_Type *self, Tile *ptile);
357}
358
359$[
360
361-- Unit_Type methods.
362function Unit_Type:build_shield_cost()
363  return self.build_cost
364end
365
366$]
367
368/* Module Tech_Type. */
369module Tech_Type {
370  const char *api_methods_tech_type_rule_name
371    @ rule_name (lua_State *L, Tech_Type *self);
372  const char *api_methods_tech_type_name_translation
373    @ name_translation (lua_State *L, Tech_Type *self);
374}
375
376/* Module Terrain. */
377module Terrain {
378  const char *api_methods_terrain_rule_name
379    @ rule_name (lua_State *L, Terrain *self);
380  const char *api_methods_terrain_name_translation
381    @ name_translation (lua_State *L, Terrain *self);
382  const char *api_methods_terrain_class_name
383    @ class_name (lua_State *L, Terrain *self);
384}
385
386/* Module Disaster. */
387module Disaster {
388  const char *api_methods_disaster_rule_name
389    @ rule_name (lua_State *L, Disaster *self);
390  const char *api_methods_disaster_name_translation
391    @ name_translation (lua_State *L, Disaster *self);
392}
393
394/* Module Achievement. */
395module Achievement {
396  const char *api_methods_achievement_rule_name
397    @ rule_name (lua_State *L, Achievement *self);
398  const char *api_methods_achievement_name_translation
399    @ name_translation (lua_State *L, Achievement *self);
400}
401
402/* Module Action. */
403module Action {
404  const char *api_methods_action_rule_name
405    @ rule_name (lua_State *L, Action *self);
406  const char *api_methods_action_name_translation
407    @ name_translation (lua_State *L, Action *self);
408}
409
410/* Module Unit_List_Link. */
411module Unit_List_Link {
412  Unit *api_methods_unit_list_link_data
413    @ data (lua_State *L, Unit_List_Link *self);
414  Unit_List_Link *api_methods_unit_list_next_link
415    @ next (lua_State *L, Unit_List_Link *self);
416}
417
418/* Module City_List_Link. */
419module City_List_Link {
420  City *api_methods_city_list_link_data
421    @ data (lua_State *L, City_List_Link *self);
422  City_List_Link *api_methods_city_list_next_link
423    @ next (lua_State *L, City_List_Link *self);
424}
425
426/* Module find. */
427module find {
428  Player *api_find_player
429    @ player (lua_State *L, int player_id);
430  City *api_find_city
431    @ city (lua_State *L, Player *pplayer, int city_id);
432  Unit *api_find_unit
433    @ unit (lua_State *L, Player *pplayer, int unit_id);
434  Unit *api_find_transport_unit
435    @ transport_unit (lua_State *L, Player *pplayer, Unit_Type *ptype,
436                      Tile *ptile);
437  Tile *api_find_tile
438    @ tile (lua_State *L, int nat_x, int nat_y);
439  Tile *api_find_tile_by_index
440    @ tile (lua_State *L, int tindex);
441
442  /* NOTE: For overloading to work correctly, the string function
443   * must be before the integer function for each case below. */
444  Government *api_find_government_by_name
445    @ government (lua_State *L, const char *name_orig);
446  Government *api_find_government
447    @ government (lua_State *L, int government_id);
448  Nation_Type *api_find_nation_type_by_name
449    @ nation_type (lua_State *L, const char *name_orig);
450  Nation_Type *api_find_nation_type
451    @ nation_type (lua_State *L, int nation_type_id);
452  Building_Type *api_find_building_type_by_name
453    @ building_type (lua_State *L, const char *name_orig);
454  Building_Type *api_find_building_type
455    @ building_type (lua_State *L, int building_type_id);
456  Unit_Type *api_find_unit_type_by_name
457    @ unit_type (lua_State *L, const char *name_orig);
458  Unit_Type *api_find_unit_type
459    @ unit_type (lua_State *L, int unit_type_id);
460  Unit_Type *api_find_role_unit_type
461    @ role_unit_type (lua_State *L, const char *role_name, Player *pplayer);
462  Tech_Type *api_find_tech_type_by_name
463    @ tech_type (lua_State *L, const char *name_orig);
464  Tech_Type *api_find_tech_type
465    @ tech_type (lua_State *L, int tech_type_id);
466  Terrain *api_find_terrain_by_name
467    @ terrain (lua_State *L, const char *name_orig);
468  Terrain *api_find_terrain
469    @ terrain (lua_State *L, int terrain_id);
470  Nonexistent *api_find_nonexistent
471    @ nonexistent (lua_State *L);
472}
473
474module E {
475  /* Notify events module is exported by api_specenum */
476}
477
478/* Effects module */
479module effects {
480  int api_effects_world_bonus
481    @ world_bonus (lua_State *L, const char *effect_type);
482  int api_effects_player_bonus
483    @ player_bonus (lua_State *L, Player *pplayer, const char *effect_type);
484  int api_effects_city_bonus
485    @ city_bonus (lua_State *L, City *pcity, const char *effect_type);
486}
487
488/* Direction module */
489module direction {
490 Direction *api_utilities_str2dir
491   @ str2dir(lua_State *L, const char *str);
492 Direction *api_utilities_dir_ccw
493   @ next_ccw(lua_State *L, Direction self);
494 Direction *api_utilities_dir_cw
495   @ next_cw(lua_State *L, Direction self);
496 Direction *api_utilities_opposite_dir
497   @ opposite(lua_State *L, Direction self);
498}
499
500$[
501-- **************************************************************************
502-- Convert direction describing text to direction
503-- **************************************************************************
504function str2direction(str)
505  return direction.str2dir(str)
506end
507$]
508
509$[
510
511-- ***************************************************************************
512-- Player and Tile: cities_iterate and units_iterate methods
513-- ***************************************************************************
514do
515  local private = methods_private
516
517  -- Iterate over the values of 'array' in order:
518  -- array[1], array[2], array[3], etc.
519  local function value_iterator(array)
520    local i = 0
521    local function iterator()
522      i = i + 1
523      return array[i]
524    end
525    return iterator
526  end
527
528  -- use a copy of the list for safe iteration
529  local function safe_iterate_list(link)
530    local objs = {}
531    while link do
532      objs[#objs + 1] = link:data()
533      link = link:next()
534    end
535    return value_iterator(objs)
536  end
537
538  -- Safe iteration over all units that belong to Player
539  function Player:units_iterate()
540    return safe_iterate_list(private.Player.unit_list_head(self))
541  end
542
543  -- Safe iteration over all cities that belong to Player
544  function Player:cities_iterate()
545    return safe_iterate_list(private.Player.city_list_head(self))
546  end
547
548  -- Safe iteration over the units on Tile
549  function Tile:units_iterate()
550    return safe_iterate_list(private.Tile.unit_list_head(self))
551  end
552
553  -- Safe iteration over the units transported by Unit
554  function Unit:cargo_iterate()
555    return safe_iterate_list(private.Unit.cargo_list_head(self))
556  end
557end
558
559-- ***************************************************************************
560-- Tile: square_iterate, circle_iterate
561-- ***************************************************************************
562do
563  local next_outward_index = methods_private.Tile.next_outward_index
564  local tile_for_outward_index = methods_private.Tile.tile_for_outward_index
565
566  -- iterate over tiles at distance 'radius'
567  function Tile:square_iterate(radius)
568    local index = -1
569    local function iterator()
570      index = next_outward_index(self, index, radius)
571      if index < 0 then
572        return nil
573      else
574        return tile_for_outward_index(self, index)
575      end
576    end
577    return iterator
578  end
579
580  -- iterate over tiles at squared distance 'sq_radius'
581  function Tile:circle_iterate(sq_radius)
582    local cr_radius = math.floor(math.sqrt(sq_radius))
583    local sq_iter = self:square_iterate(cr_radius)
584    local function iterator()
585      local tile = nil
586      repeat
587        tile = sq_iter()
588      until not tile or self:sq_distance(tile) <= sq_radius
589      return tile
590    end
591    return iterator
592  end
593end
594
595$]
596
597$[
598-- ***************************************************************************
599-- Iteration constructs for game-global objects
600-- ***************************************************************************
601do
602  -- iterate over the values returned by lookup
603  -- until nil is returned:
604  -- lookup(0), lookup(1), lookup(2), etc
605  local function index_iterate(lookup)
606    local index = -1
607    local function iterator()
608      index = index + 1
609      return lookup(index)
610    end
611    return iterator
612  end
613
614  -- Iterate over all players of the game (note: indices may have gaps)
615  local listp = methods_private.list_players
616  function players_iterate()
617    local plist = listp()
618    local index = 0
619    return function()
620      index = index + 1
621      return plist[index]
622    end
623  end
624
625  -- Iterate over all tiles of the game
626  function whole_map_iterate()
627    return index_iterate(find.tile)
628  end
629
630  -- NOTE: Identical further definitions can be made for
631  -- governments, tech_types, building_types etc
632end
633
634$]
635