Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

259 lines
6.4 KiB
C++

#pragma warning (disable:4786)
#include "ai nnet.hpp"
#include <assert.h>
#include <math.h>
Back_Layer::Back_Layer (int nodes,int ninputs,bool first)
{
Create (nodes,ninputs,first);
}
void Back_Layer::Create (int nodes,int ninputs,bool first)
{
int i,j;
double temp;
next = NULL;
prev = NULL;
num_nodes = nodes;
next = prev = NULL;
thenodes = (Back_Node *) calloc (sizeof (Back_Node),num_nodes);
num_inputs = ninputs;
inputs = (double *) calloc (sizeof (double),num_inputs);
outputs = (double *) calloc (sizeof (double),num_nodes);
errors = (double *) calloc (sizeof (double),num_nodes);
for (i=0;i<num_inputs;i++)
{ inputs[i] = 0;
}
for (i=0;i<num_nodes;i++)
{
thenodes[i].weights = (double *) calloc (sizeof (double),num_inputs);
thenodes[i].deltas = (double *) calloc (sizeof (double),num_inputs);
for (j=0;j<num_inputs;j++)
{
thenodes[i].deltas[j] = 0.0;
if (!first)
{
temp = rand ();
temp /= ((double) RAND_MAX);
temp = temp - 0.5;
thenodes[i].weights[j] = temp;
}
else
{
thenodes[i].weights[j] = 1.0;
}
}
}
}
Back_Layer::~Back_Layer (void)
{
Destroy ();
}
void Back_Layer::Destroy (void)
{
int i;
for (i=0;i<num_nodes;i++)
{
free (thenodes[i].weights);
free (thenodes[i].deltas);
}
free (thenodes);
free (inputs);
free (errors);
}
void Back_Layer::propagate_forward (void)
{
int i,j;
double sum;
assert ((!next) || (num_nodes == next->num_inputs));
for (i=0;i<num_nodes;i++)
{
if (!prev)
outputs[i] = inputs[i];
else
{
sum = 0.0;
for (j=0;j<num_inputs;j++)
{ sum += (inputs[j]*thenodes[i].weights[j]);
}
outputs[i] = 1.0/(1.0+exp (-1.0*sum));
}
if (next)
next->inputs[i] = outputs[i];
}
}
void Back_Layer::propagate_error (void)
{
int i,j;
assert (next);
for (i=0;i<num_nodes;i++)
{
errors[i] = 0;
for (j=0;j<next->num_nodes;j++)
{
errors[i] += (next->errors[j]*next->thenodes[j].weights[i]);
}
errors[i] *= (outputs[i] * (1.0-outputs[i]));
}
}
void Back_Network::correct (bool finetune)
{
compute_error (finetune);
propagate_error ();
adjust_weights ();
}
void Back_Network::adjust_weights (void)
{
int i,j,k;
double tochange;
for (i=1;i<num_layers;i++)
{
for (j=0;j<thelayers[i].num_nodes;j++)
{
for (k=0;k<thelayers[i].num_inputs;k++)
{
tochange = thelayers[i].inputs[k]*eta*thelayers[i].errors[j];
tochange += (alpha*thelayers[i].thenodes[j].deltas[k]);
thelayers[i].thenodes[j].deltas[k] = tochange;
thelayers[i].thenodes[j].weights[k] += tochange;
}
}
}
}
void Back_Network::propagate_error (void)
{
int i;
for (i=(num_layers-2);i>=0;i--)
{
thelayers[i].propagate_error ();
}
}
void Back_Network::compute_error (bool finetune)
{
int i;
for (i=0;i<num_outputs;i++)
{
if (!finetune)
thelayers[num_layers-1].errors[i] = (wanted_output[i] - output[i]);
else
{
thelayers[num_layers-1].errors[i] = output[i];
thelayers[num_layers-1].errors[i] *= (1.0 - output[i]);
thelayers[num_layers-1].errors[i] *= (wanted_output[i] - output[i]);
}
}
}
// This function does not work, the net will not stabalize to a solution
void Back_Network::Learn (bool iscorrect,bool finetune,double error)
{
int i;
double *temp;
if (iscorrect)
{
temp = get_answer ();
for (i=0;i<thelayers[num_layers-1].num_nodes;i++)
{
if (temp[i] > 0.5)
wanted_output[i] = 1.0;
else
wanted_output[i] = 0.0;
}
correct (finetune);
}
else
{
temp = get_answer ();
for (i=0;i<thelayers[num_layers-1].num_nodes;i++)
{
if ((rand ()%100) < error)
{
if (temp[i] > 0.5)
wanted_output[i] = 1.0;
else
wanted_output[i] = 0.0;
}
else
{
if ((rand ()&0x01))
wanted_output[i] = 1.0;
else
wanted_output[i] = 0.0;
}
}
correct (finetune);
}
}
Back_Network::Back_Network (int layers,int *num_nodes,double neta,double nalpha)
{
int i;
eta = neta;
alpha = nalpha;
num_inputs = num_nodes[0];
num_outputs = num_nodes[layers-1];
input = (double *) calloc (sizeof (double),num_inputs);
output = (double *) calloc (sizeof (double),num_outputs);
wanted_output = (double *) calloc (sizeof (double),num_outputs);
num_layers = layers;
thelayers = (Back_Layer *) calloc (sizeof (Back_Layer),layers);
thelayers[0].Create (num_nodes[0],num_nodes[0],true);
thelayers[0].next = &(thelayers[1]);
for (i=1;i<layers;i++)
{
thelayers[i].Create (num_nodes[i],num_nodes[i-1],false);
thelayers[i].prev = &(thelayers[i-1]);
thelayers[i].next = &(thelayers[i+1]);
}
thelayers[layers-1].next = NULL;
}
Back_Network::~Back_Network (void)
{
int i;
for (i=0;i<num_layers;i++)
{
thelayers[i].Destroy ();
}
free (thelayers);
}
void Back_Network::propagate_forward (double *ninputs)
{
int i;
for (i=0;i<num_inputs;i++)
{
input[i] = ninputs[i];
thelayers[0].inputs[i] = input[i];
}
for (i=0;i<num_layers;i++)
{
if (i != (num_layers-1))
assert (thelayers[i].num_nodes == thelayers[i+1].num_inputs);
thelayers[i].propagate_forward ();
}
for (i=0;i<num_outputs;i++)
{
output[i] = thelayers[num_layers-1].outputs[i];
}
}