winning/losing page
This commit is contained in:
+16
-56
@@ -7,7 +7,7 @@
|
|||||||
* MY_CONSTANT
|
* MY_CONSTANT
|
||||||
* */
|
* */
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
//#include <math.h>
|
||||||
#include "base/impl.c"
|
#include "base/impl.c"
|
||||||
#include "lib/network.c"
|
#include "lib/network.c"
|
||||||
#include "render.c"
|
#include "render.c"
|
||||||
@@ -101,6 +101,7 @@ typedef struct TransactionResult {
|
|||||||
|
|
||||||
typedef struct ParsedServerMessage {
|
typedef struct ParsedServerMessage {
|
||||||
Message type;
|
Message type;
|
||||||
|
u8 byte;
|
||||||
u16 port;
|
u16 port;
|
||||||
u16 port2;
|
u16 port2;
|
||||||
u32 ip;
|
u32 ip;
|
||||||
@@ -323,51 +324,6 @@ fn void renderPercentBar(TuiState* tui, u16 x, u16 y, u16 width, u8 ansi_color,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn void renderSpeechBubble(TuiState* tui, u16 x, u16 y, u16 max_width, String message, SpeechTailDirection dir) {
|
|
||||||
Pixel* buf = tui->frame_buffer;
|
|
||||||
Dim2 screen_dimensions = tui->screen_dimensions;
|
|
||||||
// calculate dimenions
|
|
||||||
u32 height = (message.length / max_width) + 1;
|
|
||||||
u32 width = message.length;
|
|
||||||
if (message.length > max_width) {
|
|
||||||
width = max_width;
|
|
||||||
}
|
|
||||||
if (width < 12) {
|
|
||||||
width = 12; // minimum width
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the upper border
|
|
||||||
renderUtf8CharToBuffer(buf, x, y, "╭", screen_dimensions);
|
|
||||||
for (i32 i = 0; i < width+1; i++) {
|
|
||||||
renderUtf8CharToBuffer(buf, x+1+i, y, "─", screen_dimensions);
|
|
||||||
}
|
|
||||||
renderUtf8CharToBuffer(buf, x+width+1, y, "╮", screen_dimensions);
|
|
||||||
|
|
||||||
// start printing the rows
|
|
||||||
for (u32 i = 0; i < height; i++) {
|
|
||||||
renderUtf8CharToBuffer(buf, x, y+1+i, "│", screen_dimensions);
|
|
||||||
// print the line of text
|
|
||||||
for (u32 j = 0; j < width; j++) {
|
|
||||||
u32 character_index = (i*(width-1))+j;
|
|
||||||
u16 pos = (x+1+j) + (screen_dimensions.width * (y+1+i));
|
|
||||||
if (message.length > character_index) {
|
|
||||||
buf[pos].bytes[0] = message.bytes[character_index];
|
|
||||||
} else {
|
|
||||||
buf[pos].bytes[0] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
renderUtf8CharToBuffer(buf, x+1+width, y+1+i, "│", screen_dimensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the bottom box border
|
|
||||||
renderUtf8CharToBuffer(buf, x, y+1+height, "╰", screen_dimensions);
|
|
||||||
for (i32 i = 0; i < width+1; i++) {
|
|
||||||
renderUtf8CharToBuffer(buf, x+1+i, y+1+height, "─", screen_dimensions);
|
|
||||||
}
|
|
||||||
renderUtf8CharToBuffer(buf, x+width+1, y+1+height, "╯", screen_dimensions);
|
|
||||||
// TODO actually print the speech tail
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void renderStaticAssetToPixelBuffer(TuiState* tui, u8* asset, u32 len, u16 x, u16 y) {
|
fn void renderStaticAssetToPixelBuffer(TuiState* tui, u8* asset, u32 len, u16 x, u16 y) {
|
||||||
u16 line = 0;
|
u16 line = 0;
|
||||||
u16 x_in_line = 0;
|
u16 x_in_line = 0;
|
||||||
@@ -431,6 +387,9 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
case MessageTurnTick:
|
case MessageTurnTick:
|
||||||
case MessageNewAccountCreated:
|
case MessageNewAccountCreated:
|
||||||
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
case MessageBadPw: {/*nothing to parse but the type*/} break;
|
||||||
|
case MessageGameOver: {
|
||||||
|
parsed.byte = message[msg_pos++];
|
||||||
|
} break;
|
||||||
case MessageTransactionResult: {
|
case MessageTransactionResult: {
|
||||||
parsed.tx_result.buying = message[msg_pos++];
|
parsed.tx_result.buying = message[msg_pos++];
|
||||||
parsed.tx_result.qty = readU32FromBufferLE(message + msg_pos);
|
parsed.tx_result.qty = readU32FromBufferLE(message + msg_pos);
|
||||||
@@ -551,6 +510,11 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
while (next_net_msg != NULL) {
|
while (next_net_msg != NULL) {
|
||||||
msg_iters += 0;
|
msg_iters += 0;
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
|
case MessageGameOver: {
|
||||||
|
state->screen = state->me.id == msg.byte ? ScreenVictory : ScreenDefeat;
|
||||||
|
sprintf(sbuf,"got winner id: %d", msg.byte);
|
||||||
|
addSystemMessage((u8*)sbuf);
|
||||||
|
} break;
|
||||||
case MessagePayoffResult: {
|
case MessagePayoffResult: {
|
||||||
state->ship_tab_states = ShipTabStateMain;
|
state->ship_tab_states = ShipTabStateMain;
|
||||||
} break;
|
} break;
|
||||||
@@ -732,10 +696,8 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
u32 principal_borrowed = selected_ship_cost - STARTING_DOWN_PAYMENT;
|
u32 principal_borrowed = selected_ship_cost - STARTING_DOWN_PAYMENT;
|
||||||
f32 mortgage_rate = calcInterestRate(selected_ship_cost, STARTING_DOWN_PAYMENT);
|
f32 mortgage_rate = calcInterestRate(selected_ship_cost, STARTING_DOWN_PAYMENT);
|
||||||
f32 r = mortgage_rate / 100.0;
|
f32 r = mortgage_rate / 100.0;
|
||||||
f32 rm = r / 12.0;
|
u32 payment = principal_borrowed * r;
|
||||||
u32 n = 12 * 4;
|
sprintf(sbuf, "Mortgage: $%d @ %f%% = $%d interest after first turn", selected_ship_cost - STARTING_DOWN_PAYMENT, mortgage_rate, payment);
|
||||||
u32 payment = principal_borrowed * (rm*pow((1.0+rm),n))/(pow((1+rm),n) - 1);
|
|
||||||
sprintf(sbuf, "Mortgage: $%d @ %f%% = $%d minimum payment per turn", selected_ship_cost - STARTING_DOWN_PAYMENT, mortgage_rate, payment);
|
|
||||||
renderStrToBuffer(tui->frame_buffer, 5, ++line, sbuf, screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, 5, ++line, sbuf, screen_dimensions);
|
||||||
line++;
|
line++;
|
||||||
// the table
|
// the table
|
||||||
@@ -1359,23 +1321,21 @@ fn bool updateAndRender(TuiState* tui, void* s, u8* input_buffer, u64 loop_count
|
|||||||
case ScreenVictory: {
|
case ScreenVictory: {
|
||||||
// SIMULATION
|
// SIMULATION
|
||||||
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
||||||
state->screen = ScreenMainGame;
|
should_quit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// RENDERING
|
// RENDERING
|
||||||
renderStrToBuffer(tui->frame_buffer, 10, 10, "You WIN!!!", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, 10, 10, "You WIN!!!", screen_dimensions);
|
||||||
|
renderStrToBuffer(tui->frame_buffer, 5, 11, "You paid off your ships mortgage and are a free trader!", screen_dimensions);
|
||||||
} break;
|
} break;
|
||||||
case ScreenDefeat: {
|
case ScreenDefeat: {
|
||||||
// SIMULATION
|
// SIMULATION
|
||||||
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
if (user_pressed_esc || input_buffer[0] == ASCII_RETURN || input_buffer[0] == ASCII_LINE_FEED) {
|
||||||
state->me.id = 0;
|
should_quit = true;
|
||||||
state->menu.selected_index = 0;
|
|
||||||
clearServerSentState();
|
|
||||||
state->screen = ScreenCreateCharacter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RENDERING
|
// RENDERING
|
||||||
renderStrToBuffer(tui->frame_buffer, 10, 10, "You died...", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, 10, 10, "You lose, forever doomed to work for the bank...", screen_dimensions);
|
||||||
renderStrToBuffer(tui->frame_buffer, 10, 11, "[press ESC to continue]", screen_dimensions);
|
renderStrToBuffer(tui->frame_buffer, 10, 11, "[press ESC to continue]", screen_dimensions);
|
||||||
} break;
|
} break;
|
||||||
case Screen_Count:
|
case Screen_Count:
|
||||||
|
|||||||
+32
-175
@@ -59,17 +59,6 @@ typedef struct ParsedClientCommandThreadQueue {
|
|||||||
Cond not_full;
|
Cond not_full;
|
||||||
} ParsedClientCommandThreadQueue;
|
} ParsedClientCommandThreadQueue;
|
||||||
|
|
||||||
typedef struct Entity {
|
|
||||||
bool changed;
|
|
||||||
u8 x;
|
|
||||||
u8 y;
|
|
||||||
u8 color;
|
|
||||||
EntityType type;
|
|
||||||
u32 misc;
|
|
||||||
u64 id;
|
|
||||||
u64 features;
|
|
||||||
} Entity;
|
|
||||||
|
|
||||||
typedef struct Account {
|
typedef struct Account {
|
||||||
u8 destination_sys_idx;
|
u8 destination_sys_idx;
|
||||||
bool changed;
|
bool changed;
|
||||||
@@ -79,26 +68,6 @@ typedef struct Account {
|
|||||||
PlayerShip ship;
|
PlayerShip ship;
|
||||||
} Account;
|
} Account;
|
||||||
|
|
||||||
typedef struct EntityList {
|
|
||||||
u64 length; // the currently used length
|
|
||||||
u64 capacity;
|
|
||||||
Entity* items;
|
|
||||||
} EntityList;
|
|
||||||
|
|
||||||
typedef struct EntityChunk {
|
|
||||||
u64 length; // the currently used # of entities in this chunk
|
|
||||||
u64 capacity; // the "chunk size" / space in this chunk
|
|
||||||
struct EntityChunk* next; // the next chunk
|
|
||||||
Entity* items; // the actual entities
|
|
||||||
} EntityChunk;
|
|
||||||
|
|
||||||
typedef struct ChunkedEntityList {
|
|
||||||
u64 length; // the current number of entities
|
|
||||||
u64 chunk_size; // the # of entities per chunk
|
|
||||||
u64 chunks; // the # of chunks in this list so far
|
|
||||||
EntityChunk* first; // the first chunk of entities
|
|
||||||
} ChunkedEntityList;
|
|
||||||
|
|
||||||
typedef struct Client {
|
typedef struct Client {
|
||||||
u16 lan_port;
|
u16 lan_port;
|
||||||
i32 lan_ip;
|
i32 lan_ip;
|
||||||
@@ -134,9 +103,7 @@ typedef struct State {
|
|||||||
///// Global Variables
|
///// Global Variables
|
||||||
global State state = { 0 };
|
global State state = { 0 };
|
||||||
global Arena permanent_arena = { 0 };
|
global Arena permanent_arena = { 0 };
|
||||||
global const Entity NULL_ENTITY = { 0 };
|
|
||||||
global bool debug_mode = false;
|
global bool debug_mode = false;
|
||||||
global ChunkedEntityList free_chunks = { 0, CHUNK_SIZE, 0, NULL };
|
|
||||||
|
|
||||||
///// functionImplementations()
|
///// functionImplementations()
|
||||||
fn ParsedClientCommandThreadQueue* newPCCThreadQueue(Arena* a) {
|
fn ParsedClientCommandThreadQueue* newPCCThreadQueue(Arena* a) {
|
||||||
@@ -182,44 +149,6 @@ fn ParsedClientCommand* pccThreadSafeNonblockingQueuePop(ParsedClientCommandThre
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 entitySerialize(Entity current, Account* acct, u64 index, u8 bytes[]) {
|
|
||||||
// send entity header (common to all entity types)
|
|
||||||
index += writeU64ToBufferLE(bytes + index, current.id);
|
|
||||||
index += writeU64ToBufferLE(bytes + index, current.features);
|
|
||||||
bytes[index++] = current.x;
|
|
||||||
bytes[index++] = current.y;
|
|
||||||
bytes[index++] = (u8)current.type; // EntityType
|
|
||||||
|
|
||||||
//if (CheckFlag(current.features, FeatureRegensHp)) {
|
|
||||||
// index += writeU16ToBufferLE(bytes + index, current.hp);
|
|
||||||
// index += writeU16ToBufferLE(bytes + index, current.max_hp);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// send character-specific details (color and name)
|
|
||||||
if (current.type == EntityCharacter) {
|
|
||||||
bytes[index++] = current.color;
|
|
||||||
// send name string
|
|
||||||
index += writeU64ToBufferLE(bytes + index, acct->name.length);
|
|
||||||
for (u32 j = 0; j < acct->name.length; j++) {
|
|
||||||
bytes[index++] = acct->name.bytes[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn u64 entityFeaturesFromType(EntityType type) {
|
|
||||||
u64 result = 0;
|
|
||||||
switch (type) {
|
|
||||||
case EntityCharacter: {
|
|
||||||
SetFlag(result, FeatureWalksAround);
|
|
||||||
SetFlag(result, FeatureCanFight);
|
|
||||||
} break;
|
|
||||||
default: {
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Account* findAccountByName(String name) {
|
fn Account* findAccountByName(String name) {
|
||||||
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
for (u32 i = 0; i < ACCOUNT_LEN; i++) {
|
||||||
if (stringsEq(&state.accounts[i].name, &name)) {
|
if (stringsEq(&state.accounts[i].name, &name)) {
|
||||||
@@ -229,93 +158,6 @@ fn Account* findAccountByName(String name) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u64 pushEntity(EntityChunk* chunk, Entity e) {
|
|
||||||
assert(chunk->length < chunk->capacity);
|
|
||||||
chunk->items[chunk->length] = e;
|
|
||||||
u64 result = chunk->length;
|
|
||||||
chunk->length += 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bool isSpaceInChunk(EntityChunk* chunk) {
|
|
||||||
return chunk->length < chunk->capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bool allChunksFull(ChunkedEntityList list) {
|
|
||||||
return list.length >= (list.chunk_size * list.chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn EntityChunk* pushNewChunk(Arena* a, ChunkedEntityList* list) {
|
|
||||||
EntityChunk* new_chunk;
|
|
||||||
if (free_chunks.length > 0) {
|
|
||||||
new_chunk = free_chunks.first;
|
|
||||||
free_chunks.length -= 1;
|
|
||||||
free_chunks.first = new_chunk->next;
|
|
||||||
} else {
|
|
||||||
new_chunk = arenaAlloc(a, sizeof(EntityChunk));
|
|
||||||
// alloc the new chunk of entities
|
|
||||||
new_chunk->length = 0;
|
|
||||||
new_chunk->capacity = list->chunk_size;
|
|
||||||
new_chunk->next = NULL;
|
|
||||||
new_chunk->items = arenaAllocArray(a, Entity, list->chunk_size);
|
|
||||||
}
|
|
||||||
// bookeeping in the list
|
|
||||||
list->chunks += 1;
|
|
||||||
if (list->first == NULL) {
|
|
||||||
list->first = new_chunk;
|
|
||||||
} else {
|
|
||||||
EntityChunk* last = list->first;
|
|
||||||
while (last->next != NULL) {
|
|
||||||
last = last->next;
|
|
||||||
}
|
|
||||||
last->next = new_chunk;
|
|
||||||
}
|
|
||||||
return new_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Entity* entityPtrFromChunkList(ChunkedEntityList* list, i32 index) {
|
|
||||||
Entity* result = (Entity*)&NULL_ENTITY;
|
|
||||||
i32 chunk_index = index / list->chunk_size;
|
|
||||||
EntityChunk* chunk = list->first;
|
|
||||||
for (i32 i = 0; i < chunk_index; i++) {
|
|
||||||
chunk = chunk->next;
|
|
||||||
}
|
|
||||||
result = &chunk->items[index % list->chunk_size];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Entity entityFromChunkList(ChunkedEntityList* list, i32 index) {
|
|
||||||
Entity result = {0};
|
|
||||||
i32 chunk_index = index / list->chunk_size;
|
|
||||||
EntityChunk* chunk = list->first;
|
|
||||||
for (i32 i = 0; i < chunk_index; i++) {
|
|
||||||
chunk = chunk->next;
|
|
||||||
}
|
|
||||||
result = chunk->items[index % list->chunk_size];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bool deleteLastEntity(ChunkedEntityList* list, EntityChunk* last_chunk, EntityChunk* second_to_last_chunk) {
|
|
||||||
last_chunk->length -= 1;
|
|
||||||
list->length -= 1;
|
|
||||||
// don't delete the room's only chunk, but otherwise move the chunk to the free-list
|
|
||||||
if (last_chunk->length == 0 && last_chunk != list->first) {
|
|
||||||
list->chunks -= 1;
|
|
||||||
second_to_last_chunk->next = NULL;
|
|
||||||
free_chunks.length += 1;
|
|
||||||
EntityChunk* last_free_chunk = free_chunks.first;
|
|
||||||
if (last_free_chunk) {
|
|
||||||
while (last_free_chunk->next != NULL) {
|
|
||||||
last_free_chunk = last_free_chunk->next;
|
|
||||||
}
|
|
||||||
last_free_chunk->next = last_chunk;
|
|
||||||
} else {
|
|
||||||
free_chunks.first = last_chunk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void exitWithErrorMessage(ptr msg) {
|
fn void exitWithErrorMessage(ptr msg) {
|
||||||
printf("error: %s", msg);
|
printf("error: %s", msg);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -515,8 +357,7 @@ fn void handleIncomingMessage(u8* message, u32 len, SocketAddress sender, i32 so
|
|||||||
|
|
||||||
printf("Logging in player: %s %d %s\n", MESSAGE_STRINGS[parsed.type], name_len, message + 7);
|
printf("Logging in player: %s %d %s\n", MESSAGE_STRINGS[parsed.type], name_len, message + 7);
|
||||||
} break;
|
} break;
|
||||||
case CommandKeepAlive:
|
case CommandKeepAlive: break;
|
||||||
break;
|
|
||||||
case CommandPayMortgage: {
|
case CommandPayMortgage: {
|
||||||
parsed.id = readU64FromBufferLE(message + msg_idx);
|
parsed.id = readU64FromBufferLE(message + msg_idx);
|
||||||
printf("paying off %lld\n", parsed.id);
|
printf("paying off %lld\n", parsed.id);
|
||||||
@@ -720,8 +561,10 @@ fn void* gameLoop(void* params) {
|
|||||||
u32 qty_traded = 0;
|
u32 qty_traded = 0;
|
||||||
u32 credit_value = 0;
|
u32 credit_value = 0;
|
||||||
if (is_buying_from_system) {
|
if (is_buying_from_system) {
|
||||||
u32 ship_space = MAX_u32;
|
u32 ship_space = account->ship.cu_m_fuel - account->ship.commodities[CommodityHydrogenFuel];
|
||||||
if (COMMODITIES[msg.commodity].unit == StorageUnitContainer) {
|
if (msg.commodity == CommodityOxygen) {
|
||||||
|
ship_space = account->ship.cu_m_o2 - account->ship.commodities[CommodityOxygen];
|
||||||
|
} else if (COMMODITIES[msg.commodity].unit == StorageUnitContainer) {
|
||||||
ship_space = account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship);
|
ship_space = account->ship.vacuum_cargo_slots - usedVacuumCargoSlots(account->ship);
|
||||||
}
|
}
|
||||||
for (u32 amount_to_buy = Min(msg.qty, total_available); amount_to_buy > 0; amount_to_buy--, total_available--, ship_space--) {
|
for (u32 amount_to_buy = Min(msg.qty, total_available); amount_to_buy > 0; amount_to_buy--, total_available--, ship_space--) {
|
||||||
@@ -858,12 +701,12 @@ fn void* gameLoop(void* params) {
|
|||||||
.remaining_mortgage = template.base_cost - STARTING_DOWN_PAYMENT,
|
.remaining_mortgage = template.base_cost - STARTING_DOWN_PAYMENT,
|
||||||
.interest_rate = calcInterestRate(template.base_cost, STARTING_DOWN_PAYMENT),
|
.interest_rate = calcInterestRate(template.base_cost, STARTING_DOWN_PAYMENT),
|
||||||
.credits = 10000.0,
|
.credits = 10000.0,
|
||||||
//.cu_m_fuel; // we are just saying you can buy as much fuel as you want
|
.cu_m_fuel = template.cu_m_fuel,
|
||||||
//.cu_m_o2; // we are just saying you can buy as much o2 as you want
|
.cu_m_o2 = template.cu_m_o2,
|
||||||
.id = account->id,
|
.id = account->id,
|
||||||
};
|
};
|
||||||
player_ship.commodities[CommodityHydrogenFuel] = 2000;
|
player_ship.commodities[CommodityHydrogenFuel] = player_ship.cu_m_fuel;
|
||||||
player_ship.commodities[CommodityOxygen] = 1000;
|
player_ship.commodities[CommodityOxygen] = player_ship.cu_m_o2;
|
||||||
account->ship = player_ship;
|
account->ship = player_ship;
|
||||||
printf("ship_type=%s, client_handle=%d, acct_id=%d\n", SHIP_TYPE_STRINGS[msg.byte], client_handle, account->id);
|
printf("ship_type=%s, client_handle=%d, acct_id=%d\n", SHIP_TYPE_STRINGS[msg.byte], client_handle, account->id);
|
||||||
u32 starting_system_idx = rand() % STAR_SYSTEM_COUNT;
|
u32 starting_system_idx = rand() % STAR_SYSTEM_COUNT;
|
||||||
@@ -933,12 +776,15 @@ fn void* gameLoop(void* params) {
|
|||||||
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
outgoingMessageQueuePush(state.network_send_queue, &outgoing_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} unlockMutex(&state.mutex); unlockMutex(&state.client_mutex);
|
} unlockMutex(&state.mutex); unlockMutex(&state.client_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.someone_won) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LaneSync();
|
LaneSync();
|
||||||
|
|
||||||
u32 player_count = 0;
|
u32 player_count = 0;
|
||||||
@@ -990,20 +836,28 @@ fn void* gameLoop(void* params) {
|
|||||||
acct->ship.ready_to_depart = false;
|
acct->ship.ready_to_depart = false;
|
||||||
acct->changed = true;
|
acct->changed = true;
|
||||||
|
|
||||||
// look for a winner + increase the mortgage from interest
|
// increase the mortgage from interest
|
||||||
if (!shipIsNull(&acct->ship)) {
|
if (!shipIsNull(&acct->ship)) {
|
||||||
if (acct->ship.remaining_mortgage == 0) {
|
if (acct->ship.remaining_mortgage > 0) {
|
||||||
state.winner_id = acct->id;
|
|
||||||
state.someone_won = true;
|
|
||||||
printf("someone WON!!! %d\n", i);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
acct->ship.remaining_mortgage += acct->ship.remaining_mortgage * (acct->ship.interest_rate / 100.0);
|
acct->ship.remaining_mortgage += acct->ship.remaining_mortgage * (acct->ship.interest_rate / 100.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO pay the mortgage payment
|
// look for a winner
|
||||||
|
Range1u64 ship_range = LaneRange(player_count);
|
||||||
|
for (u32 i = ship_range.min; i < ship_range.max; i++) {
|
||||||
|
Account* acct = &state.accounts[i];
|
||||||
|
if (!shipIsNull(&acct->ship)) {
|
||||||
|
if (acct->ship.remaining_mortgage == 0) {
|
||||||
|
state.winner_id = acct->id;
|
||||||
|
state.someone_won = true;
|
||||||
|
printf("someone WON!!! %d\n", i);
|
||||||
|
acct->changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. scratch cleanup
|
// 3. scratch cleanup
|
||||||
@@ -1209,6 +1063,9 @@ i32 main(i32 argc, ptr argv[]) {
|
|||||||
osThreadJoin(game_threads[i], MAX_u64);
|
osThreadJoin(game_threads[i], MAX_u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osThreadJoin(recv_thread, MAX_u64);
|
||||||
|
osThreadJoin(send_thread, MAX_u64);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-14
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
///// #define some game-tunable constants
|
///// #define some game-tunable constants
|
||||||
#define STARTING_DOWN_PAYMENT (10000)
|
#define STARTING_DOWN_PAYMENT (10000)
|
||||||
#define SHIP_DETAIL_COUNT (8)
|
#define SHIP_DETAIL_COUNT (7)
|
||||||
#define STAR_SYSTEM_COUNT (40)
|
#define STAR_SYSTEM_COUNT (40)
|
||||||
#define MAP_WIDTH (36)
|
#define MAP_WIDTH (36)
|
||||||
#define MAP_HEIGHT (12)
|
#define MAP_HEIGHT (12)
|
||||||
@@ -34,14 +34,14 @@ typedef enum ShipType {
|
|||||||
ShipSparrow,
|
ShipSparrow,
|
||||||
ShipDart,
|
ShipDart,
|
||||||
ShipHaulerPrimeZ1,
|
ShipHaulerPrimeZ1,
|
||||||
ShipNX400,
|
// ShipNX400,
|
||||||
ShipType_Count,
|
ShipType_Count,
|
||||||
} ShipType;
|
} ShipType;
|
||||||
global str SHIP_TYPE_STRINGS[] = {
|
global str SHIP_TYPE_STRINGS[] = {
|
||||||
"Sparrow",
|
"Sparrow",
|
||||||
"Dart",
|
"Dart",
|
||||||
"Hauler-Prime Z-1",
|
"Hauler-Prime Z-1",
|
||||||
"NX-400",
|
// "NX-400",
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct ShipTemplate {
|
typedef struct ShipTemplate {
|
||||||
@@ -54,33 +54,39 @@ typedef struct ShipTemplate {
|
|||||||
u16 passenger_amenities_flags;
|
u16 passenger_amenities_flags;
|
||||||
u16 smugglers_hold_cu_m;
|
u16 smugglers_hold_cu_m;
|
||||||
u32 base_cost;
|
u32 base_cost;
|
||||||
|
u32 cu_m_fuel;
|
||||||
|
u32 cu_m_o2;
|
||||||
} ShipTemplate;
|
} ShipTemplate;
|
||||||
|
|
||||||
global ShipTemplate SHIPS[] = {
|
global ShipTemplate SHIPS[] = {
|
||||||
{
|
{
|
||||||
.type = ShipSparrow, .drive_efficiency = 1, .life_support_efficiency = 2,
|
.type = ShipSparrow, .drive_efficiency = 10, .life_support_efficiency = 2,
|
||||||
.vacuum_cargo_slots = 5, .climate_cargo_slots = 0, .passenger_berths = 0,
|
.vacuum_cargo_slots = 5, .climate_cargo_slots = 0, .passenger_berths = 0,
|
||||||
.passenger_amenities_flags = 0,
|
.passenger_amenities_flags = 0,
|
||||||
.smugglers_hold_cu_m = 1, .base_cost = 100000,
|
.smugglers_hold_cu_m = 1, .base_cost = 100000,
|
||||||
|
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.type = ShipDart, .drive_efficiency = 12, .life_support_efficiency = 4,
|
.type = ShipDart, .drive_efficiency = 70, .life_support_efficiency = 4,
|
||||||
.vacuum_cargo_slots = 9, .climate_cargo_slots = 1, .passenger_berths = 1,
|
.vacuum_cargo_slots = 10, .climate_cargo_slots = 1, .passenger_berths = 1,
|
||||||
.passenger_amenities_flags = 0,
|
.passenger_amenities_flags = 0,
|
||||||
.smugglers_hold_cu_m = 0, .base_cost = 150000,
|
.smugglers_hold_cu_m = 0, .base_cost = 150000,
|
||||||
|
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.type = ShipHaulerPrimeZ1, .drive_efficiency = 3, .life_support_efficiency = 3,
|
.type = ShipHaulerPrimeZ1, .drive_efficiency = 50, .life_support_efficiency = 3,
|
||||||
.vacuum_cargo_slots = 25, .climate_cargo_slots = 5, .passenger_berths = 0,
|
.vacuum_cargo_slots = 100, .climate_cargo_slots = 5, .passenger_berths = 0,
|
||||||
.passenger_amenities_flags = 0,
|
.passenger_amenities_flags = 0,
|
||||||
.smugglers_hold_cu_m = 0, .base_cost = 250000,
|
.smugglers_hold_cu_m = 0, .base_cost = 250000,
|
||||||
|
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||||
},
|
},
|
||||||
{
|
/* {
|
||||||
.type = ShipNX400, .drive_efficiency = 6, .life_support_efficiency = 8,
|
.type = ShipNX400, .drive_efficiency = 6, .life_support_efficiency = 8,
|
||||||
.vacuum_cargo_slots = 5, .climate_cargo_slots = 5, .passenger_berths = 5,
|
.vacuum_cargo_slots = 5, .climate_cargo_slots = 5, .passenger_berths = 5,
|
||||||
.passenger_amenities_flags = 0,
|
.passenger_amenities_flags = 0,
|
||||||
.smugglers_hold_cu_m = 0, .base_cost = 350000,
|
.smugglers_hold_cu_m = 0, .base_cost = 350000,
|
||||||
},
|
.cu_m_fuel = 2000, .cu_m_o2 = 1000,
|
||||||
|
},*/
|
||||||
};
|
};
|
||||||
|
|
||||||
fn f32 calcInterestRate(u32 cost, u32 down_payment) {
|
fn f32 calcInterestRate(u32 cost, u32 down_payment) {
|
||||||
@@ -93,10 +99,10 @@ global FieldDescriptor SHIP_FIELDS[SHIP_DETAIL_COUNT] = {
|
|||||||
{ "Cost", FieldTypeU32, offsetof(ShipTemplate, base_cost), 8 },
|
{ "Cost", FieldTypeU32, offsetof(ShipTemplate, base_cost), 8 },
|
||||||
{ "DriveEff", FieldTypeU8, offsetof(ShipTemplate, drive_efficiency), 8 },
|
{ "DriveEff", FieldTypeU8, offsetof(ShipTemplate, drive_efficiency), 8 },
|
||||||
{ "LifeSupp", FieldTypeU8, offsetof(ShipTemplate, life_support_efficiency), 8 },
|
{ "LifeSupp", FieldTypeU8, offsetof(ShipTemplate, life_support_efficiency), 8 },
|
||||||
{ "V.Cargo", FieldTypeU16, offsetof(ShipTemplate, vacuum_cargo_slots), 7 },
|
{ "Cargo", FieldTypeU16, offsetof(ShipTemplate, vacuum_cargo_slots), 7 },
|
||||||
{ "C.Cargo", FieldTypeU16, offsetof(ShipTemplate, climate_cargo_slots), 7 },
|
{ "FuelTank", FieldTypeU32, offsetof(ShipTemplate, cu_m_fuel), 8 },
|
||||||
{ "Passengers", FieldTypeU16, offsetof(ShipTemplate, passenger_berths), 10 },
|
{ "O2 Tank", FieldTypeU32, offsetof(ShipTemplate, cu_m_o2), 8 },
|
||||||
{ "SmugglersHold", FieldTypeU16, offsetof(ShipTemplate, smugglers_hold_cu_m), 13 },
|
// { "SmugglersHold", FieldTypeU16, offsetof(ShipTemplate, smugglers_hold_cu_m), 13 },
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum EquipmentType {
|
typedef enum EquipmentType {
|
||||||
|
|||||||
Reference in New Issue
Block a user