Skip to content

Commit

Permalink
Add guidance on game.cc
Browse files Browse the repository at this point in the history
  • Loading branch information
john0312 committed Jul 25, 2024
1 parent bd2b6b0 commit 9d1ef3e
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 118 deletions.
16 changes: 10 additions & 6 deletions fw/Core/Hitcon/Logic/IrController.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
#include <time.h>

using namespace hitcon::service::sched;
using hitcon::game::game_accept_data;
using hitcon::game::IrAllowBroadcastCnt;
using hitcon::game::IrAllowedBroadcastCol;
using hitcon::game::kDataSize;

namespace hitcon {
namespace ir {

constexpr int IrAllowedBroadcastCol[] = {0, 2, 3, 4, 7};
constexpr int IrAllowBroadcastCnt = 5;

IrController::IrController()
: routine_task(950, (callback_t)&IrController::RoutineTask, this, 1000),
broadcast_task(800, (callback_t)&IrController::BroadcastIr, this),
Expand Down Expand Up @@ -59,9 +60,12 @@ void IrController::RoutineTask(void* unused) {
}

void IrController::BroadcastIr(void* unused) {
int type = rand() % IrAllowBroadcastCnt;
for (int i = 0; i < GAME_DATA_SIZE; ++i) {
// Get data and send to packet
uint8_t cell_data[kDataSize];
int col;
bool ok =
hitcon::game::get_random_cell_data_for_ir_transmission(cell_data, &col);
if (ok) {
// Package the data and send to IrLogic.
}
send_lock = true;
}
Expand Down
2 changes: 1 addition & 1 deletion fw/Core/Hitcon/Logic/IrController.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ir {
/*Definition of IR content.*/
struct GamePacket {
uint8_t col;
uint8_t data[GAME_DATA_SIZE];
uint8_t data[hitcon::game::kDataSize];
};

struct ShowPacket {
Expand Down
5 changes: 3 additions & 2 deletions fw/Core/Hitcon/Logic/NvStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <stddef.h>
#include <stdint.h>

#include <Logic/game_param.h>
#include <Service/Sched/Scheduler.h>
#include <Util/callback.h>

Expand All @@ -16,8 +17,8 @@ typedef struct nv_storage_content_t {
int32_t version;

// Add any needed data that needs to be persisted here.
uint8_t game_data[16*16];
uint8_t test;
hitcon::game::game_storage_t game_storage;

} nv_storage_content;

static_assert(sizeof(nv_storage_content) <= 4096, "nv_storage_content is too large");
Expand Down
99 changes: 36 additions & 63 deletions fw/Core/Hitcon/Logic/game.cc
Original file line number Diff line number Diff line change
@@ -1,45 +1,59 @@
#include "game.h"

static storage_t __storage;
#include <Logic/NvStorage.h>

grid_t random_grid() {
namespace hitcon {
namespace game {

// Implements the ln() with approximate polynomial.
// The output is in Q9.22 fixed point number, while the input is in
// uint32_t integer format.
int32_t q22_ln(uint32_t) {
// TODO
return (grid_t){0};
}

score_t grid_score(const grid_t *grid) {
game_cache_t game_cache;

grid_cell_t random_grid() {
// TODO
return (grid_cell_t){0};
}

score_t grid_score(const grid_cell_t *grid) {
// TODO
// Note: This probably has to be reimplemented because it spans multiple
// tasks.
return 0;
}

storage_t new_storage() {
storage_t storage;
for (int i = 0; i < GAME_NUM_COLUMNS; i++) {
for (int j = 0; j < GAME_NUM_ROWS; j++) {
for (int k = 0; k < GAME_DATA_SIZE; k++) {
storage.data[i][j] = random_grid();
game_storage_t new_storage() {
game_storage_t storage;
for (int i = 0; i < kNumCols; i++) {
for (int j = 0; j < kNumRows; j++) {
for (int k = 0; k < kDataSize; k++) {
storage.cells[i][j] = random_grid();
}
}
}
return storage;
}

void game_init(const storage_t *storage) {
if (storage == NULL) {
__storage = new_storage();
return;
}
__storage = *storage;
void game_init() {
// Note: If all data cell in game_get_storage() is 0, then it's new and should
// be inited. Init any tasks here.
}

storage_t game_get_storage() { return __storage; }
game_storage_t &game_get_storage() {
return g_nv_storage.GetCurrentStorage().game_storage;
}

// Generate a new grid and replace existing grid if score is higher.
// Should be called periodically.
void __game_generate_random_and_update_column(int column) {
grid_t new_grid = random_grid();
for (int i = 0; i < GAME_NUM_ROWS; i++) {
if (grid_score(&new_grid) > grid_score(&__storage.data[column][i])) {
grid_cell_t new_grid = random_grid();
for (int i = 0; i < kNumRows; i++) {
if (grid_score(&new_grid) >
grid_score(&game_get_storage().cells[column][i])) {
// TODO: sort column and replace the lowest score with the new grid
return;
}
Expand All @@ -53,46 +67,5 @@ void __game_receive_and_update_column(int column, void *event_data) {
// TODO
}

#define FUNC_GENERATE_RANDOM_AND_UPDATE_COLUMN(name, column) \
void name() { __game_generate_random_and_update_column(column); }
#define FUNC_RECEIVE_AND_UPDATE_COLUMN(name, column) \
void name(void *event_data) { \
__game_receive_and_update_column(column, event_data); \
}

FUNC_GENERATE_RANDOM_AND_UPDATE_COLUMN(game_update_unshared,
GAME_COLUMN_UNSHARED)
FUNC_GENERATE_RANDOM_AND_UPDATE_COLUMN(game_update_shared_periodic,
GAME_COLUMN_SHARED_PLAYER)

FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_shared_event,
GAME_COLUMN_SHARED_PLAYER)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast1_event,
GAME_COLUMN_BROADCASTER1)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast2_event,
GAME_COLUMN_BROADCASTER2)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast3_event,
GAME_COLUMN_BROADCASTER3)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast4_event,
GAME_COLUMN_BROADCASTER4)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast5_event,
GAME_COLUMN_BROADCASTER5)
FUNC_RECEIVE_AND_UPDATE_COLUMN(game_update_broadcast6_event,
GAME_COLUMN_BROADCASTER6)

void register_callbacks(void (*register_callback_no_arg)(
int period, callback_no_arg_t callback_no_arg),
void (*register_callback_event_data)(
callback_event_data_t callback_event_data)) {
register_callback_no_arg(GAME_UPDATE_UNSHARED_PERIOD, game_update_unshared);
register_callback_no_arg(GAME_UPDATE_SHARED_PERIOD,
game_update_shared_periodic);

register_callback_event_data(game_update_shared_event);
register_callback_event_data(game_update_broadcast1_event);
register_callback_event_data(game_update_broadcast2_event);
register_callback_event_data(game_update_broadcast3_event);
register_callback_event_data(game_update_broadcast4_event);
register_callback_event_data(game_update_broadcast5_event);
register_callback_event_data(game_update_broadcast6_event);
}
} // namespace game
} // namespace hitcon
60 changes: 14 additions & 46 deletions fw/Core/Hitcon/Logic/game.h
Original file line number Diff line number Diff line change
@@ -1,64 +1,32 @@
#ifndef GAME_H
#define GAME_H
#ifndef LOGIC_GAME_DOT_H_
#define LOGIC_GAME_DOT_H_

#include <stddef.h>
#include <stdint.h>

/**
* Definition of columns:
* 0: self generated (unshared)
* 1: self generated, shared with other players (send/receive)
* 2: received from broadcasters scattered around the world
* 3: (same as 2)
* ...
* 7: (same as 2)
*/
#include <Logic/game_param.h>

#define GAME_COLUMN_UNSHARED 0 // column index
#define GAME_COLUMN_SHARED_PLAYER 1 // column index
#define GAME_COLUMN_BROADCASTER1 2 // column index
#define GAME_COLUMN_BROADCASTER2 3 // column index
#define GAME_COLUMN_BROADCASTER3 4 // column index
#define GAME_COLUMN_BROADCASTER4 5 // column index
#define GAME_COLUMN_BROADCASTER5 6 // column index
#define GAME_COLUMN_BROADCASTER6 7 // column index

#define GAME_UPDATE_UNSHARED_PERIOD (10 * 60) // 10 minutes
#define GAME_UPDATE_SHARED_PERIOD (10 * 60) // 10 minutes

#define GAME_NUM_COLUMNS 8
#define GAME_NUM_ROWS 16
#define GAME_DATA_SIZE 8

typedef int score_t;

typedef struct {
uint8_t data[GAME_DATA_SIZE];
} grid_t;

typedef struct {
grid_t data[GAME_NUM_COLUMNS][GAME_NUM_ROWS];
} storage_t;
namespace hitcon {
namespace game {

// Initialize the game.
// If storage is NULL, this function will generate one.
void game_init(const storage_t *storage);
void game_init(const game_storage_t *storage);

// Get the storage of the game. Can be used to save the game (persistent
// storage).
storage_t game_get_storage();

typedef void (*callback_no_arg_t)(void);
typedef void (*callback_event_data_t)(void *event_data);
void register_callbacks(void (*register_callback_no_arg)(
int period, callback_no_arg_t callback_no_arg),
void (*register_callback_event_data)(
callback_event_data_t callback_event_data));
game_storage_t& game_get_storage();

// This is the data we received from peer.
void game_accept_data(int col, uint8_t* data);

// Retrieve the data at particular cell.
uint8_t* get_data_cell(int col, int row);

#endif // GAME_H
// Get a random data cell for sending over IR. The data is written to out_data, while the column is written to out_col.
bool get_random_cell_data_for_ir_transmission(uint8_t* out_data, int* out_col);

} // namespace game
} // namespace hitcon

#endif // LOGIC_GAME_DOT_H_
58 changes: 58 additions & 0 deletions fw/Core/Hitcon/Logic/game_param.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef LOGIC_GAME_PARAM_DOT_H_
#define LOGIC_GAME_PARAM_DOT_H_

#include <stddef.h>
#include <stdint.h>

namespace hitcon {
namespace game {

// We've a grid of cells, each cell has some data.

constexpr size_t kNumCols = 8;
constexpr size_t kNumRows = 16;
constexpr size_t kDataSize = 8;

// We do a random generation once every kRandomGenPeriodMs ms.
constexpr size_t kRandomGenPeriodMs = 100;

typedef int score_t;

// Represents one cell in the grid.
typedef struct {
uint8_t data[kDataSize];
} grid_cell_t;

// game_storage_t is persisted to the persistent storage.
typedef struct {
grid_cell_t cells[kNumCols][kNumRows];
} game_storage_t;

// game_cache_t is a temporary structure that contains frequently used data,
// but is not persisted to the storage.
typedef struct {
// The score for each cell is the number of prefix 0 bit in
// sha3_256(col_prefix | cell_data).
// Technically a uint8_t might overflow, but by then we're all screwed so whatever.
uint8_t cell_score_cache[kNumCols][kNumRows];

// The score for each column is the sum of all score in the column.
uint32_t col_score_cache[kNumCols];

// The total score is the sum of log(col_score), where by log is the natural log.
// This number is stored in Q format fixed number. Q9.22 is used.
uint32_t total_score;
} game_cache_t;

// These columns may be broadcasted by the IrController.
constexpr int IrAllowedBroadcastCol[] = {0, 2, 3, 4, 7};
constexpr size_t IrAllowBroadcastCnt = sizeof(IrAllowedBroadcastCol)/sizeof(IrAllowedBroadcastCol[0]);

// These columns may accept data through internal random generation.
constexpr int InternalGenCol[] = {0, 1, 2};
constexpr size_t InternalGenColCnt = sizeof(InternalGenCol)/sizeof(InternalGenCol[0]);

} // namespace game
} // namespace hitcon

#endif // LOGIC_GAME_PARAM_DOT_H_

0 comments on commit 9d1ef3e

Please sign in to comment.