Code review request

anyone experienced in this language that is super bored and wouldn’t mind looking at my project so far? What I have now is pretty much the extent of my programming knowledge coming from c# and OOP, having not used c or Odin up until a few weeks ago. I’m curious if there are any obvious mistakes or bad practices that I need to fix before I start trying to learn some more advanced Odin stuff. Coming from an OOP language I’m not sure if I am digging myself a path to spaghetti code. As of right now everything is working as I expect it to

Write it in a way thats readable to you. You might want to research the difference between structure of arrays and array of structures. If I have some procedures that are tied to some system like entities then I like to name them starting with entity for example entity_delete, entity_create then when I start typing entity the autocomplete is showing me all procedures related to it.

Great start. I’m a newbie into Odin as well.

A [dynamic]Entity is a heap block plus a length and capacity and &entities[3] is a raw address inside that block.

When append exceeds capacity Odin re-allocates a bigger block, copies the elements over and frees the old block. The dynamic array’s internal data pointer updates, while any saved ^Entity does not auto-update and keeps pointing at a now freed block. Reading through the pointer will most likely give you a zero-value (and more unlikely - stale data or a crash).

For example:

entities: [dynamic]Entity // cap 8, len 8, data at, say, 0x1000
// ... add 8 entities using append()
turn = &entities[0]       // saves pointer to data at 0x1000
// ... will add one more and Odin will have to re-allocate, since capacity was only for 8
append(&entities, hill)   // array grows and the new block goes to, say, 0x5000 and the old is freed
turn.health -= 1          // writes to freed memory at 0x1000

I hope this makes sense.

Within your in_editing_mode branch, when you call add_entity(new_entity) it calls append(&entities, new_entity) and turn and others like it hold addresses from before that append, which will no longer be correct if append reallocates the dynamic array.

All is fine while you have 5 entities, which fit in the initial capacity, but once you exceed that capacity and append a new entity - Odin will re-allocate new memory and copy over the old data.

When you call unordered_remove(&entities, i) Odin moves the last element into slot i, which will make every pointer which pointed at the old last element now refer to freed memory.

I would suggest you use an index instead of an address and I can see you have // turn: int and further down: turn_index := 0. I would use the latter. Indexes are stable across re-allocations.

Alternatively you can define entities: [MAX_ENTITIES]Entity plus a count. which would be easiest for 10x10 grid, and a fixed array never re-allocates, so plain indices would be enough.