Added some transitions.

This commit is contained in:
2021-09-26 16:45:27 -07:00
parent 7740bd9930
commit f3a16b9c8c
17 changed files with 406 additions and 87 deletions

View File

@ -0,0 +1,60 @@
/**
* Copyright (c) 2021 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "easing.h"
float easeLinear(float t) {
return t;
}
float easeInQuad(float t) {
return t * t;
}
float easeOutQuad(float t) {
return t * (2 - t);
}
float easeInOutQuad(float t) {
return t < .5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
}
float easeInCubic(float t) {
return t * t * t;
}
float easeOutCubic(float t) {
return (t - 1) * (t - 1) * (t - 1) + 1;
}
float easeInOutCubic(float t) {
return t < .5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
}
float easeInQuart(float t) {
return t * t * t * t;
}
float easeOutQuart(float t) {
return 1 - (t-1)*(t-1)*(t-1)*(t-1);
}
float easeInOutQuart(float t) {
return t < .5 ? 8*t*t*t*t : 1-8*(t-1)*(t-1)*(t-1)*(t-1);
}
float easeInQuint(float t) {
return t*t*t*t*t;
}
float easeOutQuint(float t) {
return 1 + (t-1)*(t-1)*(t-1)*(t-1)*(t-1);
}
float easeInOutQuint(float t) {
return t<.5 ? 16*t*t*t*t*t : 1+16*(t-1)*(t-1)*(t-1)*(t-1)*(t-1);
}

View File

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
typedef float easefunction_t(float t);
/** /**
* Returns the ease time for a given real time duration span. * Returns the ease time for a given real time duration span.
* @param start At what point in time the animation started * @param start At what point in time the animation started
@ -15,22 +17,16 @@
*/ */
#define easeTimeToEase(start, current, duration) ((current-start)/duration) #define easeTimeToEase(start, current, duration) ((current-start)/duration)
float easeLinear(float t);
// Easing Functions, most were sourced from https://gist.github.com/gre/1650294 float easeInQuad(float t);
#define easeLinear(t) t float easeOutQuad(float t);
float easeInOutQuad(float t);
#define easeInQuad(t) (t*t) float easeInCubic(float t);
#define easeOutQuad(t) (t*(2-t)) float easeOutCubic(float t);
#define easeInOutQuad(t) (t < .5 ? 2*t*t : -1+(4-2*t)*t) float easeInOutCubic(float t);
float easeInQuart(float t);
#define easeInCubic(t) (t*t*t) float easeOutQuart(float t);
#define easeOutCubic(t) ((t-1)*(t-1)*(t-1)+1) float easeInOutQuart(float t);
#define easeInOutCubic(t) (t < .5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1) float easeInQuint(float t);
float easeOutQuint(float t);
#define easeInQuart(t) (t*t*t*t) float easeInOutQuint(float t);
#define easeOutQuart(t) (1 - (t-1)*(t-1)*(t-1)*(t-1))
#define easeInOutQuart(t) (t < .5 ? 8*t*t*t*t : 1-8*(t-1)*(t-1)*(t-1)*(t-1))
#define easeInQuint(t) (t*t*t*t*t)
#define easeOutQuint(t) (1 + (t-1)*(t-1)*(t-1)*(t-1)*(t-1))
#define easeInOutQuint(t) (t<.5 ? 16*t*t*t*t*t : 1+16*(t-1)*(t-1)*(t-1)*(t-1)*(t-1))

View File

