Complete.Org: Mailing Lists: Archives: freeciv-ai: April 2004:
[freeciv-ai] Re: simple historian agent wants to get into cvs
Home

[freeciv-ai] Re: simple historian agent wants to get into cvs

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: Raimar Falke <i-freeciv-lists@xxxxxxxxxxxxx>
Cc: freeciv-ai@xxxxxxxxxxx
Subject: [freeciv-ai] Re: simple historian agent wants to get into cvs
From: nikodimka <nikodimka@xxxxxxxxx>
Date: Tue, 6 Apr 2004 14:24:17 -0700 (PDT)

I have changed the simple historian agent patch 
according to Raimar's comments. 

so I present the patch again:

======================8<======================8<=====================

diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/agents/Makefile.am
freeciv-cvs-Feb-27.sha/client/agents/Makefile.am
--- freeciv-cvs-Feb-27/client/agents/Makefile.am        Sat Dec 21 07:19:05 2002
+++ freeciv-cvs-Feb-27.sha/client/agents/Makefile.am    Tue Mar 30 01:50:30 2004
@@ -10,4 +10,6 @@
        cma_core.c              \
        cma_core.h              \
        cma_fec.c               \
-       cma_fec.h 
+       cma_fec.h               \
+       sha.c                   \
+       sha.h                   
diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/agents/agents.c
freeciv-cvs-Feb-27.sha/client/agents/agents.c
--- freeciv-cvs-Feb-27/client/agents/agents.c   Mon Nov 10 22:59:57 2003
+++ freeciv-cvs-Feb-27.sha/client/agents/agents.c       Wed Apr  7 00:51:01 2004
@@ -16,6 +16,7 @@
 #endif
 
 #include <assert.h>
+#include <stdarg.h>
 #include <string.h>
 
 #include "capability.h"
@@ -29,6 +30,7 @@
 #include "cma_core.h"
 #include "cma_fec.h"
 #include "mapctrl_g.h"
+#include "sha.h"
 
 #include "agents.h"
 
@@ -41,11 +43,19 @@
 
 struct my_agent;
 
+union arguments{
+  int int_arg;
+  struct xy_arg {
+    int x;
+    int y;
+  } xy_arg;
+};
+
 struct call {
   struct my_agent *agent;
-  enum oct { OCT_NEW_TURN, OCT_UNIT, OCT_CITY } type;
+  enum oct { OCT_NEW_TURN, OCT_UNIT, OCT_CITY, OCT_TILE } type;
   enum callback_type cb_type;
-  int arg;
+  union arguments arg;
 };
 
 #define SPECLIST_TAG call
