--- /dev/null
+#ifndef IMATERIASOURCE_H
+# define IMATERIASOURCE_H
+
+class IMateriaSource
+{
+ public:
+ virtual ~IMateriaSource() {}
+
+ virtual void leanMateria(AMateria *) = 0;
+ virtual AMateria *createMateria(const std::string &type) = 0;
+};
+
+#endif // IMATERIASOURCE_H
--- /dev/null
+#include "MateriaSource.h"
+
+MateriaSource::MateriaSource()
+ : m_num_known(0)
+{
+ for (size_t i(0); i < max_known; ++i)
+ m_known_materia[i] = NULL;
+}
+
+MateriaSource::MateriaSource(const MateriaSource &other)
+ : m_num_known(0)
+{
+ *this = other;
+}
+
+MateriaSource::~MateriaSource()
+{
+ deleteKnown();
+}
+
+void MateriaSource::deleteKnown()
+{
+ for (; m_num_know > 0;)
+ delete m_known_materia[--m_num_known];
+}
+
+MateriaSource &MateriaSource::operator=(const MateriaSource &other)
+{
+ deleteKnown();
+ for (; m_num_known < other.m_num_known; ++m_num_known)
+ m_known_materia[m_num_known] = other.m_known_materia[m_num_known]->clone();
+}
+
+void MateriaSource::learnMateria(AMateria *materia)
+{
+ if (m_num_known == max_known)
+ return ;
+ m_known_materia[m_num_known] = materia->clone();
+ ++m_num_known;
+}
+
+AMateria *MateriaSource::createMateria(const std::string &type)
+{
+ for (size_t i(0); i < m_num_known; ++i)
+ if (m_known_materia[i] == type)
+ return (m_known_materia[i]->clone());
+ return (NULL);
+}
--- /dev/null
+#ifndef MATERIASOURCE_H
+# define MATERIASOURCE_H
+
+# include "AMateria.h"
+# include "IMateriaSource.h"
+
+class MateriaSource : IMateriaSource
+{
+ private:
+ MateriaSource &operator=(const MateriaSource &other);
+
+ static const size_t max_known = 4;
+
+ AMateria *m_known_materia[max_known];
+ size_t m_num_known;
+
+ public:
+ MateriaSource();
+ MateriaSource(const MateriaSource &other);
+ ~MateriaSource();
+
+ void learnMateria(AMateria *materia);
+ AMateria *createMateria(const std::string &type);
+};
+
+#endif // MATERIASOURCE_H