working on player AI
This commit is contained in:
@@ -414,3 +414,15 @@ void GameState::RebuildPlayerOptionsFromActiveAttacks( PlayerNumber pn )
|
||||
}
|
||||
GAMESTATE->m_PlayerOptions[pn] = po;
|
||||
}
|
||||
|
||||
int GameState::GetSumOfActiveAttackLevels( PlayerNumber pn )
|
||||
{
|
||||
int iSum = 0;
|
||||
|
||||
for( unsigned s=0; s<NUM_INVENTORY_SLOTS; s++ )
|
||||
if( m_ActiveAttacks[pn][s].fSecsRemaining > 0 )
|
||||
iSum += m_ActiveAttacks[pn][s].level;
|
||||
|
||||
return iSum;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ public:
|
||||
// used in PLAY_MODE_RAVE and PLAY_MODE_BATTLE
|
||||
struct ActiveAttack
|
||||
{
|
||||
AttackLevel level;
|
||||
float fSecsRemaining;
|
||||
CString sModifier;
|
||||
};
|
||||
@@ -172,7 +173,7 @@ public:
|
||||
void LaunchAttack( PlayerNumber target, ActiveAttack aa );
|
||||
void RebuildPlayerOptionsFromActiveAttacks( PlayerNumber pn );
|
||||
void RemoveAllActiveAttacks(); // called on end of song
|
||||
|
||||
int GetSumOfActiveAttackLevels( PlayerNumber pn );
|
||||
|
||||
|
||||
bool HasEarnedExtraStage();
|
||||
|
||||
@@ -17,16 +17,18 @@
|
||||
#include "RageTimer.h"
|
||||
|
||||
|
||||
#define NUM_ITEM_TYPES THEME->GetMetricF("Inventory","NumItemTypes")
|
||||
#define ITEM_DURATION_SECONDS THEME->GetMetricF("Inventory","ItemDurationSeconds")
|
||||
#define ITEM_COMBO( i ) THEME->GetMetricI("Inventory",ssprintf("Item%dCombo",i+1))
|
||||
#define ITEM_EFFECT( i ) THEME->GetMetric ("Inventory",ssprintf("Item%dEffect",i+1))
|
||||
#define NUM_ITEM_TYPES THEME->GetMetricF("Inventory","NumItemTypes")
|
||||
#define ITEM_DURATION_SECONDS THEME->GetMetricF("Inventory","ItemDurationSeconds")
|
||||
#define ITEM_COMBO( i ) THEME->GetMetricI("Inventory",ssprintf("Item%dCombo",i+1))
|
||||
#define ITEM_EFFECT( i ) THEME->GetMetric ("Inventory",ssprintf("Item%dEffect",i+1))
|
||||
#define ITEM_LEVEL( i ) THEME->GetMetricI("Inventory",ssprintf("Item%dLevel",i+1))
|
||||
|
||||
const PlayerNumber OPPOSITE_PLAYER[NUM_PLAYERS] = { PLAYER_2, PLAYER_1 };
|
||||
|
||||
|
||||
struct Item
|
||||
{
|
||||
AttackLevel level;
|
||||
int iCombo;
|
||||
CString sModifier;
|
||||
};
|
||||
@@ -38,6 +40,7 @@ void ReloadItems()
|
||||
for( int i=0; i<NUM_ITEM_TYPES; i++ )
|
||||
{
|
||||
Item item;
|
||||
item.level = (AttackLevel)(ITEM_LEVEL(i)-1);
|
||||
item.iCombo = ITEM_COMBO(i);
|
||||
item.sModifier = ITEM_EFFECT(i);
|
||||
g_Items.push_back( item );
|
||||
@@ -151,10 +154,20 @@ void Inventory::UseItem( int iSlot )
|
||||
return;
|
||||
|
||||
PlayerNumber pnToAttack = OPPOSITE_PLAYER[m_PlayerNumber];
|
||||
|
||||
GameState::ActiveAttack aa;
|
||||
aa.fSecsRemaining = ITEM_DURATION_SECONDS;
|
||||
aa.sModifier = asInventory[iSlot];
|
||||
aa.fSecsRemaining = ITEM_DURATION_SECONDS;
|
||||
aa.level = ATTACK_LEVEL_1;
|
||||
|
||||
// UGLY: Search through g_Items and find out what the attack level for this item is.
|
||||
for( unsigned i=0; i<g_Items.size(); i++ )
|
||||
{
|
||||
if( aa.sModifier == g_Items[i].sModifier )
|
||||
{
|
||||
aa.level = g_Items[i].level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
GAMESTATE->LaunchAttack( pnToAttack, aa );
|
||||
GAMESTATE->RebuildPlayerOptionsFromActiveAttacks( pnToAttack );
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "Combo.h"
|
||||
#include "ScoreDisplay.h"
|
||||
#include "LifeMeter.h"
|
||||
#include "PlayerAI.h"
|
||||
|
||||
#define GRAY_ARROWS_Y THEME->GetMetricF("Player","GrayArrowsY")
|
||||
#define JUDGMENT_Y THEME->GetMetricF("Player","JudgmentY")
|
||||
@@ -39,75 +40,10 @@ CachedThemeMetricI BRIGHT_GHOST_COMBO_THRESHOLD("Player","BrightGhostComboTh
|
||||
#define STOP_DRAWING_AT_PIXELS THEME->GetMetricI("Player","StopDrawingAtPixels")
|
||||
|
||||
/* Distance to search for a note in Step(). */
|
||||
/* Units? */
|
||||
static const float StepSearchDistanceBackwards = 1.0f;
|
||||
static const float StepSearchDistanceForwards = 1.0f;
|
||||
|
||||
struct TapScoreDistribution
|
||||
{
|
||||
float fCumulativeProbability[NUM_TAP_NOTE_SCORES];
|
||||
TapNoteScore GetTapNoteScore()
|
||||
{
|
||||
float fRand = randomf(0,1);
|
||||
for( int i=0; i<NUM_TAP_NOTE_SCORES; i++ )
|
||||
if( fRand <= fCumulativeProbability[i] )
|
||||
return (TapNoteScore)i;
|
||||
ASSERT(0); // the last probability must be 1.0, so we should never get here!
|
||||
return TNS_MARVELOUS;
|
||||
}
|
||||
};
|
||||
TapScoreDistribution TAP_SCORE_DISTRIBUTIONS[NUM_PLAYER_CONTROLLERS] =
|
||||
{
|
||||
// HUMAN
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
1.00f, // TNS_MISS // don't ever hit automatically when human
|
||||
0.00f, // TNS_BOO
|
||||
0.00f, // TNS_GOOD
|
||||
0.00f, // TNS_GREAT
|
||||
0.00f, // TNS_PERFECT
|
||||
0.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_EASY
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.02f, // TNS_MISS
|
||||
0.06f, // TNS_BOO
|
||||
0.10f, // TNS_GOOD
|
||||
0.55f, // TNS_GREAT
|
||||
0.80f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_MEDIUM
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.01f, // TNS_MISS
|
||||
0.02f, // TNS_BOO
|
||||
0.05f, // TNS_GOOD
|
||||
0.45f, // TNS_GREAT
|
||||
0.70f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_HARD
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.005f, // TNS_MISS
|
||||
0.010f, // TNS_BOO
|
||||
0.02f, // TNS_GOOD
|
||||
0.10f, // TNS_GREAT
|
||||
0.50f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_AUTOPLAY
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.00f, // TNS_MISS
|
||||
0.00f, // TNS_BOO
|
||||
0.00f, // TNS_GOOD
|
||||
0.00f, // TNS_GREAT
|
||||
0.00f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
Player::Player()
|
||||
@@ -439,7 +375,7 @@ void Player::Step( int col )
|
||||
}
|
||||
else
|
||||
{
|
||||
score = TAP_SCORE_DISTRIBUTIONS[GAMESTATE->m_PlayerController[m_PlayerNumber]].GetTapNoteScore();
|
||||
score = PlayerAI::GetTapNoteScore( GAMESTATE->m_PlayerController[m_PlayerNumber], GAMESTATE->GetSumOfActiveAttackLevels(m_PlayerNumber) );
|
||||
}
|
||||
|
||||
if( score==TNS_MARVELOUS && !PREFSMAN->m_bMarvelousTiming )
|
||||
@@ -582,7 +518,7 @@ void Player::CrossedRow( int iNoteRow )
|
||||
{
|
||||
if( GetTapNote(t, iNoteRow) != TAP_EMPTY )
|
||||
{
|
||||
TapNoteScore tns = TAP_SCORE_DISTRIBUTIONS[ GAMESTATE->m_PlayerController[m_PlayerNumber] ].GetTapNoteScore();
|
||||
TapNoteScore tns = PlayerAI::GetTapNoteScore( GAMESTATE->m_PlayerController[m_PlayerNumber], GAMESTATE->GetSumOfActiveAttackLevels(m_PlayerNumber) );
|
||||
if( tns!=TNS_MISS )
|
||||
this->Step( t );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "global.h"
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Class: PlayerAI
|
||||
|
||||
Desc: See header.
|
||||
|
||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||
Chris Danford
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "PlayerAI.h"
|
||||
#include "RageUtil.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
struct TapScoreDistribution
|
||||
{
|
||||
float fCumulativeProbability[NUM_TAP_NOTE_SCORES];
|
||||
TapNoteScore GetTapNoteScore( int iDifficultyExponent )
|
||||
{
|
||||
float fRand = randomf(0,1);
|
||||
ASSERT( iDifficultyExponent >= 1 );
|
||||
fRand = powf(fRand, iDifficultyExponent);
|
||||
for( int i=0; i<NUM_TAP_NOTE_SCORES; i++ )
|
||||
if( fRand <= fCumulativeProbability[i] )
|
||||
return (TapNoteScore)i;
|
||||
ASSERT(0); // the last probability must be 1.0, so we should never get here!
|
||||
return TNS_MARVELOUS;
|
||||
}
|
||||
};
|
||||
|
||||
TapScoreDistribution TAP_SCORE_DISTRIBUTIONS[NUM_PLAYER_CONTROLLERS] =
|
||||
{
|
||||
// HUMAN
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
1.00f, // TNS_MISS // don't ever hit automatically when human
|
||||
0.00f, // TNS_BOO
|
||||
0.00f, // TNS_GOOD
|
||||
0.00f, // TNS_GREAT
|
||||
0.00f, // TNS_PERFECT
|
||||
0.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_EASY
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.02f, // TNS_MISS
|
||||
0.06f, // TNS_BOO
|
||||
0.10f, // TNS_GOOD
|
||||
0.55f, // TNS_GREAT
|
||||
0.80f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_MEDIUM
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.01f, // TNS_MISS
|
||||
0.02f, // TNS_BOO
|
||||
0.05f, // TNS_GOOD
|
||||
0.45f, // TNS_GREAT
|
||||
0.70f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_HARD
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.005f, // TNS_MISS
|
||||
0.010f, // TNS_BOO
|
||||
0.03f, // TNS_GOOD
|
||||
0.10f, // TNS_GREAT
|
||||
0.50f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
// CPU_AUTOPLAY
|
||||
{
|
||||
0.00f, // TNS_NONE
|
||||
0.00f, // TNS_MISS
|
||||
0.00f, // TNS_BOO
|
||||
0.00f, // TNS_GOOD
|
||||
0.00f, // TNS_GREAT
|
||||
0.00f, // TNS_PERFECT
|
||||
1.00f, // TNS_MARVELOUS
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
TapNoteScore PlayerAI::GetTapNoteScore( PlayerController pc, int iSumOfAttackLevels )
|
||||
{
|
||||
return TAP_SCORE_DISTRIBUTIONS[pc].GetTapNoteScore( iSumOfAttackLevels+1 );
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef PlayerAI_H
|
||||
#define PlayerAI_H
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Class: PlayerAI
|
||||
|
||||
Desc: .
|
||||
|
||||
Copyright (c) 2001-2002 by the person(s) listed below. All rights reserved.
|
||||
Chris Danford
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "GameConstantsAndTypes.h"
|
||||
|
||||
|
||||
class PlayerAI
|
||||
{
|
||||
public:
|
||||
|
||||
static TapNoteScore PlayerAI::GetTapNoteScore( PlayerController pc, int iSumOfAttackLevels );
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -81,6 +81,7 @@ void RaveHelper::LaunchAttack( AttackLevel al )
|
||||
PlayerNumber pnToAttack = OPPOSITE_PLAYER[m_PlayerNumber];
|
||||
|
||||
GameState::ActiveAttack aa;
|
||||
aa.level = al;
|
||||
aa.fSecsRemaining = ATTACK_DURATION_SECONDS;
|
||||
aa.sModifier = sAttackToGive;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ IntDir=.\../Release6
|
||||
TargetDir=\stepmania\stepmania
|
||||
TargetName=StepMania
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
|
||||
# End Special Build Tool
|
||||
|
||||
@@ -95,7 +95,7 @@ IntDir=.\../Debug6
|
||||
TargetDir=\stepmania\stepmania
|
||||
TargetName=StepMania-debug
|
||||
SOURCE="$(InputPath)"
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PreLink_Cmds=disasm\verinc cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
PostBuild_Cmds=disasm\mapconv $(IntDir)\$(TargetName).map $(TargetDir)\StepMania.vdi ia32.vdi
|
||||
# End Special Build Tool
|
||||
|
||||
@@ -495,6 +495,14 @@ SOURCE=.\NoteTypes.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\PlayerAI.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\PlayerAI.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\PlayerNumber.cpp
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -671,6 +671,12 @@ cl /Zl /nologo /c verstub.cpp /Fo$(IntDir)\
|
||||
<File
|
||||
RelativePath="NotesWriterSM.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="PlayerAI.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="PlayerAI.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="PlayerNumber.cpp">
|
||||
</File>
|
||||
|
||||
Reference in New Issue
Block a user