- Implement AI land marks which only used to tracks visited areas on the map for now. Significantly reduces wasting of cpu time by AI checking same place several times (10x or even more in rare cases)
- More branching in walk algorythm which allows for better coverage of reachable places. Sometimes makes AI perform ridiculous jumping just to make a tiny step.
- Small fixes/adjustments
/***************************************************************************/
/* */
/* ftcmru.c */
/* */
/* FreeType MRU support (body). */
/* */
/* Copyright 2003, 2004, 2006, 2009 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
/* this file you indicate that you have read the license and */
/* understand and accept it fully. */
/* */
/***************************************************************************/
#include <ft2build.h>
#include FT_CACHE_H
#include "ftcmru.h"
#include FT_INTERNAL_OBJECTS_H
#include FT_INTERNAL_DEBUG_H
#include "ftcerror.h"
FT_LOCAL_DEF( void )
FTC_MruNode_Prepend( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
if ( first )
{
FTC_MruNode last = first->prev;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
{
fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );
exit( 2 );
}
cnode = cnode->next;
} while ( cnode != first );
}
#endif
first->prev = node;
last->next = node;
node->next = first;
node->prev = last;
}
else
{
node->next = node;
node->prev = node;
}
*plist = node;
}
FT_LOCAL_DEF( void )
FTC_MruNode_Up( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FT_ASSERT( first != NULL );
if ( first != node )
{
FTC_MruNode prev, next, last;
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
last = first->prev;
last->next = node;
first->prev = node;
node->next = first;
node->prev = last;
*plist = node;
}
}
FT_LOCAL_DEF( void )
FTC_MruNode_Remove( FTC_MruNode *plist,
FTC_MruNode node )
{
FTC_MruNode first = *plist;
FTC_MruNode prev, next;
FT_ASSERT( first != NULL );
#ifdef FT_DEBUG_ERROR
{
FTC_MruNode cnode = first;
do
{
if ( cnode == node )
goto Ok;
cnode = cnode->next;
} while ( cnode != first );
fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );
exit( 2 );
Ok:
}
#endif
prev = node->prev;
next = node->next;
prev->next = next;
next->prev = prev;
if ( node == next )
{
FT_ASSERT( first == node );
FT_ASSERT( prev == node );
*plist = NULL;
}
else if ( node == first )
*plist = next;
}
FT_LOCAL_DEF( void )
FTC_MruList_Init( FTC_MruList list,
FTC_MruListClass clazz,
FT_UInt max_nodes,
FT_Pointer data,
FT_Memory memory )
{
list->num_nodes = 0;
list->max_nodes = max_nodes;
list->nodes = NULL;
list->clazz = *clazz;
list->data = data;
list->memory = memory;
}
FT_LOCAL_DEF( void )
FTC_MruList_Reset( FTC_MruList list )
{
while ( list->nodes )
FTC_MruList_Remove( list, list->nodes );
FT_ASSERT( list->num_nodes == 0 );
}
FT_LOCAL_DEF( void )
FTC_MruList_Done( FTC_MruList list )
{
FTC_MruList_Reset( list );
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FTC_MruNode )
FTC_MruList_Find( FTC_MruList list,
FT_Pointer key )
{
FTC_MruNode_CompareFunc compare = list->clazz.node_compare;
FTC_MruNode first, node;
first = list->nodes;
node = NULL;
if ( first )
{
node = first;
do
{
if ( compare( node, key ) )
{
if ( node != first )
FTC_MruNode_Up( &list->nodes, node );
return node;
}
node = node->next;
} while ( node != first);
}
return NULL;
}
#endif
FT_LOCAL_DEF( FT_Error )
FTC_MruList_New( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FT_Error error;
FTC_MruNode node;
FT_Memory memory = list->memory;
if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
{
node = list->nodes->prev;
FT_ASSERT( node );
if ( list->clazz.node_reset )
{
FTC_MruNode_Up( &list->nodes, node );
error = list->clazz.node_reset( node, key, list->data );
if ( !error )
goto Exit;
}
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
}
else if ( FT_ALLOC( node, list->clazz.node_size ) )
goto Exit;
error = list->clazz.node_init( node, key, list->data );
if ( error )
goto Fail;
FTC_MruNode_Prepend( &list->nodes, node );
list->num_nodes++;
Exit:
*anode = node;
return error;
Fail:
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
goto Exit;
}
#ifndef FTC_INLINE
FT_LOCAL_DEF( FT_Error )
FTC_MruList_Lookup( FTC_MruList list,
FT_Pointer key,
FTC_MruNode *anode )
{
FTC_MruNode node;
node = FTC_MruList_Find( list, key );
if ( node == NULL )
return FTC_MruList_New( list, key, anode );
*anode = node;
return 0;
}
#endif /* FTC_INLINE */
FT_LOCAL_DEF( void )
FTC_MruList_Remove( FTC_MruList list,
FTC_MruNode node )
{
FTC_MruNode_Remove( &list->nodes, node );
list->num_nodes--;
{
FT_Memory memory = list->memory;
if ( list->clazz.node_done )
list->clazz.node_done( node, list->data );
FT_FREE( node );
}
}
FT_LOCAL_DEF( void )
FTC_MruList_RemoveSelection( FTC_MruList list,
FTC_MruNode_CompareFunc selection,
FT_Pointer key )
{
FTC_MruNode first, node, next;
first = list->nodes;
while ( first && ( selection == NULL || selection( first, key ) ) )
{
FTC_MruList_Remove( list, first );
first = list->nodes;
}
if ( first )
{
node = first->next;
while ( node != first )
{
next = node->next;
if ( selection( node, key ) )
FTC_MruList_Remove( list, node );
node = next;
}
}
}
/* END */