@@ -87,18 +97,53 @@
 ***********************************************************************/
 static void enqueue_call(struct my_agent *agent,
                         enum oct type,
-                        enum callback_type cb_type, int arg)
+                        enum callback_type cb_type, ...)
 {
+  va_list ap;
   struct call *pcall2;
+  union arguments arg;
+
+  va_start(ap, cb_type);
 
   if (client_is_observer()) {
     return;
   }
 
+  switch (type) {
+  case OCT_UNIT:
+  case OCT_CITY:
+    arg.int_arg = va_arg(ap, int);
+    break;
+  case OCT_TILE:
+    arg.xy_arg.x = va_arg(ap, int);
+    arg.xy_arg.y = va_arg(ap, int);
+    break;
+  case OCT_NEW_TURN:
+    /* nothing */
+    break;
+  default:
+    assert(0);
+  }
+  va_end(ap);
+
   call_list_iterate(agents.calls, pcall) {
     if (pcall->type == type && pcall->cb_type == cb_type
-       && pcall->arg == arg && pcall->agent == agent) {
-      return;
+       && pcall->agent == agent) {
+      switch (type) {
+      case OCT_UNIT:
+      case OCT_CITY:
+       if (arg.int_arg == pcall->arg.int_arg) return;
+       break;
+      case OCT_TILE:
+       if (arg.xy_arg.x == pcall->arg.xy_arg.x &&
+           arg.xy_arg.y == pcall->arg.xy_arg.y) return;
+       break;
+      case OCT_NEW_TURN:
+       /* no checks needed for no-arg calls*/
+       break;
+      default:
+       assert(0);
+      }      
     }
   } call_list_iterate_end;
 
@@ -161,9 +206,12 @@
   if (call->type == OCT_NEW_TURN) {
     call->agent->agent.turn_start_notify();
   } else if (call->type == OCT_UNIT) {
-    call->agent->agent.unit_callbacks[call->cb_type] (call->arg);
+    call->agent->agent.unit_callbacks[call->cb_type] (call->arg.int_arg);
   } else if (call->type == OCT_CITY) {
-    call->agent->agent.city_callbacks[call->cb_type] (call->arg);
+    call->agent->agent.city_callbacks[call->cb_type] (call->arg.int_arg);
+  } else if (call->type == OCT_TILE) {
+    call->agent->agent.tile_callbacks[call->cb_type]
+      (call->arg.xy_arg.x, call->arg.xy_arg.y);
   } else {
     assert(0);
   }
@@ -300,6 +348,7 @@
   /* Add init calls of agents here */
   cma_init();
   cmafec_init();
+  simple_historian_init(); 
 }
 
 /***********************************************************************
@@ -445,7 +494,7 @@
       continue;
     }
     if (agent->agent.turn_start_notify) {
-      enqueue_call(agent, OCT_NEW_TURN, CB_LAST, 0);
+      enqueue_call(agent, OCT_NEW_TURN, CB_LAST);
     }
   }
   /*
@@ -610,6 +659,80 @@
     }
     if (agent->agent.city_callbacks[CB_REMOVE]) {
       enqueue_call(agent, OCT_CITY, CB_REMOVE, pcity->id);
+    }
+  }
+
+  call_handle_methods();
+}
+
+/***********************************************************************
+ Called from client/packhand.c. See agents_unit_changed for a generic
+ documentation.
+ Tiles got removed because of FOW.
+***********************************************************************/
+void agents_tile_remove(int x, int y)
+{
+  int i;
+
+  freelog(LOG_DEBUG,
+         "A: agents_tile_remove(tile=(%d, %d))", x, y);
+
+  for (i = 0; i < agents.entries_used; i++) {
+    struct my_agent *agent = &agents.entries[i];
+
+    if (is_outstanding_request(agent)) {
+      continue;
+    }
+    if (agent->agent.tile_callbacks[CB_REMOVE]) {
+      enqueue_call(agent, OCT_TILE, CB_REMOVE, x, y);
+    }
+  }
+
+  call_handle_methods();
+}
+
+/***********************************************************************
+ Called from client/packhand.c. See agents_unit_changed for a generic
+ documentation.
+***********************************************************************/
+void agents_tile_changed(int x, int y)
+{
+  int i;
+  freelog(LOG_DEBUG,
+         "A: agents_tile_changed(tile=(%d, %d))", x, y);
+
+  for (i = 0; i < agents.entries_used; i++) {
+    struct my_agent *agent = &agents.entries[i];
+
+    if (is_outstanding_request(agent)) {
+      continue;
+    }
+    if (agent->agent.tile_callbacks[CB_CHANGE]) {
+      enqueue_call(agent, OCT_TILE, CB_CHANGE, x, y);
+    }
+  }
+
+  call_handle_methods();
+}
+
+/***********************************************************************
+ Called from client/packhand.c. See agents_unit_changed for a generic
+ documentation.
+***********************************************************************/
+void agents_tile_new(int x, int y)
+{
+  int i;
+  freelog(LOG_DEBUG,
+         "A: agents_tile_new(tile=(%d, %d))", x, y);
+
+  for (i = 0; i < agents.entries_used; i++) {
+    struct my_agent *agent = &agents.entries[i];
+
+    if (is_outstanding_request(agent)) {
+      continue;
+    }
+    if (agent->agent.tile_callbacks[CB_NEW]) {
+      enqueue_call(agent, OCT_TILE, CB_NEW, x, y);
     }
   }
 
diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/agents/agents.h
freeciv-cvs-Feb-27.sha/client/agents/agents.h
--- freeciv-cvs-Feb-27/client/agents/agents.h   Thu Nov  7 09:04:52 2002
+++ freeciv-cvs-Feb-27.sha/client/agents/agents.h       Tue Mar 30 01:50:09 2004
@@ -22,6 +22,9 @@
  * every agent is only called once at any time.
  */
 
+/* Don't use the very last level  unless you know what you're doing */
+#define LAST_AGENT_LEVEL 99
+
 #define MAX_AGENT_NAME_LEN 10
 
 struct city;
@@ -38,6 +41,7 @@
   void (*turn_start_notify) (void);
   void (*city_callbacks[CB_LAST]) (int);
   void (*unit_callbacks[CB_LAST]) (int);
+  void (*tile_callbacks[CB_LAST]) (int, int);
 };
 
 void agents_init(void);
