what can BASIC do that GM can't?
GM script language omitted a few BASIC features, but it also added GM-specific things like dialogs and prompts.
Notably, GM script language does not allow arithmetic expressions involving more than two terms or factors, so e.g. these two lines
will work, but these won't:
X = 1 + 2 + 3
X = 1 * 2 * 3
Furthermore, GM scripting does not support parentheses.
Bleh, I wrote a dynamic C array and wouldn't advise using realloc. There's a chance of losing data.
No theres not, unless:
a) You're doing it wrong.
b) Theres not enough RAM available on heap; this will however return an error which you can deal with.
I've used realloc to create a resizing binary heap which is currently being used every day on an extremely active business application -- never had a single error or amnesic episode. Also there are no std library c/c++ functions that will have a chance of not working properly. In fact on the official C++ website:
"The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved."
The memory is GUARANTEED to be preserved.
Here is some example code of correct usage I wrote for the above mentioned application:
//check if the heap is full
if (h->index >= h->blockSize) //if the index is the block size, it is pointing outside the block and the block is full
{
//if the heap is at capacity, return with error
if (h->blockSize >= MAXELEMENTS){
puts("Error: The heap has reached its maximum size");
return;
}
//otherwise resize the heap
// try to reallocate
printf("%d\\n", h->index);
void* temp = realloc(h->block, sizeof(ELEMENT)*h->blockSize+BLOCKINCREMENT);
if (temp == NULL){ //if reallocate fails, report the error, then end the function
puts("Could not realloc memory");
return;
}
//if reallocate is successful, update state variables
h->blockSize += BLOCKINCREMENT; //incremenet the size
h->block = temp; //get the new block
}
Here's a mutable array I made in C.
//
// MutableArray.c
// Avisaria Collision Demo
//
// Created by Matthew French on 9/24/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import <stdio.h>
#import <stdlib.h>
typedef struct MutableArray MutableArray;
static inline MutableArray* MutableArrayMake();
static inline void MutableArrayAdd(MutableArray* m,void* object);
static inline void MutableArrayRemove(MutableArray* m,void* object);
static inline void MutableArrayRemoveAllObjects(MutableArray* m);
static inline int MutableArrayIndexOfObject(MutableArray* m,void* object);
static inline void* MutableArrayObjectAtIndex(MutableArray* m,int index);
static inline void MutableArrayFree(MutableArray* m);
struct MutableArray {
int count;
void** objects;
};
static inline MutableArray* MutableArrayMake() {
MutableArray* m = (MutableArray*)malloc(sizeof(MutableArray));
m->count = 0;
m->objects = NULL;
return m;
}
static inline void MutableArrayAdd(MutableArray* m,void* object) {
m->count += 1;
void** new = (void**)malloc(m->count*sizeof(void*));
if (m->objects!=NULL) {
for (int i = 0; i < m->count-1; i++) {
new[i] = m->objects[i];
}
free(m->objects);
m->objects = NULL;
}
new[m->count-1] = object;
m->objects = new;
}
static inline void MutableArrayRemove(MutableArray* m,void* object) {
int n = 0;
for (int i = 0; i < m->count; i++) {
if (m->objects[i] == object) {
n++;
}
}
int r = 0;
void** new = (void**)malloc((m->count - n)*sizeof(void*));
for (int i = 0; i < m->count; i++) {
if (m->objects[i] != object) {
new[i-r] = m->objects[i];
} else {
r ++;
}
}
free(m->objects);
m->objects = new;
m->count -= n;
}
static inline void MutableArrayRemoveAllObjects(MutableArray* m) {
m->count = 0;
free(m->objects);
m->objects = NULL;
}
static inline int MutableArrayIndexOfObject(MutableArray* m,void* object) {
for (int i = 0; i < m->count; i++) {
if (m->objects[i] == object) {
return i;
}
}
return -1;
}
static inline void* MutableArrayObjectAtIndex(MutableArray* m,int index) {
return m->objects[index];
}
static inline void MutableArrayFree(MutableArray* m) {
if (m->count > 0) {
free(m->objects);
}
free(m);
}
Awesome, I'll have to look at it more in depth in the morning.
It almost looks C++ish.
No, this would be C++ish:
Also @Gan: Defining your functions as static is redundant since you have not static variables in them. The only thing its going to do its make it harder for a compiler to optimize your code. In addition your free function and the remove all function have a memory leak. Also you should never use "import", its depreciated. Not to be rude, but what is the point of this? All the operations are O(n) because you re-create the array every time. This means your data structure is extremely slow and thus useless compared to a linked list, or a normal vector, (both of which have add and remove as O(1)) for example.
Example of memory leak:
//
// MutableArray.c
// Avisaria Collision Demo
//
// Created by Matthew French on 9/24/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
typedef struct MutableArray MutableArray;
static inline MutableArray* MutableArrayMake();
static inline void MutableArrayAdd(MutableArray* m,void* object);
static inline void MutableArrayRemove(MutableArray* m,void* object);
static inline void MutableArrayRemoveAllObjects(MutableArray* m);
static inline int MutableArrayIndexOfObject(MutableArray* m,void* object);
static inline void* MutableArrayObjectAtIndex(MutableArray* m,int index);
static inline void MutableArrayFree(MutableArray* m);
struct MutableArray {
int count;
void** objects;
};
static inline MutableArray* MutableArrayMake() {
MutableArray* m = (MutableArray*)malloc(sizeof(MutableArray));
m->count = 0;
m->objects = NULL;
return m;
}
static inline void MutableArrayAdd(MutableArray* m,void* object) {
m->count += 1;
void** new = (void**)malloc(m->count*sizeof(void*));
if (m->objects!=NULL) {
int i;
for ( i = 0; i < m->count-1; i++) {
new[i] = m->objects[i];
}
free(m->objects);
m->objects = NULL;
}
new[m->count-1] = object;
m->objects = new;
}
static inline void MutableArrayRemove(MutableArray* m,void* object) {
int n = 0;
int i;
for (i = 0; i < m->count; i++) {
if (m->objects[i] == object) {
n++;
}
}
int r = 0;
void** new = (void**)malloc((m->count - n)*sizeof(void*));
for (i = 0; i < m->count; i++) {
if (m->objects[i] != object) {
new[i-r] = m->objects[i];
} else {
r ++;
}
}
free(m->objects);
m->objects = new;
m->count -= n;
}
static inline void MutableArrayRemoveAllObjects(MutableArray* m) {
m->count = 0;
free(m->objects);
m->objects = NULL;
}
static inline int MutableArrayIndexOfObject(MutableArray* m,void* object) {
int i;
for (i = 0; i < m->count; i++) {
if (m->objects[i] == object) {
return i;
}
}
return -1;
}
static inline void* MutableArrayObjectAtIndex(MutableArray* m,int index) {
return m->objects[index];
}
static inline void MutableArrayFree(MutableArray* m) {
if (m->count > 0) {
free(m->objects);
}
free(m);
}
void print(MutableArray* m)
{
int i;
for (i = 0; i < m->count; i++)
puts((char*)m->objects[i]);
}
int main()
{
MutableArray* m;
while (getchar() != 'z') {
m = MutableArrayMake();
int i;
for(i = 0; i < 10000; i++) {
MutableArrayAdd(m, malloc(100));
MutableArrayAdd(m, malloc(100));
MutableArrayAdd(m, malloc(100));
}
MutableArrayRemoveAllObjects(m);
MutableArrayFree(m);
}
return 0;
}
Run it, and keep pressing return. Watch the memory usage go up and up. This is probably because you are freeing the objects pointer, but not everything it points to (since its basically an array of other pointers). You could fix this with a simple:
int i;
for (i = 0; i < m->count; i++)
free(m->objects[i]);
You do realize it would be much faster if you didn't have to iterate over the entire array whenever you added or removed something right?
Yeah probs, though a linked list would up the complexity. It'd hafta be wrapped to work just like a mutable array if I were to use one.
Imagine tryin to get a single object at some index, it'd have to iterate through quite a few. I'm not sure it'd be faster when I have a ton of collision tests, targeting and AI behaviors. Though adding a object certainly would be faster.
Then again so far I only add objects at the beginning, haven't tested removing and adding sheep during the game.
It'd take some testing to see if it's worth it.
As for the CPU usage, that's a good point. I'm gonna have to test it again to figure out why it does that.
As for the import, I got that in there cause I'm mincing C and Obj-C. Even though it probably makes no difference...
Aha! I knew it looked a bit more object-oriented than the C I'm used too!
As for it being slow... well it seems to be much faster than an NSMutableArray. I also don't like linked lists, just preference.
I like linked lists myself, but I can't find a practical usage for them something else doesn't already do faster :/
So not to change the subject or anything, but I 1/2 finished The function that I've been working on forever. It works fine except it's only accurate to a tenth, and freaks out, if it's given a string without a decimal in it. (which is why I made my own realloc commmand... still working on that)
#define DIGIT (c[array] - 48)
#define SLOTS (numberofsections(string))
#define AZERO (numberofsectionsabovezero(string))
#define BZERO (numberofsectionsbelowzero(string))
#define RESET place = -array + AZERO
float stringtonumber(char string[]) {
float f = 0;
int array, place;
float exponent = 1;
for (array = 0; array >= -BZERO && array < SLOTS ; array++) {
place = RESET;
if (string[array] == '.')
{continue;}
if (place > 0)
{
for (place = RESET, exponent = 1; place != 1; --place)
{exponent *= 10;}
}
else if (place < 0)
{
for (place = RESET, exponent = 1; place != 0; ++place)//else is important
{exponent /= 10;}
}
f = f + DIGIT * exponent; //add to final
printf("f evaluated to: %f\\n\\n",f);
}
// divide to move up decimal point by # of sections under 0
return(f);
}
I'm quite proud of it ;D
I've spent half a month working on it.