DMH-Online

Dungeon Masters Helper · Est. 2005

Misc Scripts

NWN Script: chess_game.htm

Author Sticky: Post Working Scripts Here
Bagofbones Posted: Tuesday, 09 July 04:10AM
1. itools_chess

2. Include file for functions to implement a human chess game with NPC characters as well as help in other chess related traps etc.

3. Notes:

These functions assume they are called from an area containing two waypoints, with the tags CHS_WP_WHITE and CHS_WP_BLACK, that define the chessboard. In this version the chessboard must have ranks that run east/west with white's king's rook in the south-east corner.Any board size can be defined. I tested with the chessboard terrain rotated to put white at the bottom right.

The commands will place blue and red shafts of light on given chess squares. These indicate the squares the "pieces" will be moved to and from respectivly. The chs_MakeIndicatedMove() command will find to closest reature object to the blue shaft of light nad move to the location of the red shaft light. If the target location is occupied by a piece it is captured (destroyed). I tested this using male and female commoners. I changed their appearances to simulate the monsters I wanted to use.

These commands do not try to enforce any chess rules in this version. Many of then may have a general purpose use in a chess related module. See the include file comments for a list of the functions.

4. itools_chess verstion 1.4
NWScript:
//::///////////////////////////////////////////////
//:: FileName itools_chess
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//:: Created By: Bagofbones@earthlink.net
//:: Created On: 6/29/02 6:04:29 PM
//::
//:: Version  Modified  Change
//:: 1.2      7/03/02   added chs_SetIndicatorRank
//::                    and chs_SetIndicatorFile
//:: 1.3      7/07/02   added chs_getPieceAtLocation
//::
//:: 1.4      7/08/02   added chs_MakeIndicatedMove
//:://////////////////////////////////////////////

//::///////////////////////////////////////////////
//:: include file for human chess functions
//:://////////////////////////////////////////////
/*
These functions assume they are called from an area
containing two waypoints that define the chessbord.
In this version the chessboard must have Ranks that run
east/west with white's king's rook in the south.
the indicator used can be changed by changeing the blueprint and
tag strings in the appropriate files.  Currently I use a shaft
of blue light to indicate the source square and a shaft of red light
to indicate a destination square.
Functions in this include file:
location  chs_GetBoardLocation( int nRank, int nFile, int bFacingBlack );
int  chs_LocationToRank( location lTest );
int  chs_LocationToFile( location lTest );
int  chs_SetIndicatorFile( int nFile, int bFromMarker = TRUE );
int  chs_SetIndicatorRank( int nRank, int bFromMarker );
int  chs_SetIndicatorPositon( int nRank, int nFile, int bFromMarker = TRUE );
object chs_getPieceAtLocation( location lTest );
int  chs_MakeIndicatedMove();
TODO:
Add  SettupBoard() and ClearBoard;
*/