@ -7,6 +7,32 @@
#include "timeline.h" #include "timeline.h"
void _timelineActionDeltaUpdateStart(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
if(action->data == NULL) return;
*((float *)action->data) = timeline->initials[i];
}
void _timelineActionDeltaUpdateDuration(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
float n;
if(action->data == NULL) return;
n = timeline->easings[i](
timelineActionGetTimeRaw(timeline, action)
);
*((float *)action->data) = timeline->initials[i] + (timeline->deltas[i] * n);
}
void _timelineActionDeltaUpdateEnd(
timeline_t *timeline, timelineaction_t *action, uint8_t i
) {
if(action->data == NULL) return;
*((float *)action->data) = timeline->initials[i] + timeline->deltas[i];
}
void timelineInit(timeline_t *timeline) { void timelineInit(timeline_t *timeline) {
timeline->current = 0; timeline->current = 0;
timeline->diff = 0; timeline->diff = 0;
@ -68,10 +94,48 @@ bool timelineIsFinished(timeline_t *timeline) {
timelineaction_t * timelineAddAction(timeline_t *timeline, float start, timelineaction_t * timelineAddAction(timeline_t *timeline, float start,
float duration float duration
) { ) {
if(timeline->actionCount == TIMELINE_ACTION_COUNT_MAX) return NULL;
timelineaction_t *action = timeline->actions + (timeline->actionCount++); timelineaction_t *action = timeline->actions + (timeline->actionCount++);
action->loop = false; action->loop = false;
action->start = start, action->duration = duration; action->start = start, action->duration = duration;
action->onStart = action->onEnd = action->onDuration = NULL; action->onStart = action->onEnd = action->onDuration = NULL;
return action; return action;
}
timelineaction_t * timelineAddDeltaAction(timeline_t *timeline,
float start, float duration, float initial, float delta,
easefunction_t *easing, float *destination
) {
timelineaction_t *action;
timeline->initials[timeline->actionCount] = initial;
timeline->deltas[timeline->actionCount] = delta;
timeline->easings[timeline->actionCount] = (
easing == NULL ? &easeLinear : easing
);
action = timelineAddAction(timeline, start, duration);
action->data = destination;
action->onStart = &_timelineActionDeltaUpdateStart;
action->onDuration = &_timelineActionDeltaUpdateDuration;
action->onEnd = &_timelineActionDeltaUpdateEnd;
return action;
}
timelineaction_t * timelineAddDeltaActionTo(timeline_t *timeline,
float start, float duration, float initial, float end,
easefunction_t *easing, float *destination
) {
return timelineAddDeltaAction(
timeline, start, duration, initial, end-initial, easing, destination
);
}
float timelineActionGetTimeRaw(timeline_t *timeline, timelineaction_t *action) {
return (timeline->current - action->start) / action->duration;
}
float timelineActionGetTime(timeline_t *tl, timelineaction_t *at) {
return mathClamp(timelineActionGetTimeRaw(tl, at), 0, 1);
}
void timelineClear(timeline_t *timeline) {
timeline->actionCount = 0;
} }

View File

@ -5,6 +5,8 @@
#pragma once #pragma once
#include "../../libs.h" #include "../../libs.h"
#include "../../util/math.h"
#include "easing.h"
/** Maximum number of actions a timeline can support, smaller than 0xFF */ /** Maximum number of actions a timeline can support, smaller than 0xFF */
#define TIMELINE_ACTION_COUNT_MAX 128 #define TIMELINE_ACTION_COUNT_MAX 128
@ -72,6 +74,14 @@ typedef struct _timeline_t {
/** Actions within the timeline */ /** Actions within the timeline */
timelineaction_t actions[TIMELINE_ACTION_COUNT_MAX]; timelineaction_t actions[TIMELINE_ACTION_COUNT_MAX];
/** For delta actions, storage of the initial values */
float initials[TIMELINE_ACTION_COUNT_MAX];
/** For delta actions, storage of their deltas. */
float deltas[TIMELINE_ACTION_COUNT_MAX];
/** Easing functions to use for delta functions */
easefunction_t *easings[TIMELINE_ACTION_COUNT_MAX];
uint8_t actionCount; uint8_t actionCount;
} timeline_t; } timeline_t;
@ -110,4 +120,68 @@ bool timelineIsFinished(timeline_t *timeline);
*/ */
timelineaction_t * timelineAddAction(timeline_t *timeline, float start, timelineaction_t * timelineAddAction(timeline_t *timeline, float start,
float duration float duration
); );
/**
* Add a special action kind that can treat delta style animations. These are
* animations that have a start, and an end value, that will be tracked for you
* and keep you up to date.
*
* @param timeline Timeline to add to.
* @param start Starting time.
* @param duration Animation duration.
* @param initial Initial value for the animation.
* @param delta Delta value for the animation.
* @param easing Pointer to an easing function to use, set to NULL for linear.
* @param destination A constant floating point to update.
* @return The queued timeline action.
*/
timelineaction_t * timelineAddDeltaAction(timeline_t *timeline,
float start, float duration, float initial, float delta,
easefunction_t *easing, float *destination
);
/**
* Shorthand for timelineAddDeltaAction that will calculate the delta based on
* and end position.
*
* @param timeline Timeline to add to.
* @param start Starting time.
* @param duration Animation duration.
* @param initial Initial value for the animation.
* @param end End value for the animation.
* @param easing Pointer to an easing function to use, set to NULL for linear.
* @param destination A constant floating point to update.
* @return The queued timeline action.
*/
timelineaction_t * timelineAddDeltaActionTo(timeline_t *timeline,
float start, float duration, float initial, float end,
easefunction_t *easing, float *destination
);
/**
* Gets the timeline action's animation time. This is a representation of
* 0 - 1 where 0 means the animation is at the start, and 1 meaning the
* animation is at full completion. This is not clamped and may exceed 1.
*
* @param timeline Timeline the action belongs to.
* @param action Action itself.
* @return 0 - 1+, where 0 = start, 1 = duration, >1 is time since duration.
*/
float timelineActionGetTimeRaw(timeline_t *timeline, timelineaction_t *action);
/**
* Gets the timeline action's animation time between 0 - 1, clamped.
*
* @param tl Timeline to get delta from.
* @param at Timeline action.
* @return 0 - 1, where 0 = start, 1 = duration.
*/
float timelineActionGetTime(timeline_t *tl, timelineaction_t *at);
/**
* Removes all actions from the timeline.
*
* @param timeline Timeline to clear.
*/
void timelineClear(timeline_t *timeline);

View File

@ -15,6 +15,12 @@ void cameraLookAt(camera_t *camera,
matrixLookAt(&camera->view, x, y, z, targetX, targetY, targetZ, 0, 1, 0); matrixLookAt(&camera->view, x, y, z, targetX, targetY, targetZ, 0, 1, 0);
} }
void cameraLookAtStruct(camera_t *camera, cameralookat_t look) {
cameraLookAt(camera,
look.x, look.y, look.z, look.lookX, look.lookY, look.lookZ
);
}
void cameraLook(camera_t *camera, void cameraLook(camera_t *camera,
float x, float y, float z, float x, float y, float z,
float pitch, float yaw, float roll float pitch, float yaw, float roll

View File

@ -17,6 +17,10 @@ typedef struct {
matrix_t projection; matrix_t projection;
} camera_t; } camera_t;
typedef struct {
float x, y, z, lookX, lookY, lookZ;
} cameralookat_t;
/** /**
* Make a camera look at a position in world space while itself being positioned * Make a camera look at a position in world space while itself being positioned
* within world space. * within world space.
@ -34,6 +38,14 @@ void cameraLookAt(camera_t *camera,
float targetX, float targetY, float targetZ float targetX, float targetY, float targetZ
); );
/**
* Shorthand for look at that uses the look struct.
*
* @param camera Camera to position.
* @param look Look vectors.
*/
void cameraLookAtStruct(camera_t *camera, cameralookat_t look);
/** /**
* Make a camera look in a direction based on a rotation direction. * Make a camera look in a direction based on a rotation direction.
* *

View File

@ -59,7 +59,7 @@ void _pokerGameActionBetOnUpdate(
break; break;
case POKER_TURN_TYPE_ALL_IN: case POKER_TURN_TYPE_ALL_IN:
discussion.reason = POKER_DISCUSSION_REASON_PLAYER_CALLING; discussion.reason = POKER_DISCUSSION_REASON_PLAYER_ALL_IN;
break; break;
case POKER_TURN_TYPE_FOLD: case POKER_TURN_TYPE_FOLD:

View File

@ -77,6 +77,13 @@ void pokerDiscussionGet(
discussion->emotions[0] = VN_CHARACTER_EMOTION_BOASTFUL; discussion->emotions[0] = VN_CHARACTER_EMOTION_BOASTFUL;
break; break;
case POKER_DISCUSSION_REASON_PLAYER_ALL_IN:
discussion->count++;
discussion->messages[0] = "All in.";
discussion->players[0] = data->playerCause;
discussion->emotions[0] = VN_CHARACTER_EMOTION_ANGRY_PROUD;
break;
// Flops // Flops
case POKER_DISCUSSION_REASON_FLOP: case POKER_DISCUSSION_REASON_FLOP:
discussion->count++; discussion->count++;

View File

@ -23,9 +23,10 @@
#define POKER_DISCUSSION_REASON_PLAYER_CHECKING 0x05 #define POKER_DISCUSSION_REASON_PLAYER_CHECKING 0x05
#define POKER_DISCUSSION_REASON_PLAYER_CALLING 0x06 #define POKER_DISCUSSION_REASON_PLAYER_CALLING 0x06
#define POKER_DISCUSSION_REASON_PLAYER_RAISING 0x07 #define POKER_DISCUSSION_REASON_PLAYER_RAISING 0x07
#define POKER_DISCUSSION_REASON_FLOP 0x08 #define POKER_DISCUSSION_REASON_PLAYER_ALL_IN 0x08
#define POKER_DISCUSSION_REASON_DEAL 0x09 #define POKER_DISCUSSION_REASON_FLOP 0x09
#define POKER_DISCUSSION_REASON_BETTING_DONE 0x0A #define POKER_DISCUSSION_REASON_DEAL 0x0A
#define POKER_DISCUSSION_REASON_BETTING_DONE 0x0B
typedef struct { typedef struct {
pokergame_t *poker; pokergame_t *poker;

View File

@ -14,6 +14,9 @@ void pokerWorldInit(
) { ) {
vncharacter_t *character; vncharacter_t *character;
uint8_t i; uint8_t i;
world->seat = POKER_GAME_SEAT_DEALER;
world->seatTime = 0;
// Initialize the skywal // Initialize the skywal
skywallInit(&world->skywall); skywallInit(&world->skywall);
@ -34,16 +37,21 @@ void pokerWorldInit(
} }
} }
void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex) { void pokerWorldLookAtPlayer(
uint8_t seat; vnscene_t *scene, uint8_t playerIndex
seat = pokerGameSeatFromIndex(playerIndex); ) {
scene->cameraLookX = POKER_WORLD_SEAT_POSITION_X(seat); uint8_t seat = pokerGameSeatFromIndex(playerIndex);
scene->cameraLookZ = POKER_WORLD_SEAT_POSITION_Z(seat); vnSceneLookAt(scene,
scene->cameraLook.x,
scene->cameraLook.y,
scene->cameraLook.z,
POKER_WORLD_SEAT_POSITION_X(seat),
scene->cameraLook.lookY,
POKER_WORLD_SEAT_POSITION_Z(seat)
);
} }
void pokerWorldRender( void pokerWorldRender(pokerworld_t *world, pokergameassets_t *assets) {
pokerworld_t *world, pokergameassets_t *assets
) {
// Render the wall // Render the wall
shaderUseTexture(&assets->shader, &assets->roomTexture); shaderUseTexture(&assets->shader, &assets->roomTexture);
shaderUsePosition(&assets->shader, 0,2,0, 0,0,0); shaderUsePosition(&assets->shader, 0,2,0, 0,0,0);

View File

@ -9,11 +9,13 @@
#include "../../libs.h" #include "../../libs.h"
#include "../../display/shader.h" #include "../../display/shader.h"
#include "../../display/primitive.h" #include "../../display/primitive.h"
#include "../../display/animation/easing.h"
#include "../../display/primitives/skywall.h" #include "../../display/primitives/skywall.h"
#include "../../vn/vnscene.h" #include "../../vn/vnscene.h"
#include "../../vn/vncharacter.h" #include "../../vn/vncharacter.h"
#include "../../poker/player.h" #include "../../poker/player.h"
#include "../../poker/dealer.h" #include "../../poker/dealer.h"
#include "../../engine/engine.h"
#include "pokergameassets.h" #include "pokergameassets.h"
@ -48,6 +50,10 @@
typedef struct { typedef struct {
primitive_t skywall; primitive_t skywall;
/** Which seat the game should look at */
uint8_t seat;
float seatTime;
} pokerworld_t; } pokerworld_t;
@ -66,12 +72,14 @@ void pokerWorldInit(
/** /**
* Adjusts the camera to look at a specific player. You can use this to look at * Adjusts the camera to look at a specific player. You can use this to look at
* the dealer by referencing the POKER_PLAYER_COUNT as the index. * the dealer by referencing the POKER_PLAYER_HUMAN_INDEX as the index.
* *
* @param scene Scene to adjust. * @param scene Visual Novel Engine scene.
* @param playerIndex Player index to look at. * @param playerIndex Player index to look at.
*/ */
void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex); void pokerWorldLookAtPlayer(
vnscene_t *scene, uint8_t playerIndex
);
/** /**
* Render the poker world. * Render the poker world.
@ -79,9 +87,7 @@ void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex);
* @param world Poker Game World. * @param world Poker Game World.
* @param assets Assets to use. * @param assets Assets to use.
*/ */
void pokerWorldRender( void pokerWorldRender(pokerworld_t *world, pokergameassets_t *assets);
pokerworld_t *world, pokergameassets_t *assets
);
/** /**
* Cleanup the poker world. * Cleanup the poker world.

View File

@ -14,6 +14,7 @@ bool pokerPlayerIsAlive(pokerplayer_t *player) {
void pokerPlayerReset(pokerplayer_t *player) { void pokerPlayerReset(pokerplayer_t *player) {
player->cardCount = 0; player->cardCount = 0;
player->currentBet = 0; player->currentBet = 0;
player->timesRaised = 0;
// Invert then bitwise AND to turn off. // Invert then bitwise AND to turn off.
player->state &= ~( player->state &= ~(

View File

@ -53,6 +53,9 @@ typedef struct {
/** Current bet in current round player has placed */ /** Current bet in current round player has placed */
int32_t currentBet; int32_t currentBet;
/** How many times for the current flop that the player has raised */
int32_t timesRaised;
} pokerplayer_t; } pokerplayer_t;
/** /**

View File

@ -9,12 +9,13 @@
pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) {
int32_t random, maxBet, bluffBet, callBet; int32_t random, maxBet, bluffBet, callBet;
float winProbability, expectedGain, confidence, potOdds; float confidence, expectedGain, potOdds;
bool isBluff; bool isBluff;
int32_t amount; int32_t amount;
pokerplayer_t *player; pokerplayer_t *player;
pokerplayerwinning_t winning; pokerplayerwinning_t winning;
uint8_t i, cardNumber0, cardNumber1, suitNumber0, suitNumber1; uint8_t i, cardNumber0, cardNumber1, suitNumber0, suitNumber1;
pokerturn_t turn;
player = poker->players + playerIndex; player = poker->players + playerIndex;
@ -23,42 +24,53 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) {
return pokerTurnOut(poker, playerIndex); return pokerTurnOut(poker, playerIndex);
} }
// Now we basically need to determine the AI's action here. The AI really only // The following logic is heavily inspired by;
// needs to do one thing, decide whether or not they want to Bet or Not. // https://github.com/gorel/C-Poker-AI/blob/master/src/common/pokerai.c
// In future I may make checking optional, but for now there's really no // But with some changes and smarts added by me. The original source code will
// reason not to. // essentially just run a crap tun of simulated games and get the times that
pokerWinnerPlayerGet(&poker->dealer, player, &winning); // they are expected to win from those games, but I'm just going to use the
// odds of the winning hand.
// Get the current winning hand.
// Is this preflop?
if(poker->dealer.cardsFacing == 0 && player->cardCount >= 2) { if(poker->dealer.cardsFacing == 0 && player->cardCount >= 2) {
// Get the hand weight
cardNumber0 = cardGetNumber(player->cards[0]); cardNumber0 = cardGetNumber(player->cards[0]);
cardNumber1 = cardGetNumber(player->cards[1]); cardNumber1 = cardGetNumber(player->cards[1]);
suitNumber0 = cardGetSuit(player->cards[0]); suitNumber0 = cardGetSuit(player->cards[0]);
suitNumber1 = cardGetSuit(player->cards[1]); suitNumber1 = cardGetSuit(player->cards[1]);
// Get delta between cards
i = mathAbs(cardNumber0 - cardNumber1); i = mathAbs(cardNumber0 - cardNumber1);
// Get card weight
confidence = (float)cardNumber0 + (float)cardNumber1; confidence = (float)cardNumber0 + (float)cardNumber1;
if(cardNumber0 == cardNumber1) { if(cardNumber0 == cardNumber1) {// Pairs
confidence += 6; confidence += 6;
} else if(suitNumber0 == suitNumber1) { } else if(suitNumber0 == suitNumber1) {// Same suit
confidence += 4; confidence += 4;
} }
// Get difference from cards for guessing flush
if(i > 4) { if(i > 4) {
confidence -= 4; confidence -= 4;
} else if(i > 2) { } else if(i > 2) {
confidence -= i; confidence -= i;
} }
// Get the confidence delta 0-1
confidence = confidence / 30.0f; confidence = confidence / 30.0f;
} else { } else {
// Simulate my hand being the winning hand, use that as the confidence
pokerWinnerPlayerGet(&poker->dealer, player, &winning);
confidence = pokerWinnerGetTypeConfidence(winning.type); confidence = pokerWinnerGetTypeConfidence(winning.type);
} }
// Now we know how confident the AI is, let's put a chip value to that weight
// How many chips to call?
callBet = poker->bet.currentBet - player->currentBet; callBet = poker->bet.currentBet - player->currentBet;
winProbability = confidence;
// Do they need chips to call, or is it possible to check?
if(callBet > 0) { if(callBet > 0) {
potOdds = (float)callBet / ((float)callBet + (float)poker->bet.pot); potOdds = (float)callBet / ((float)callBet + (float)poker->bet.pot);
} else { } else {
@ -66,26 +78,36 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) {
1.0f / (float)pokerBetGetRemainingPlayerCount(&poker->bet, poker->players) 1.0f / (float)pokerBetGetRemainingPlayerCount(&poker->bet, poker->players)
); );
} }
expectedGain = winProbability / potOdds;
// Now determine the expected ROI
expectedGain = confidence / potOdds;
// Now get a random 0-100
random = randInt32() % 100; random = randInt32() % 100;
maxBet = (int32_t)(poker->bet.currentBet / 1.75f) - (random / 2);//?
maxBet -= callBet;//? // Determine the max bet that the AI is willing to make
maxBet = (int32_t)(poker->bet.currentBet / 1.75f) - (random / 2) - callBet;
// Determine what's a good bluff bet.
bluffBet = random * maxBet / 100 / 2; bluffBet = random * maxBet / 100 / 2;
// Now prep the output
isBluff = false; isBluff = false;
amount = 0; amount = 0;
if(expectedGain < 0.8 && winProbability < 0.8) { // Now the actual AI can happen. This is basically a weight to confidence
// ratio. The higher the gains and the confidence then the more likely the AI
// is to betting. There are also bluff chances within here.
if(expectedGain < 0.8 && confidence < 0.8) {
if(random < 95) { if(random < 95) {
amount = 0;//FOLD amount = 0;
} else { } else {
amount = bluffBet; amount = bluffBet;
isBluff = true; isBluff = true;
} }
} else if ((expectedGain < 1.0 && winProbability < 0.85) || winProbability < 0.1) { } else if ((expectedGain < 1.0 && confidence < 0.85) || confidence < 0.1) {
if (random < 80) { if (random < 80) {
amount = 0;//FOLD amount = 0;
} else if(random < 5) { } else if(random < 5) {
amount = callBet; amount = callBet;
isBluff = true; isBluff = true;
@ -93,13 +115,13 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) {
amount = bluffBet; amount = bluffBet;
isBluff = true; isBluff = true;
} }
} else if ((expectedGain < 1.3 && winProbability < 0.9) || winProbability < 0.5) { } else if ((expectedGain < 1.3 && confidence < 0.9) || confidence < 0.5) {
if (random < 60 || winProbability < 0.5) { if (random < 60 || confidence < 0.5) {
amount = callBet; amount = callBet;
} else { } else {
amount = maxBet; amount = maxBet;
} }
} else if (winProbability < 0.95 || poker->dealer.cardsFacing < 0x04) { } else if (confidence < 0.95 || poker->dealer.cardsFacing < 0x04) {
if(random < 30) { if(random < 30) {
amount = callBet; amount = callBet;
} else { } else {
@ -109,21 +131,24 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) {
amount = (poker->bet.currentBet - callBet) * 9 / 10; amount = (poker->bet.currentBet - callBet) * 9 / 10;
} }
// Let's not get caught in a raising loop with AI.
if(player->timesRaised >= POKER_TURN_MAX_RAISES) amount = callBet;
printf("Raw Amount %i\n", amount); // Did we actually bet?
// TODO: Make sure we don't get stuck in a raise loop.
if(amount > 0) { if(amount > 0) {
amount = mathMin(amount, callBet); amount = mathMin(amount, callBet);
return pokerTurnRaise(poker, playerIndex, amount); turn = pokerTurnRaise(poker, playerIndex, amount);
} turn.confidence = confidence;
} else if(pokerTurnCanPlayerCheck(poker, playerIndex)) {
if(pokerTurnCanPlayerCheck(poker, playerIndex)) { turn = pokerTurnCheck(poker, playerIndex);
return pokerTurnCheck(poker, playerIndex); turn.confidence = 1;
} else {
turn = pokerTurnFold(poker, playerIndex);
turn.confidence = 1 - confidence;
} }
// Nothing worth doing, so let's just fold here.
return pokerTurnFold(poker, playerIndex); return turn;
} }
void pokerTurnAction(poker_t *poker, pokerplayer_t *player, pokerturn_t *turn) { void pokerTurnAction(poker_t *poker, pokerplayer_t *player, pokerturn_t *turn) {
@ -132,14 +157,17 @@ void pokerTurnAction(poker_t *poker, pokerplayer_t *player, pokerturn_t *turn) {
case POKER_TURN_TYPE_CALL: case POKER_TURN_TYPE_CALL:
case POKER_TURN_TYPE_ALL_IN: case POKER_TURN_TYPE_ALL_IN:
pokerBetPlayer(&poker->bet, player, turn->chips); pokerBetPlayer(&poker->bet, player, turn->chips);
player->timesRaised++;
break; break;
case POKER_TURN_TYPE_CHECK: case POKER_TURN_TYPE_CHECK:
pokerBetPlayer(&poker->bet, player, 0); pokerBetPlayer(&poker->bet, player, 0);
player->timesRaised = 0;
break; break;
case POKER_TURN_TYPE_FOLD: case POKER_TURN_TYPE_FOLD:
player->state |= POKER_PLAYER_STATE_FOLDED; player->state |= POKER_PLAYER_STATE_FOLDED;
player->timesRaised = 0;
break; break;
} }

View File

@ -19,6 +19,8 @@
#define POKER_TURN_TYPE_CALL_ALL_IN 0x04 #define POKER_TURN_TYPE_CALL_ALL_IN 0x04
#define POKER_TURN_TYPE_CHECK 0x05 #define POKER_TURN_TYPE_CHECK 0x05
#define POKER_TURN_MAX_RAISES 0x02
/** The turn that a player/the AI decided to do for its turn */ /** The turn that a player/the AI decided to do for its turn */
typedef struct { typedef struct {
/** What type of action the turn is */ /** What type of action the turn is */

View File

@ -12,12 +12,16 @@ void vnSceneInit(vnscene_t *scene, font_t *font, texture_t *text) {
vnConversationInit(&scene->conversation, font, text); vnConversationInit(&scene->conversation, font, text);
scene->conversation.textbox.linesMax = 3; scene->conversation.textbox.linesMax = 3;
scene->cameraX = 0; // Init the animation
scene->cameraY = 0; timelineInit(&scene->timeline);
scene->cameraZ = 0;
scene->cameraLookX = 0; // Reset Camera
scene->cameraLookY = 0; scene->cameraLook.x = 0;
scene->cameraLookZ = -5; scene->cameraLook.y = 0;
scene->cameraLook.z = 0;
scene->cameraLook.lookX = 0;
scene->cameraLook.lookY = 0;
scene->cameraLook.lookZ = 0;
// Reset character count // Reset character count
scene->characterCount = 0x00; scene->characterCount = 0x00;
@ -26,6 +30,9 @@ void vnSceneInit(vnscene_t *scene, font_t *font, texture_t *text) {
void vnSceneUpdate(vnscene_t *scene, engine_t *engine) { void vnSceneUpdate(vnscene_t *scene, engine_t *engine) {
uint8_t i; uint8_t i;
// Tick the animations.
timelineUpdate(&scene->timeline, engine->time.delta);
// Update the conversation // Update the conversation
vnConversationUpdate(&scene->conversation, engine); vnConversationUpdate(&scene->conversation, engine);
@ -40,11 +47,8 @@ void vnSceneDispose(vnscene_t *scene) {
} }
void vnSceneRenderWorld(vnscene_t *scene, engine_t *engine, shader_t *shader) { void vnSceneRenderWorld(vnscene_t *scene, engine_t *engine, shader_t *shader) {
// Adjust 3D Space position // Adjust Camera Position.
cameraLookAt(&scene->camera, cameraLookAtStruct(&scene->camera, scene->cameraLook);
scene->cameraX, scene->cameraY, scene->cameraZ,
scene->cameraLookX, scene->cameraLookY, scene->cameraLookZ
);
// Set Camera Perspective // Set Camera Perspective
cameraPerspective(&scene->camera, 35, cameraPerspective(&scene->camera, 35,
@ -90,4 +94,45 @@ void vnSceneRenderGui(vnscene_t *scene, engine_t *engine, shader_t *shader) {
// Render Conversation Element // Render Conversation Element
vnConversationRender(&scene->conversation, engine, shader); vnConversationRender(&scene->conversation, engine, shader);
}
void vnSceneLookAt(vnscene_t *scene,
float x, float y, float z, float lookX, float lookY, float lookZ
) {
float d, s;
timeline_t *t;
easefunction_t *f;
d = 1.0f;
s = scene->timeline.current;
t = &scene->timeline;
f = &easeOutQuart;
// Clear the timeline
timelineClear(t);
// Positions
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.x, x, f, &scene->cameraLook.x
);
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.y, y, f, &scene->cameraLook.y
);
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.z, z, f, &scene->cameraLook.z
);
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.lookX, lookX, f, &scene->cameraLook.lookX
);
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.lookY, lookY, f, &scene->cameraLook.lookY
);
timelineAddDeltaActionTo(t, s, d,
scene->cameraLook.lookZ, lookZ, f, &scene->cameraLook.lookZ
);
}
void vnSceneLookAtCharacter(vnscene_t *scene, uint8_t c, float distance) {
vncharacter_t *character = scene->characters + c;
} }

View File

@ -12,17 +12,19 @@
#include "ui/vntextbox.h" #include "ui/vntextbox.h"
#include "../display/camera.h" #include "../display/camera.h"
#include "../display/shader.h" #include "../display/shader.h"
#include "../display/animation/timeline.h"
#include "../display/animation/easing.h"
#include "../util/math.h"
/** Maximum number of Visual Novel Characters the scene can support */ /** Maximum number of Visual Novel Characters the scene can support */
#define VN_SCENE_CHARACTERS_MAX 6 #define VN_SCENE_CHARACTERS_MAX 6
#define VN_SCENE_DISTANCE_DEFAULT -5.0f
typedef struct { typedef struct {
float cameraX; timeline_t timeline;
float cameraY;
float cameraZ; // Camera Targets
float cameraLookX; cameralookat_t cameraLook;
float cameraLookY;
float cameraLookZ;
/** Camera used for rendering, updated frequently */ /** Camera used for rendering, updated frequently */
camera_t camera; camera_t camera;
@ -45,4 +47,8 @@ void vnSceneRenderWorld(vnscene_t *scene, engine_t *engine, shader_t *shader);
void vnSceneRenderCharacters(vnscene_t *scene, shader_t *shader); void vnSceneRenderCharacters(vnscene_t *scene, shader_t *shader);
void vnSceneRenderGui(vnscene_t *scene, engine_t *engine, shader_t *shader); void vnSceneRenderGui(vnscene_t *scene, engine_t *engine, shader_t *shader);
void vnSceneLookAt(vnscene_t *scene,
float x, float y, float z, float lookX, float lookY, float lookZ
);