@@ -64,6 +68,10 @@
 void agents_city_changed(struct city *pcity);
 void agents_city_new(struct city *pcity);
 void agents_city_remove(struct city *pcity);
+
+void agents_tile_changed(int, int);
+void agents_tile_new(int, int);
+void agents_tile_remove(int, int);
 
 /* called from agents */
 void cause_a_city_changed_for_agent(const char *name_of_calling_agent,
diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/agents/sha.c
freeciv-cvs-Feb-27.sha/client/agents/sha.c
--- freeciv-cvs-Feb-27/client/agents/sha.c      Wed Dec 31 17:00:00 1969
+++ freeciv-cvs-Feb-27.sha/client/agents/sha.c  Wed Apr  7 01:17:06 2004
@@ -0,0 +1,131 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2004 - A. Gorshenev
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "log.h"
+#include "map.h"
+#include "support.h"
+
+#include "agents.h"
+
+#include "sha.h"
+
+/**************************************************************************
+This is the simple historian agent.
+It just saves the last states of all tiles and units.
+The trick is just to call this agent the last of all
+so it still keeps old values whereas all other agents 
+allready got the new ones.
+**************************************************************************/
+
+static struct agent simple_historian_agent;
+
+static struct tile *previous_tiles = NULL;
+static struct unit_list previous_units;
+
+/**************************************************************************
+...
+**************************************************************************/
+static void sha_tile_update(int x, int y) {
+  
+  int index = map_pos_to_index(x, y); 
+  freelog(LOG_DEBUG, "sha got tile: %d ~= (%d, %d)", index, x, y);
+  
+  previous_tiles[index] = *map_get_tile(x, y);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void sha_unit_change(int id) {
+  struct unit *punit = find_unit_by_id(id);
+  struct unit *pold_unit = unit_list_find(&previous_units, id);
+
+  freelog(LOG_DEBUG, "sha got unit: %d", id);
+
+  assert(pold_unit);
+  *pold_unit = *punit;
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void sha_unit_new(int id) {
+  struct unit *punit= find_unit_by_id(id);
+  struct unit *pold_unit = create_unit_virtual(get_player(punit->owner), 
+                                              NULL, 0, 0);
+
+  freelog(LOG_DEBUG, "sha got unit: %d", id);
+
+  *pold_unit = *punit;
+  unit_list_insert(&previous_units, pold_unit);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+static void sha_unit_remove(int id) {
+  struct unit *pold_unit = unit_list_find(&previous_units, id);;
+
+  freelog(LOG_DEBUG, "sha got unit: %d", id);
+
+  assert(pold_unit);
+  unit_list_unlink(&previous_units, pold_unit);
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+void simple_historian_init(void) {
+
+  previous_tiles = fc_malloc(MAX_MAP_INDEX*sizeof(*previous_tiles));
+  memset(previous_tiles, 0, MAX_MAP_INDEX*sizeof(*previous_tiles));
+
+  unit_list_init(&previous_units);
+
+  memset(&simple_historian_agent, 0, sizeof(simple_historian_agent));
+  sz_strlcpy(simple_historian_agent.name, "Simple Historian");
+
+  simple_historian_agent.level = LAST_AGENT_LEVEL;
+                                       
+  simple_historian_agent.unit_callbacks[CB_REMOVE] = sha_unit_remove;
+  simple_historian_agent.unit_callbacks[CB_CHANGE] = sha_unit_change;
+  simple_historian_agent.unit_callbacks[CB_NEW]    = sha_unit_new;
+  simple_historian_agent.tile_callbacks[CB_REMOVE] = sha_tile_update;
+  simple_historian_agent.tile_callbacks[CB_CHANGE] = sha_tile_update;
+  simple_historian_agent.tile_callbacks[CB_NEW]    = sha_tile_update;
+  register_agent(&simple_historian_agent);
+}
+
+/**************************************************************************
+Public interface
+**************************************************************************/
+
+/**************************************************************************
+...
+**************************************************************************/
+struct tile* sha_tile_recall(int x, int y) {
+  int index = map_pos_to_index(x, y); 
+  return &previous_tiles[index];
+}
+
+/**************************************************************************
+...
+**************************************************************************/
+struct unit* sha_unit_recall(int id) {
+  return unit_list_find(&previous_units, id);
+}
+
diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/agents/sha.h
freeciv-cvs-Feb-27.sha/client/agents/sha.h
--- freeciv-cvs-Feb-27/client/agents/sha.h      Wed Dec 31 17:00:00 1969
+++ freeciv-cvs-Feb-27.sha/client/agents/sha.h  Wed Apr  7 00:57:05 2004
@@ -0,0 +1,24 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 2004 - A. Gorshenev
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifndef FC__CLIENT_AGENTS_SIMPLE_HISTORIAN_H
+#define FC__CLIENT_AGENTS_SIMPLE_HISTORIAN_H
+
+void simple_historian_init(void);
+
+struct tile* sha_tile_recall(int x, int y);
+struct unit* sha_unit_recall(int id);
+
+#endif /* header guard */
+
+
diff -ruN -Xfreeciv-cvs-Feb-27.sha/diff_ignore 
freeciv-cvs-Feb-27/client/packhand.c
freeciv-cvs-Feb-27.sha/client/packhand.c
--- freeciv-cvs-Feb-27/client/packhand.c        Sun Feb 22 23:01:50 2004
+++ freeciv-cvs-Feb-27.sha/client/packhand.c    Wed Apr  7 00:45:52 2004
@@ -1902,6 +1902,7 @@
   struct tile *ptile = map_get_tile(packet->x, packet->y);
   enum known_type old_known = ptile->known;
   bool tile_changed = FALSE;
+  bool known_changed = FALSE;
 
   if (ptile->terrain != packet->type) { /*terrain*/
     tile_changed = TRUE;
@@ -1924,6 +1925,9 @@
       tile_changed = TRUE;
     }
   }
+  if (ptile->known != packet->known) {
+    known_changed = TRUE;
+  }
   ptile->known = packet->known;
 
   if (packet->spec_sprite[0] != '\0') {
@@ -1965,6 +1969,19 @@
   if (ptile->continent > map.num_continents) {
     map.num_continents = ptile->continent;
     allot_island_improvs();
+  }
+
+  if (known_changed || tile_changed) {
+    /* here I assume that tile can *change* only if it was known
+       and still is known. Otherwise it is new or removed 
+       and that it can not go into UNKNOWN after it has been known */
+    if (known_changed && (ptile->known == TILE_KNOWN)) {
+      agents_tile_new(packet->x, packet->y);
+    } else if (known_changed && (ptile->known == TILE_KNOWN_FOGGED)) {
+      agents_tile_remove(packet->x, packet->y);
+    } else {
+      agents_tile_changed(packet->x, packet->y);
+    }
   }
 
   /* refresh tiles */


__________________________________
Do you Yahoo!?
Yahoo! Small Business $15K Web Design Giveaway 
http://promotions.yahoo.com/design_giveaway/


[Prev in Thread] Current Thread [Next in Thread]