From 32afdfa17f2dc19ee244a235183fccacb1eb69e6 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 26 Sep 2021 16:45:27 -0700 Subject: [PATCH] Added some transitions. --- src/display/animation/easing.c | 60 ++++++++++++++++++++++ src/display/animation/easing.h | 34 ++++++------ src/display/animation/timeline.c | 66 +++++++++++++++++++++++- src/display/animation/timeline.h | 76 ++++++++++++++++++++++++++- src/display/camera.c | 6 +++ src/display/camera.h | 12 +++++ src/game/poker/actions/bet.c | 2 +- src/game/poker/pokerdiscussion.c | 7 +++ src/game/poker/pokerdiscussion.h | 7 +-- src/game/poker/pokerworld.c | 24 ++++++--- src/game/poker/pokerworld.h | 18 ++++--- src/poker/player.c | 1 + src/poker/player.h | 3 ++ src/poker/turn.c | 88 +++++++++++++++++++++----------- src/poker/turn.h | 2 + src/vn/vnscene.c | 67 ++++++++++++++++++++---- src/vn/vnscene.h | 20 +++++--- 17 files changed, 406 insertions(+), 87 deletions(-) create mode 100644 src/display/animation/easing.c diff --git a/src/display/animation/easing.c b/src/display/animation/easing.c new file mode 100644 index 00000000..babbb2c3 --- /dev/null +++ b/src/display/animation/easing.c @@ -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); +} \ No newline at end of file diff --git a/src/display/animation/easing.h b/src/display/animation/easing.h index 05c32769..fef1e1f3 100644 --- a/src/display/animation/easing.h +++ b/src/display/animation/easing.h @@ -6,6 +6,8 @@ */ #pragma once +typedef float easefunction_t(float t); + /** * Returns the ease time for a given real time duration span. * @param start At what point in time the animation started @@ -15,22 +17,16 @@ */ #define easeTimeToEase(start, current, duration) ((current-start)/duration) - -// Easing Functions, most were sourced from https://gist.github.com/gre/1650294 -#define easeLinear(t) t - -#define easeInQuad(t) (t*t) -#define easeOutQuad(t) (t*(2-t)) -#define easeInOutQuad(t) (t < .5 ? 2*t*t : -1+(4-2*t)*t) - -#define easeInCubic(t) (t*t*t) -#define easeOutCubic(t) ((t-1)*(t-1)*(t-1)+1) -#define easeInOutCubic(t) (t < .5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1) - -#define easeInQuart(t) (t*t*t*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)) \ No newline at end of file +float easeLinear(float t); +float easeInQuad(float t); +float easeOutQuad(float t); +float easeInOutQuad(float t); +float easeInCubic(float t); +float easeOutCubic(float t); +float easeInOutCubic(float t); +float easeInQuart(float t); +float easeOutQuart(float t); +float easeInOutQuart(float t); +float easeInQuint(float t); +float easeOutQuint(float t); +float easeInOutQuint(float t); \ No newline at end of file diff --git a/src/display/animation/timeline.c b/src/display/animation/timeline.c index 6f6d2a77..6cc1c90e 100644 --- a/src/display/animation/timeline.c +++ b/src/display/animation/timeline.c @@ -7,6 +7,32 @@ #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) { timeline->current = 0; timeline->diff = 0; @@ -68,10 +94,48 @@ bool timelineIsFinished(timeline_t *timeline) { timelineaction_t * timelineAddAction(timeline_t *timeline, float start, float duration ) { - if(timeline->actionCount == TIMELINE_ACTION_COUNT_MAX) return NULL; timelineaction_t *action = timeline->actions + (timeline->actionCount++); action->loop = false; action->start = start, action->duration = duration; action->onStart = action->onEnd = action->onDuration = NULL; 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; } \ No newline at end of file diff --git a/src/display/animation/timeline.h b/src/display/animation/timeline.h index f5c09de5..c4bcd8db 100644 --- a/src/display/animation/timeline.h +++ b/src/display/animation/timeline.h @@ -5,6 +5,8 @@ #pragma once #include "../../libs.h" +#include "../../util/math.h" +#include "easing.h" /** Maximum number of actions a timeline can support, smaller than 0xFF */ #define TIMELINE_ACTION_COUNT_MAX 128 @@ -72,6 +74,14 @@ typedef struct _timeline_t { /** Actions within the timeline */ 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; } timeline_t; @@ -110,4 +120,68 @@ bool timelineIsFinished(timeline_t *timeline); */ timelineaction_t * timelineAddAction(timeline_t *timeline, float start, float duration -); \ No newline at end of file +); + +/** + * 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); \ No newline at end of file diff --git a/src/display/camera.c b/src/display/camera.c index 16e5c2da..47ebfce9 100644 --- a/src/display/camera.c +++ b/src/display/camera.c @@ -15,6 +15,12 @@ void cameraLookAt(camera_t *camera, 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, float x, float y, float z, float pitch, float yaw, float roll diff --git a/src/display/camera.h b/src/display/camera.h index 5efa59b2..f9203de8 100644 --- a/src/display/camera.h +++ b/src/display/camera.h @@ -17,6 +17,10 @@ typedef struct { matrix_t projection; } 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 * within world space. @@ -34,6 +38,14 @@ void cameraLookAt(camera_t *camera, 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. * diff --git a/src/game/poker/actions/bet.c b/src/game/poker/actions/bet.c index db0af09c..637acb46 100644 --- a/src/game/poker/actions/bet.c +++ b/src/game/poker/actions/bet.c @@ -59,7 +59,7 @@ void _pokerGameActionBetOnUpdate( break; case POKER_TURN_TYPE_ALL_IN: - discussion.reason = POKER_DISCUSSION_REASON_PLAYER_CALLING; + discussion.reason = POKER_DISCUSSION_REASON_PLAYER_ALL_IN; break; case POKER_TURN_TYPE_FOLD: diff --git a/src/game/poker/pokerdiscussion.c b/src/game/poker/pokerdiscussion.c index 9847dc32..09a15437 100644 --- a/src/game/poker/pokerdiscussion.c +++ b/src/game/poker/pokerdiscussion.c @@ -77,6 +77,13 @@ void pokerDiscussionGet( discussion->emotions[0] = VN_CHARACTER_EMOTION_BOASTFUL; 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 case POKER_DISCUSSION_REASON_FLOP: discussion->count++; diff --git a/src/game/poker/pokerdiscussion.h b/src/game/poker/pokerdiscussion.h index 8e787159..6992ca08 100644 --- a/src/game/poker/pokerdiscussion.h +++ b/src/game/poker/pokerdiscussion.h @@ -23,9 +23,10 @@ #define POKER_DISCUSSION_REASON_PLAYER_CHECKING 0x05 #define POKER_DISCUSSION_REASON_PLAYER_CALLING 0x06 #define POKER_DISCUSSION_REASON_PLAYER_RAISING 0x07 -#define POKER_DISCUSSION_REASON_FLOP 0x08 -#define POKER_DISCUSSION_REASON_DEAL 0x09 -#define POKER_DISCUSSION_REASON_BETTING_DONE 0x0A +#define POKER_DISCUSSION_REASON_PLAYER_ALL_IN 0x08 +#define POKER_DISCUSSION_REASON_FLOP 0x09 +#define POKER_DISCUSSION_REASON_DEAL 0x0A +#define POKER_DISCUSSION_REASON_BETTING_DONE 0x0B typedef struct { pokergame_t *poker; diff --git a/src/game/poker/pokerworld.c b/src/game/poker/pokerworld.c index 3917858b..5060dc61 100644 --- a/src/game/poker/pokerworld.c +++ b/src/game/poker/pokerworld.c @@ -14,6 +14,9 @@ void pokerWorldInit( ) { vncharacter_t *character; uint8_t i; + + world->seat = POKER_GAME_SEAT_DEALER; + world->seatTime = 0; // Initialize the skywal skywallInit(&world->skywall); @@ -34,16 +37,21 @@ void pokerWorldInit( } } -void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex) { - uint8_t seat; - seat = pokerGameSeatFromIndex(playerIndex); - scene->cameraLookX = POKER_WORLD_SEAT_POSITION_X(seat); - scene->cameraLookZ = POKER_WORLD_SEAT_POSITION_Z(seat); +void pokerWorldLookAtPlayer( + vnscene_t *scene, uint8_t playerIndex +) { + uint8_t seat = pokerGameSeatFromIndex(playerIndex); + 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( - pokerworld_t *world, pokergameassets_t *assets -) { +void pokerWorldRender(pokerworld_t *world, pokergameassets_t *assets) { // Render the wall shaderUseTexture(&assets->shader, &assets->roomTexture); shaderUsePosition(&assets->shader, 0,2,0, 0,0,0); diff --git a/src/game/poker/pokerworld.h b/src/game/poker/pokerworld.h index 3dae9894..e369ebd9 100644 --- a/src/game/poker/pokerworld.h +++ b/src/game/poker/pokerworld.h @@ -9,11 +9,13 @@ #include "../../libs.h" #include "../../display/shader.h" #include "../../display/primitive.h" +#include "../../display/animation/easing.h" #include "../../display/primitives/skywall.h" #include "../../vn/vnscene.h" #include "../../vn/vncharacter.h" #include "../../poker/player.h" #include "../../poker/dealer.h" +#include "../../engine/engine.h" #include "pokergameassets.h" @@ -48,6 +50,10 @@ typedef struct { primitive_t skywall; + + /** Which seat the game should look at */ + uint8_t seat; + float seatTime; } pokerworld_t; @@ -66,12 +72,14 @@ void pokerWorldInit( /** * 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. */ -void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex); +void pokerWorldLookAtPlayer( + vnscene_t *scene, uint8_t playerIndex +); /** * Render the poker world. @@ -79,9 +87,7 @@ void pokerWorldLookAtPlayer(vnscene_t *scene, uint8_t playerIndex); * @param world Poker Game World. * @param assets Assets to use. */ -void pokerWorldRender( - pokerworld_t *world, pokergameassets_t *assets -); +void pokerWorldRender(pokerworld_t *world, pokergameassets_t *assets); /** * Cleanup the poker world. diff --git a/src/poker/player.c b/src/poker/player.c index 6d9e36a4..44593cbf 100644 --- a/src/poker/player.c +++ b/src/poker/player.c @@ -14,6 +14,7 @@ bool pokerPlayerIsAlive(pokerplayer_t *player) { void pokerPlayerReset(pokerplayer_t *player) { player->cardCount = 0; player->currentBet = 0; + player->timesRaised = 0; // Invert then bitwise AND to turn off. player->state &= ~( diff --git a/src/poker/player.h b/src/poker/player.h index d7724d50..695ca595 100644 --- a/src/poker/player.h +++ b/src/poker/player.h @@ -53,6 +53,9 @@ typedef struct { /** Current bet in current round player has placed */ int32_t currentBet; + + /** How many times for the current flop that the player has raised */ + int32_t timesRaised; } pokerplayer_t; /** diff --git a/src/poker/turn.c b/src/poker/turn.c index ffc1a8c7..ae57f28c 100644 --- a/src/poker/turn.c +++ b/src/poker/turn.c @@ -9,12 +9,13 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { int32_t random, maxBet, bluffBet, callBet; - float winProbability, expectedGain, confidence, potOdds; + float confidence, expectedGain, potOdds; bool isBluff; int32_t amount; pokerplayer_t *player; pokerplayerwinning_t winning; uint8_t i, cardNumber0, cardNumber1, suitNumber0, suitNumber1; + pokerturn_t turn; player = poker->players + playerIndex; @@ -23,42 +24,53 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { return pokerTurnOut(poker, playerIndex); } - // Now we basically need to determine the AI's action here. The AI really only - // needs to do one thing, decide whether or not they want to Bet or Not. - // In future I may make checking optional, but for now there's really no - // reason not to. - pokerWinnerPlayerGet(&poker->dealer, player, &winning); + // The following logic is heavily inspired by; + // https://github.com/gorel/C-Poker-AI/blob/master/src/common/pokerai.c + // But with some changes and smarts added by me. The original source code will + // essentially just run a crap tun of simulated games and get the times that + // 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) { + // Get the hand weight cardNumber0 = cardGetNumber(player->cards[0]); cardNumber1 = cardGetNumber(player->cards[1]); suitNumber0 = cardGetSuit(player->cards[0]); suitNumber1 = cardGetSuit(player->cards[1]); + // Get delta between cards i = mathAbs(cardNumber0 - cardNumber1); + // Get card weight confidence = (float)cardNumber0 + (float)cardNumber1; - if(cardNumber0 == cardNumber1) { + if(cardNumber0 == cardNumber1) {// Pairs confidence += 6; - } else if(suitNumber0 == suitNumber1) { + } else if(suitNumber0 == suitNumber1) {// Same suit confidence += 4; } + // Get difference from cards for guessing flush if(i > 4) { confidence -= 4; } else if(i > 2) { confidence -= i; } + // Get the confidence delta 0-1 confidence = confidence / 30.0f; } else { + // Simulate my hand being the winning hand, use that as the confidence + pokerWinnerPlayerGet(&poker->dealer, player, &winning); 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; - winProbability = confidence; + // Do they need chips to call, or is it possible to check? if(callBet > 0) { potOdds = (float)callBet / ((float)callBet + (float)poker->bet.pot); } else { @@ -66,26 +78,36 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { 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; - 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; + // Now prep the output isBluff = false; 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) { - amount = 0;//FOLD + amount = 0; } else { amount = bluffBet; 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) { - amount = 0;//FOLD + amount = 0; } else if(random < 5) { amount = callBet; isBluff = true; @@ -93,13 +115,13 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { amount = bluffBet; isBluff = true; } - } else if ((expectedGain < 1.3 && winProbability < 0.9) || winProbability < 0.5) { - if (random < 60 || winProbability < 0.5) { + } else if ((expectedGain < 1.3 && confidence < 0.9) || confidence < 0.5) { + if (random < 60 || confidence < 0.5) { amount = callBet; } else { amount = maxBet; } - } else if (winProbability < 0.95 || poker->dealer.cardsFacing < 0x04) { + } else if (confidence < 0.95 || poker->dealer.cardsFacing < 0x04) { if(random < 30) { amount = callBet; } else { @@ -109,21 +131,24 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { 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); - - // TODO: Make sure we don't get stuck in a raise loop. + // Did we actually bet? if(amount > 0) { amount = mathMin(amount, callBet); - return pokerTurnRaise(poker, playerIndex, amount); - } - - if(pokerTurnCanPlayerCheck(poker, playerIndex)) { - return pokerTurnCheck(poker, playerIndex); + turn = pokerTurnRaise(poker, playerIndex, amount); + turn.confidence = confidence; + } else if(pokerTurnCanPlayerCheck(poker, playerIndex)) { + turn = 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) { @@ -132,14 +157,17 @@ void pokerTurnAction(poker_t *poker, pokerplayer_t *player, pokerturn_t *turn) { case POKER_TURN_TYPE_CALL: case POKER_TURN_TYPE_ALL_IN: pokerBetPlayer(&poker->bet, player, turn->chips); + player->timesRaised++; break; case POKER_TURN_TYPE_CHECK: pokerBetPlayer(&poker->bet, player, 0); + player->timesRaised = 0; break; case POKER_TURN_TYPE_FOLD: player->state |= POKER_PLAYER_STATE_FOLDED; + player->timesRaised = 0; break; } diff --git a/src/poker/turn.h b/src/poker/turn.h index 2e0bf61f..d083c0e1 100644 --- a/src/poker/turn.h +++ b/src/poker/turn.h @@ -19,6 +19,8 @@ #define POKER_TURN_TYPE_CALL_ALL_IN 0x04 #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 */ typedef struct { /** What type of action the turn is */ diff --git a/src/vn/vnscene.c b/src/vn/vnscene.c index 04da03d1..7ceea3c1 100644 --- a/src/vn/vnscene.c +++ b/src/vn/vnscene.c @@ -12,12 +12,16 @@ void vnSceneInit(vnscene_t *scene, font_t *font, texture_t *text) { vnConversationInit(&scene->conversation, font, text); scene->conversation.textbox.linesMax = 3; - scene->cameraX = 0; - scene->cameraY = 0; - scene->cameraZ = 0; - scene->cameraLookX = 0; - scene->cameraLookY = 0; - scene->cameraLookZ = -5; + // Init the animation + timelineInit(&scene->timeline); + + // Reset Camera + scene->cameraLook.x = 0; + scene->cameraLook.y = 0; + scene->cameraLook.z = 0; + scene->cameraLook.lookX = 0; + scene->cameraLook.lookY = 0; + scene->cameraLook.lookZ = 0; // Reset character count 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) { uint8_t i; + // Tick the animations. + timelineUpdate(&scene->timeline, engine->time.delta); + // Update the conversation vnConversationUpdate(&scene->conversation, engine); @@ -40,11 +47,8 @@ void vnSceneDispose(vnscene_t *scene) { } void vnSceneRenderWorld(vnscene_t *scene, engine_t *engine, shader_t *shader) { - // Adjust 3D Space position - cameraLookAt(&scene->camera, - scene->cameraX, scene->cameraY, scene->cameraZ, - scene->cameraLookX, scene->cameraLookY, scene->cameraLookZ - ); + // Adjust Camera Position. + cameraLookAtStruct(&scene->camera, scene->cameraLook); // Set Camera Perspective cameraPerspective(&scene->camera, 35, @@ -90,4 +94,45 @@ void vnSceneRenderGui(vnscene_t *scene, engine_t *engine, shader_t *shader) { // Render Conversation Element 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; } \ No newline at end of file diff --git a/src/vn/vnscene.h b/src/vn/vnscene.h index 384f7f31..0504e74e 100644 --- a/src/vn/vnscene.h +++ b/src/vn/vnscene.h @@ -12,17 +12,19 @@ #include "ui/vntextbox.h" #include "../display/camera.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 */ #define VN_SCENE_CHARACTERS_MAX 6 +#define VN_SCENE_DISTANCE_DEFAULT -5.0f typedef struct { - float cameraX; - float cameraY; - float cameraZ; - float cameraLookX; - float cameraLookY; - float cameraLookZ; + timeline_t timeline; + + // Camera Targets + cameralookat_t cameraLook; /** Camera used for rendering, updated frequently */ 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 vnSceneRenderGui(vnscene_t *scene, engine_t *engine, shader_t *shader); \ No newline at end of file +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 +); \ No newline at end of file