//::///////////////////////////////////////////////
//:: Name  chs_GetBoardLocation
//::
//:://////////////////////////////////////////////
/*
Input:
int nRank -the chess square's rank 1(white)-8(black)
int nFile -the chess square's file 1(File A)-8(File H)
int bFacingBlack - the locations facing direction
                   TRUE - at Black , FALSE - at White
Output:
location  -  square center facing opponent. locaion's
area object will be OBJECT_INVALID if there is an error.
Description:

*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
location
chs_GetBoardLocation( int nRank, int nFile, int bFacingBlack )
{
   // Start with the assumption that the board ranks run east-west
   // with white to the south
   // Create an Invalid location to return on error
   vector vSquare = Vector(0.0,0.0,0.0 );
   float fFacing = 0.0;
   location lSquare =  Location( OBJECT_INVALID , vSquare, fFacing );
   if( nRank < 1 || nRank > 8 || nFile < 1 || nFile > 8 )
   {
     // Invalid Rank/File parameters
     return lSquare;
   }
   object oWhiteWaypoint= GetWaypointByTag("CHS_WP_WHITE");
   if( !GetIsObjectValid(oWhiteWaypoint) )
   {
     // Could not find white's waypoint
     return lSquare;
   }
   vector vWhite = GetPosition( oWhiteWaypoint );
   object oBlackWaypoint = GetWaypointByTag( "CHS_WP_BLACK" );
   if( !GetIsObjectValid(oBlackWaypoint) )
   {
     // Could not find black's waypoint
     // TODO: calculate assuming standard chessboard terrain
     return lSquare;
   }
   vector vBlack = GetPosition( oBlackWaypoint );
   // math to determine square center ( adjusted to center of square )
   float fRank = IntToFloat(nRank)-0.5;
   float fFile = IntToFloat(nFile)-0.5;
   vSquare.x = vBlack.x +  ( vWhite.x - vBlack.x )*(fFile/8.0);
   vSquare.y = vWhite.y +  ( vBlack.y - vWhite.y )*(fRank/8.0);
   vSquare.z = vBlack.z;
   // use the black or white waypoints to determine which way the piece should face
   if( bFacingBlack )
   {
     lSquare =  Location( GetArea( oWhiteWaypoint) , vSquare, GetFacing(oWhiteWaypoint) );
   }
   else
   {
     lSquare =  Location( GetArea( oWhiteWaypoint) , vSquare, GetFacing(oBlackWaypoint) );
   }
   return lSquare;
}
//::///////////////////////////////////////////////
//:: Name  chs_LocationToRank
//::
//:://////////////////////////////////////////////
/*
Input:
  location - finds the chessboard rank of this location
             or 0 if not on the board.
Output:
  int -  0 =  location not on board 1 = White's King's rank
                                    8 - Black's King's rank
Description:
Tests a location to see if it lies on a chessboard
defined by two waypoints with the tags, CHS_WP_WHITE
and CHS_WP_BLACK. If it does, the chess Rank will be
returned. If not then 0 will be returned.
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int
chs_LocationToRank( location lTest )
{
   // Start with the assumption that the board ranks run east-west
   // with white to the south
   // int bWhiteGreaterThanBlack = TRUE;
   // int bRanksParallelToXAxis = TRUE;
   int nRank = 0; // assume invalid to start with
   float fDistance = 1.0;
   float fBoardHight = 1.0;

   object oWhiteWaypoint= GetWaypointByTag("CHS_WP_WHITE");
   if( !GetIsObjectValid(oWhiteWaypoint) )
   {
     // Could not find white's waypoint
     return 0;
   }
   vector vWhite = GetPosition( oWhiteWaypoint );
   object oBlackWaypoint = GetWaypointByTag( "CHS_WP_BLACK" );
   if( !GetIsObjectValid(oBlackWaypoint) )
   {
     // Could not find black's waypoint
     // TODO: calculate assuming standard chessboard terrain
     return 0;
   }
   vector vBlack = GetPosition( oBlackWaypoint );
   // math to determine what rank and file the loaction is in
   // TODO: test area?
   vector vTest = GetPositionFromLocation( lTest );
   // are we in the box?
   // TODO: test for bWhiteGreaterThanBlack, and bRanksParallelToXAxis
   //       and handle arbitrary board orientation.
   if(  vTest.x > vBlack.x  &&  vTest.x < vWhite.x && vTest.y < vBlack.y  && vTest.y > vWhite.y )
   {
     fDistance =  vTest.y - vWhite.y;
     fBoardHight = vBlack.y - vWhite.y;
     // looks like FloatToInt truncates rather than roundint to the
     // nearest int as the documentation implies
     nRank = FloatToInt((8.0* fDistance/fBoardHight) + 0.999);
     return nRank;
   }
   // The location was not on the board
   return 0;
}
//::///////////////////////////////////////////////
//:: Name  chs_LocationToFile
//::
//:://////////////////////////////////////////////
/*
Input:
  location - finds the chessboard file of this location
             or 0 if it is not on the board.
Output:
  int -  0 =  location not on board
         1 - 8 =  Files A-H
Description:
Tests a location to see if it lies on a chessboard
defined by two waypoints with the tags, CHS_WP_WHITE
and CHS_WP_BLACK. If it does, the ches Rank will be
returned. If not then 0 will be returned.
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int
chs_LocationToFile( location lTest )
{
   // Start with the assumption that the board ranks run east-west
   // with white to the south
   // int bWhiteGreaterThanBlack = TRUE;
   // int bRanksParallelToXAxis = TRUE;
   int nFile = 0; // assume invalid to start with
   float fDistance = 1.0;
   float fBoardWidth = 1.0;

   object oWhiteWaypoint= GetWaypointByTag("CHS_WP_WHITE");
   if( !GetIsObjectValid(oWhiteWaypoint) )
   {
     // Could not find white's waypoint
     return 0;
   }
   vector vWhite = GetPosition( oWhiteWaypoint );
   object oBlackWaypoint = GetWaypointByTag( "CHS_WP_BLACK" );
   if( !GetIsObjectValid(oBlackWaypoint) )
   {
     // Could not find black's waypoint
     // TODO: calculate assuming standard chessboard terrain
     return 0;
   }
   vector vBlack = GetPosition( oBlackWaypoint );
   // math to determine what rank and file the loaction is in
   // TODO: test area?
   vector vTest = GetPositionFromLocation( lTest );
   // are we in the box?
   // TODO: test for bWhiteGreaterThanBlack, and bRanksParallelToXAxis
   //       and handle arbitrary board orientation.
   if(  vTest.x > vBlack.x  &&  vTest.x < vWhite.x && vTest.y < vBlack.y  && vTest.y > vWhite.y )
   {
     fDistance =  vTest.x - vBlack.x;
     fBoardWidth = vWhite.x- vBlack.x;
     nFile = FloatToInt((8.0* fDistance/fBoardWidth) + 0.999);
     return nFile;
   }
   // The location was not on the board
   return 0;
}
//::///////////////////////////////////////////////
//:: Name  chs_SetIndicatorPositon
//::
//:://////////////////////////////////////////////
/*
Input:
int nRank -the chess square's rank 1(white)-8(black)
int nFile -the chess square's file 1(File A)-8(File H)
int bFromMarker - true for blue "from" marker
                - FLASE for red "to" marker
Output:
int -  non zero on success
Description:
Create
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int
chs_SetIndicatorPositon( int nRank, int nFile, int bFromMarker = TRUE )
{
  object oFromShaft = GetNearestObjectByTag("Shaft of Light - Blue"); // , GetPCSpeaker(), 1);
  if(  GetIsObjectValid(oFromShaft) )
  {
     // destroy the old Shaft
     DestroyObject( oFromShaft );
  }
  location lNewFromShaft = chs_GetBoardLocation( nRank, nFile, FALSE );
  if( GetIsObjectValid( GetAreaFromLocation( lNewFromShaft )  ) )
  {
    object oNewFromShaft = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_solblue", lNewFromShaft, TRUE);
    return TRUE;
  }
  return FALSE;
}
//::///////////////////////////////////////////////
//:: Name  chs_SetIndicatorRank
//::
//:://////////////////////////////////////////////
/*
Input:
int nRank -the chess square's rank 1(white)-8(black)
Output:
int -  non zero on success
Description:
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int chs_SetIndicatorRank( int nRank, int bFromMarker )
{
  // Assume a blue shaft of light on file A to start with
  string sMarkerTag = "Shaft of Light - Blue";
  string sMarkerTemplate = "plc_solblue";
  int nFile = 1;
  if( !bFromMarker )
  {
    sMarkerTag = "Shaft of Light - Red";
    sMarkerTemplate = "plc_solred";
  }
  object oObject = GetNearestObjectByTag(sMarkerTag ); // , GetPCSpeaker(), 1);
  if(  GetIsObjectValid(oObject) )
  {
     // destroy the old Shaft but rember its location
     location lOldLocation = GetLocation( oObject );
     // Get the file
     nFile =chs_LocationToFile( lOldLocation );
     if( nFile <1 || nFile > 8 )
     {
       nFile = 1; // revert to a file  on error
     }
     DestroyObject( oObject );
  }
  location lNewShaft = chs_GetBoardLocation( nRank, nFile, FALSE );
  if( GetIsObjectValid( GetAreaFromLocation( lNewShaft )  ) )
  {
    object oNewObject = CreateObject(OBJECT_TYPE_PLACEABLE, sMarkerTemplate, lNewShaft, TRUE);
    return TRUE;
  }
  // Problem getting board location
  return FALSE;
}

//::///////////////////////////////////////////////
//:: Name  chs_SetIndicatorFile
//::
//:://////////////////////////////////////////////
/*
Input:
int nRank -the chess square's rank 1(white)-8(black)
Output:
int -  non zero on success
Description:
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int
chs_SetIndicatorFile( int nFile, int bFromMarker = TRUE )
{
  // Assume a blue shaft of light on the white kings rank
  // to start with
  string sMarkerTag = "Shaft of Light - Blue";
  string sMarkerTemplate = "plc_solblue";
  int nRank = 1;
  if( !bFromMarker )
  {
    sMarkerTag = "Shaft of Light - Red";
    sMarkerTemplate = "plc_solred";
  }
  object oObject = GetNearestObjectByTag(sMarkerTag); // , GetPCSpeaker(), 1);
  location lOldLocation;
  if(  GetIsObjectValid(oObject) )
  {
     // destroy the old Shaft but rember its location
     lOldLocation = GetLocation( oObject );
     // Get the file
     nRank =chs_LocationToRank( lOldLocation );
     if( nRank <1 || nRank > 8 )
     {
       nRank = 1; // revert to a file  on error
     }
     DestroyObject( oObject );
  }
  location lNewShaft = chs_GetBoardLocation( nRank, nFile, FALSE );
  if( GetIsObjectValid( GetAreaFromLocation( lNewShaft )  ) )
  {
    object oNewObject = CreateObject(OBJECT_TYPE_PLACEABLE, sMarkerTemplate, lNewShaft, TRUE);
    return TRUE;
  }
  // Problem getting board location
  return FALSE;
}
//::///////////////////////////////////////////////
//:: Name  chs_getPieceAtLocation
//::
//:://////////////////////////////////////////////
/*
Output:
  object - the pice in the square or OBJECT_INVALID if none
Description:
  I assume the pieces are creatures.
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
object
chs_getPieceAtLocation( location lTest )
{
 WriteTimestampedLogEntry("Start GetPieceAtLocation:");
 // I assume the pieces are creatures
 object oPiece = GetNearestObjectToLocation( OBJECT_TYPE_CREATURE, lTest);
 if( !GetIsObjectValid(oPiece ) )
 {
   PrintString("First Piece was invalid");
   return oPiece;
 }
 PrintString( "Found piece at location: " + GetTag(oPiece ));
 location lPiece = GetLocation( oPiece );
 // Make sure the piece is in the same square as the indicator
 if( chs_LocationToRank(lPiece ) != chs_LocationToRank( lTest ) )
 {
   PrintString( "bad Rank. Piece Rank:");
   PrintInteger( chs_LocationToRank(lPiece ) );
   PrintString( "Location Rank:");
   PrintInteger( chs_LocationToRank(lTest ) );
   return OBJECT_INVALID;
 }
 if( chs_LocationToFile(lPiece ) != chs_LocationToFile( lTest ) )
 {
   PrintString( "bad File. Piece File:");
   PrintInteger( chs_LocationToFile(lPiece ) );
   PrintString( "Location File:");
   PrintInteger( chs_LocationToFile(lTest ) );
   return OBJECT_INVALID;
 }
 return oPiece;
}
//::///////////////////////////////////////////////
//:: Name  chs_MakeIndicatedMove
//::
//:://////////////////////////////////////////////
/*
Output:
  int -  0  if the waypoints that define the board cannot
            be found or if no "piece" is in the same square
            as the source marker.
         1  if the piece was found an moved to an empty square
         2  if the piece was found and captured another piece
Description:
 If an object is found near the source marker it is
 given a command to move to the target markers location
 and any object in the same square as a target marker is
 "captured" ( destroyed ).  No test is made to insure that a move is
 legal or that it is not capturing its own side's piece.
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On: 7/02/02
//:://////////////////////////////////////////////
int
chs_MakeIndicatedMove()
{
  WriteTimestampedLogEntry("Start MakeIndicatedMove:");
  // TODO: add code for battles?
  string sFromMarkerTag = "Shaft of Light - Blue";
  string sFromMarkerTemplate = "plc_solblue";
  string sToMarkerTag = "Shaft of Light - Red";
  string sToMarkerTemplate = "plc_solred";
  object oFromMarker = GetNearestObjectByTag(sFromMarkerTag);
  object oToMarker = GetNearestObjectByTag(sToMarkerTag);
  if(!GetIsObjectValid(oFromMarker))
  {
    PrintString("Could not find from marker");
    return 0;
  }
  if(!GetIsObjectValid(oToMarker))
  {
    PrintString("Could not find to marker");
    return 0;
  }
  location lFromLocation = GetLocation( oFromMarker );
  // make sure we have a piece in this square. I assume the piece is a creature
  object oPieceToMove = chs_getPieceAtLocation( lFromLocation );
  if( !GetIsObjectValid( oPieceToMove ) )
  {
    PrintString("Could not find the Piece to move");
    return 0;
  }
  PrintString("Found a piece to move: "+ GetTag( oPieceToMove));
  location lToLocation = GetLocation( oToMarker );
  object oPieceToCapture = chs_getPieceAtLocation( lToLocation );
  PrintString("Found a piece to capture");
  AssignCommand( oPieceToMove , ActionForceMoveToLocation(lToLocation, FALSE, 10.0 ));
  if( GetIsObjectValid( oPieceToCapture ))
  {
    PrintString("Found a piece to capture: "+ GetTag( oPieceToCapture));
    DestroyObject( oPieceToCapture );
    // we captured a piece so return 2
    return 2;
  }
  // we moved to an empty space so return 1
  return 1;
}




Examples:

I used a conversation with a "ChessMaster" NPC as the UI to move chess pieces.

A script attached to the action taken for the players response of "The piece shall be moved from the C file" might look like this:

NWScript:
#include "itools_chess"
void main()
{
  // Set the "Move From" indicator to the "C" File
  chs_SetIndicatorFile( 3,TRUE);
}




After the to and from indicators are in valid locations the player response
"Move the piece now"

might be implement like this:

NWScript:
#include "itools_chess"
void main()
{
 int iReturn = chs_MakeIndicatedMove();
 if( iReturn == 0 )
 {
   // the indicated move was not valid so make a scream
   PlaySound("as_pl_screamm1");
 }
 if( iReturn == 1 )
 {
   // The indicated move was to an open space, make an evil laugh
   PlaySound("as_pl_laughingm1");
 }
 if( iReturn == 2 )
 {
   // the indicated move captured a piece,  make mob noises
   PlaySound("as_pl_prisinmob1");
 }
}




One know problem is that pieces can be pushed off thier spaces by other pieces. This could be fixed by storing the current location in each piece and sending them back to that location when necessary.

Good Luck and Have fun making chess mods!

⌂ All Scripts ← PreviousNext → 👁 Category List

All Misc Scripts

📄 arena 📄 cast_bless_on_PC 📄 change_music 📄 chess_game 📄 climbing 📄 climbing_002 📄 common_includes_002 📄 cone_aoe 📄 cron 📄 cross_country_travel 📄 daoc_style_graves 📄 determine_time 📄 effects 📄 escort 📄 ez_respawn 📄 faction 📄 floating_text 📄 function_includes 📄 gambling 📄 include_sounds 📄 include_time_date 📄 jail 📄 jail_system 📄 journal_entry 📄 logbook 📄 manage_action_queue 📄 mmorpg_vault 📄 mod_intro 📄 mod_intro_002 📄 mod_intro_003 📄 mod_intro_005 📄 pers_world_database 📄 pers_world_database_002 📄 piller_of_fire 📄 plot_item 📄 portal_system 📄 portal_system_002 📄 puking 📄 quest_escort 📄 rep_per 📄 reward_rp 📄 rotation 📄 save_pc_location_002 📄 save_pc_location_003 📄 skill_checks 📄 skill_checks_002 📄 slot_machine 📄 story 📄 swimming 📄 take20_bypass 📄 vis_waypoint 📄 working_temple 📄 working_temple_002 📄 xp_gold_loss 📄 xp_gold_loss_002 📄 xp_loss_action