home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
289_01
/
othdbm.c
< prev
next >
Wrap
Text File
|
1989-05-25
|
19KB
|
637 lines
/*-----------------------------------------------------------------------------
OTHDBM.C
Revision History
----------------
Jon Ward 17 Oct 1988 Initial Revision.
Jon Ward 30 Oct 1988 Mods for move type.
Jon Ward 30 Oct 1988 Optimized and combined the allocate functions.
Now we use the macros ALLOCATE_LIMB and
ALLOCATE_BOARD.
Jon Ward 04 Dec 1988 Debugging commencing.
Jon Ward 03 Jan 1989 Added relinking ability to db_delete_subtree
changed free_limb from static to global.
-----------------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "othello.h"
/*-----------------------------------------------------------------------------
How This Thing Works:
There will be two data spaces. One for limbs, and one for boards. Each data
space will be maintained as an array. Each array will be bit-mapped so that
we can determine if an element in the array is unused.
-----------------------------------------------------------------------------*/
/*------------------------------------------------
The following structure bd_row_st is used as a
trick to get the MSC compiler to perform a struct
assignment for the board row. The reason for this
is that the database boards are stored in a far
area of ram. Segmentation...Argh!!!!
The dbm_board_st struct is a compressed form of
the board_st structure used every else in the
program. The boards, when compressed, are much
smaller, about 52% smaller or 66% as big as they
would have been.
------------------------------------------------*/
struct bd_row_st
{
unsigned char row [8];
};
struct dbm_board_st
{
struct bd_row_st board [8];
unsigned char fa_bits [FA_BITS_SIZE];
};
typedef struct dbm_board_st dbm_board_type;
#define MAX_DBM_LIMBS 65536 / sizeof (limb_type)
#define MAX_DBM_BOARDS 32768
STATIC limb_type far limb_array [MAX_DBM_LIMBS];
STATIC key_type num_limbs_left; /* number of limbs available */
STATIC key_type num_boards_left; /* number of boards available */
#define MAX_BD_PTRS 50
#define STORED_BOARD_SIZE sizeof (dbm_board_type)
STATIC key_type bd_per_blk = 16384 / STORED_BOARD_SIZE;
STATIC dbm_board_type far *board_ptrs [MAX_BD_PTRS];
STATIC int bd_blks;
typedef unsigned int am_type; /* availability map type */
#define AM_SIZE (8 * sizeof (am_type)) /* bits in availability map type */
STATIC am_type lam [(MAX_DBM_LIMBS + 7) / 8]; /* limb availability map */
STATIC am_type bam [(MAX_DBM_BOARDS + 7) / 8]; /* board availability map */
#define AM_USED ((am_type) (-1))
#define LAM_SIZE (sizeof (lam) / sizeof (lam [0]))
#define BAM_SIZE (sizeof (bam) / sizeof (bam [0]))
/*-----------------------------------------------
The following macros are used to GET, SET, and
CLR bits in the limb and board availability maps.
-----------------------------------------------*/
#define GET_BIT(x,y) (((x) [(y) / AM_SIZE]) & (1 << ((y) % AM_SIZE)))
#define SET_BIT(x,y) (((x) [(y) / AM_SIZE]) |= (1 << ((y) % AM_SIZE)))
#define CLR_BIT(x,y) (((x) [(y) / AM_SIZE]) &= ~(1 << ((y) % AM_SIZE)))
key_type max_limb_key = MAX_DBM_LIMBS; /* maximum key number for limbs */
key_type max_board_key = MAX_DBM_BOARDS; /* maximum key number for boards */
key_type last_parent_key; /* last parent child was added to */
key_type last_child_key; /* last child added */
/*-----------------------------------------------------------------------------
Local Function Prototypes
-----------------------------------------------------------------------------*/
STATIC key_type allocate_limb (int am_sel);
STATIC void free_board (key_type board);
STATIC void free_subtree (key_type key);
STATIC void get_board (
key_type key,
board_type *board);
STATIC void put_board (
key_type key,
board_type *board);
/*-----------------------------------------------------------------------------
The following data is used by the allocate_am function when searching for and
allocating a limb or board element in the database.
-----------------------------------------------------------------------------*/
struct am_struct
{
am_type *am; /* pointer to availability map */
key_type size; /* number of elements in availability map */
key_type *max; /* maximum key for am */
int *num_avail; /* number of available elements */
};
STATIC struct am_struct am_data [] =
{
{ lam, LAM_SIZE, &max_limb_key, &num_limbs_left },
{ bam, BAM_SIZE, &max_board_key, &num_boards_left },
};
#define ALLOCATE_LIMB() (allocate_am (0))
#define ALLOCATE_BOARD() (allocate_am (1))
/*-----------------------------------------------------------------------------
STATIC key_type allocate_am (int am_sel);
This function will locate the next available element in either the limb or
board array. The am_sel argument determines whether the limb (0) or board (1)
map will be used. If a free element if found, it is marked as used, and the
key for referencing that element is returned. If no free space is available,
the NO_KEY manifest constant is returned to indicate an allocation failure.
-----------------------------------------------------------------------------*/
STATIC key_type allocate_am (int am_sel) /* availability map selector */
{
struct am_struct *amp; /* pointer into availability map structure */
register am_type *pt; /* pointer into the limb availability map */
register key_type key; /* key var */
amp = &am_data [am_sel]; /* init pointer to am struct */
for (pt = amp->am; pt < (amp->am + amp->size); pt++)
{
if (*pt != AM_USED) /* if a limb is free */
{
am_type am_entry; /* var copy of am entry */
key = AM_SIZE * (pt - amp->am);
am_entry = *pt;
for (; am_entry & 1; am_entry >>= 1, key++); /* generate the key */
if (key >= *(amp->max)) /* range check the key */
break; /* break if it's too big */
SET_BIT (amp->am, key); /* set alloc bit if range ok */
*(amp->num_avail) -= 1; /* decrement number available */
return (key); /* return the key */
}
}
return (NO_KEY); /* out of limb space */
}
/*-----------------------------------------------------------------------------
void free_limb (key_type limb);
This function will free the array element associated with a previously
allocated limb. The limb argument id the index for the array element to free.
The limb is freed merely by clearing the corresponding bit in the limb
availability map.
-----------------------------------------------------------------------------*/
void free_limb (key_type limb)
{
if (limb >= 0 && limb < max_limb_key && GET_BIT (lam, limb))
{
num_limbs_left++;
CLR_BIT (lam, limb);
}
}
/*-----------------------------------------------------------------------------
STATIC void free_board (key_type board)
This function will free the array element associated with a previously
allocated board. The board argument id the index for the array element to free.
The board is freed merely by clearing the corresponding bit in the board
availability map.
-----------------------------------------------------------------------------*/
STATIC void free_board (key_type board)
{
if (board >= 0 && board < max_board_key && GET_BIT (bam, board))
{
num_boards_left++;
CLR_BIT (bam, board);
}
}
/*-----------------------------------------------------------------------------
void db_init (void);
This function will clear the othello database manager variables and prepare
some data space for the othello program to use. It should only be called once
to initialize the database.
Return Value
None.
-----------------------------------------------------------------------------*/
/*-----------------------------------------------
The following pragma declares the memset function
to generate inline code
-----------------------------------------------*/
#pragma intrinsic (memset)
void db_init ()
{
key_type blk_size; /