1 /*
2 * Copyright (C) 2004 Ivo Danihelka (ivo@danihelka.net)
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9 #include "ModelFactory.h"
10
11 #include "V2.h"
12 #include "Unit.h"
13 #include "Shape.h"
14 #include "LogicException.h"
15 #include "StringTool.h"
16
17 //-----------------------------------------------------------------
18 /**
19 * Add model at scene.
20 * @param kind kind of item (e.g. "fish_big", "item_light", ...)
21 * @param loc placement location
22 * @param shape see Shape for format
23 * @return model
24 *
25 * @throws LogicException for unknown kind
26 * @throws LayoutException when shape or location is bad
27 */
28 Cube *
createModel(const std::string & kind,const V2 & loc,const std::string & shape)29 ModelFactory::createModel(const std::string &kind, const V2 &loc,
30 const std::string &shape)
31 {
32 if (StringTool::startsWith(kind, "output_")) {
33 return createOutputItem(kind, loc, shape);
34 }
35
36 Cube::eWeight weight;
37 Cube::eWeight power;
38 bool alive;
39 createParams(kind, &weight, &power, &alive);
40
41 Shape *newShape = new Shape(shape);
42 Cube *model = new Cube(loc,
43 weight, power, alive, newShape);
44
45 return model;
46 }
47 //-----------------------------------------------------------------
48 /**
49 * Determine object params.
50 * @throws LogicException when kind is unkown
51 */
52 void
createParams(const std::string & kind,Cube::eWeight * out_weight,Cube::eWeight * out_power,bool * out_alive)53 ModelFactory::createParams(const std::string &kind,
54 Cube::eWeight *out_weight, Cube::eWeight *out_power, bool *out_alive)
55 {
56 if ("fish_small" == kind) {
57 *out_weight = Cube::LIGHT;
58 *out_power = Cube::LIGHT;
59 *out_alive = true;
60 }
61 else if ("fish_big" == kind) {
62 *out_weight = Cube::LIGHT;
63 *out_power = Cube::HEAVY;
64 *out_alive = true;
65 }
66 else if (StringTool::startsWith(kind, "fish_extra")) {
67 *out_weight = Cube::LIGHT;
68 *out_power = Cube::LIGHT;
69 *out_alive = true;
70 }
71 else if (StringTool::startsWith(kind, "fish_EXTRA")) {
72 *out_weight = Cube::LIGHT;
73 *out_power = Cube::HEAVY;
74 *out_alive = true;
75 }
76 else {
77 *out_power = Cube::NONE;
78 *out_alive = false;
79 if ("item_light" == kind) {
80 *out_weight = Cube::LIGHT;
81 }
82 else if ("item_heavy" == kind) {
83 *out_weight = Cube::HEAVY;
84 }
85 else if ("item_fixed" == kind) {
86 *out_weight = Cube::FIXED;
87 }
88 else {
89 throw LogicException(ExInfo("unknown model kind")
90 .addInfo("kind", kind));
91 }
92 }
93 }
94 //-----------------------------------------------------------------
95 /**
96 * Create unit for driveable fish.
97 * @param kind kind of item (e.g. "fish_big", "item_light", ...)
98 * @return new unit or NULL
99 */
100 Unit *
createUnit(const std::string & kind)101 ModelFactory::createUnit(const std::string &kind)
102 {
103 Unit *result = NULL;
104 if ("fish_small" == kind) {
105 KeyControl smallfish;
106 smallfish.setUp(SDLK_i);
107 smallfish.setDown(SDLK_k);
108 smallfish.setLeft(SDLK_j);
109 smallfish.setRight(SDLK_l);
110 result = new Unit(smallfish, ControlSym('u', 'd', 'l', 'r'), true);
111 }
112 else if ("fish_big" == kind) {
113 KeyControl bigfish;
114 bigfish.setUp(SDLK_w);
115 bigfish.setDown(SDLK_s);
116 bigfish.setLeft(SDLK_a);
117 bigfish.setRight(SDLK_d);
118 result = new Unit(bigfish, ControlSym('U', 'D', 'L', 'R'));
119 }
120 else if (StringTool::startsWith(kind, "fish_extra") ||
121 StringTool::startsWith(kind, "fish_EXTRA"))
122 {
123 KeyControl extrafish;
124 extrafish.setUp(SDLK_LAST);
125 extrafish.setDown(SDLK_LAST);
126 extrafish.setLeft(SDLK_LAST);
127 extrafish.setRight(SDLK_LAST);
128 result = new Unit(extrafish, parseExtraControlSym(kind));
129 }
130 return result;
131 }
132 //-----------------------------------------------------------------
133 /**
134 * Create special model, which will be used for outher space.
135 * NOTE: hack border around field
136 */
137 Cube *
createBorder()138 ModelFactory::createBorder()
139 {
140 Cube *border = new Cube(V2(-1,-1), Cube::FIXED, Cube::NONE, false,
141 new Shape("X\n"));
142 return border;
143 }
144 //-----------------------------------------------------------------
145 /**
146 * Create one way output out of room.
147 * @throws LogicException when output_DIR is not known
148 */
149 Cube *
createOutputItem(const std::string & kind,const V2 & loc,const std::string & shape)150 ModelFactory::createOutputItem(const std::string &kind, const V2 &loc,
151 const std::string &shape)
152 {
153 Dir::eDir outDir = Dir::DIR_NO;
154 if ("output_left" == kind) {
155 outDir = Dir::DIR_LEFT;
156 }
157 else if ("output_right" == kind) {
158 outDir = Dir::DIR_RIGHT;
159 }
160 else if ("output_up" == kind) {
161 outDir = Dir::DIR_UP;
162 }
163 else if ("output_down" == kind) {
164 outDir = Dir::DIR_DOWN;
165 }
166 else {
167 throw LogicException(ExInfo("unknown border dir")
168 .addInfo("kind", kind));
169 }
170
171 Cube *model = new Cube(loc,
172 Cube::FIXED, Cube::NONE, false, new Shape(shape));
173 model->setOutDir(outDir);
174 return model;
175 }
176 //-----------------------------------------------------------------
177 /**
178 * Define controls symbols for extra fish.
179 * Format: "fish_extra-UDLR"
180 * @throws LogicException when symbols are not specified
181 */
182 ControlSym
parseExtraControlSym(const std::string & kind)183 ModelFactory::parseExtraControlSym(const std::string &kind)
184 {
185 static const std::string PREFIX = "fish_extra-";
186 if (kind.size() != PREFIX.size() + 4) {
187 throw LogicException(ExInfo("you must specify control symbols")
188 .addInfo("kind", kind));
189 }
190
191 char up = kind[PREFIX.size()];
192 char down = kind[PREFIX.size() + 1];
193 char left = kind[PREFIX.size() + 2];
194 char right = kind[PREFIX.size() + 3];
195 return ControlSym(up, down, left, right);
196 }
197
198